|
|
Comments and Discussions
|
|
 |

|
this is an example exactly as i want, thank you.
|
|
|
|

|
Thank you very much .Only you can solve my hand problom
|
|
|
|
|
|

|
Great article. Can't find any simpler example of ReadDirectoryChanges anywhere.
|
|
|
|
|

|
Actually no, I disagree on one count only.
The example is good, but fails to take into account that the buffer returned is populated with an array of changes. not just one - the code does not show iterating over the list of objects.
If there are no objections I will paste just the code changes in here:
FILE_NOTIFY_INFORMATION *pRecord = Buffer;
do
{
switch(pRecord->Action)
{
case FILE_ACTION_ADDED: helper_txt = "The file was added to the directory"; break;
case FILE_ACTION_REMOVED: helper_txt = "The file was removed from the directory"; break;
case FILE_ACTION_MODIFIED: helper_txt = "The file was modified. This can be a change in the time stamp or attributes."; break;
case FILE_ACTION_RENAMED_OLD_NAME: helper_txt = "The file was renamed and this is the old name."; break;
case FILE_ACTION_RENAMED_NEW_NAME: helper_txt = "The file was renamed and this is the new name."; break;
}
m_Sec.Lock();
int item = pList1->InsertItem(pList1->GetItemCount(), CString(pRecord->FileName).Left(pRecord->FileNameLength / 2) + " - " + helper_txt );
pList1->SetItemText(item, 1, tm.Format("%Y/%m/%d/ - %H:%M:%S"));
m_Sec.Unlock();
if (0== pRecord->NextEntryOffset)
break;
// point to next record in array
pRecord = (FILE_NOTIFY_INFORMATION *)(&((unsigned char*)Buffer)[pRecord->NextEntryOffset]);
} while (TRUE);
I have however found that the watchers seem to be locking changes on the actual directory opened. I found the case for this, is in the way the directory is opened before watching - will prevent anyone from adding folders or files, simple to fix: add
FILE_SHARE_WRITE
to the open flags when opening the directory handle
Enjoy
Conrad -
The world waits for you to stick your neck out, it's not easy. But once you actually stand up, you do get noticed.
http://www.plcsimulator.org/
|
|
|
|

|
Hi, Nice article.
I just have a little question. Is it possible to know the new path of a file which has been moved ? For example: if i have this directory "C:\TestFileSpy\" and this file "C:\TestFileSpy\Temp.txt", then i move "Temp.txt" to my desktop. how can i get the new path ( "C:\Users\Propietario\Desktop\Temp.txt" ) ?
Thanks,
Fernando.
|
|
|
|

|
Here's how I do it:
When FILE_ACTION_REMOVED is detected, call ReadDirectoryChangesW again.
If the very next notification is FILE_ACTION_ADDED then that is the new path location.
|
|
|
|

|
When I try to compile the code iget the following link error
msvcrtd.lib(crtexew.obj) : error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartup
What am I doing wong?
Thanks
John
|
|
|
|

|
For anyone who is interested and who are using VS C++2008 I fixed my linking problem by compiling the release version and not the debug version.
I also took out references to
#define unicode
#define _unicode
in stdAfx.h that I had inadvertently added when cut & pasting version info.
Finally, I changed all the lines in filespyview.cpp that read
_beginthread( ThreadRoute, 0, (void*)new Param(FILE_NOTIFY_CHANGE_DIR_NAME, "FILE_NOTIFY_CHANGE_DIR_NAME" ) );
or the like to
_beginthread( ThreadRoute, 0, (void*)new Param(FILE_NOTIFY_CHANGE_DIR_NAME, CString("FILE_NOTIFY_CHANGE_DIR_NAME" )) );
and all compiled nicely and ran beautifully.
|
|
|
|

|
when i spy the dictionary
why some file create,delete,rename or resize,etc couldn't be spy
and when file update quickly it will miss some of them
this is the code from a filespy demo
static void Action(CSpyDlg* dlg)
{
USES_CONVERSION;
HANDLE hDir = CreateFile( CString("d:"), FILE_LIST_DIRECTORY, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL );
FILE_NOTIFY_INFORMATION Buffer[1024];
DWORD BytesReturned;
while(ReadDirectoryChangesW(
hDir, &Buffer, sizeof(Buffer), TRUE, FILE_NOTIFY_CHANGE_SECURITY|
FILE_NOTIFY_CHANGE_CREATION|
FILE_NOTIFY_CHANGE_LAST_ACCESS|
FILE_NOTIFY_CHANGE_LAST_WRITE|
FILE_NOTIFY_CHANGE_SIZE|
FILE_NOTIFY_CHANGE_ATTRIBUTES|
FILE_NOTIFY_CHANGE_DIR_NAME|
FILE_NOTIFY_CHANGE_FILE_NAME, &BytesReturned, NULL, NULL ))
{
CTime tm = CTime::GetCurrentTime();
CString helper_txt;
switch(Buffer[0].Action)
{
case FILE_ACTION_ADDED: helper_txt = "The file was added to the directory"; break;
case FILE_ACTION_REMOVED: helper_txt = "The file was removed from the directory"; break;
case FILE_ACTION_MODIFIED: helper_txt = "The file was modified. This can be a change in the time stamp or attributes."; break;
case FILE_ACTION_RENAMED_OLD_NAME: helper_txt = "The file was renamed and this is the old name."; break;
case FILE_ACTION_RENAMED_NEW_NAME: helper_txt = "The file was renamed and this is the new name."; break;
}
int i=0;
do
{
m_Sec.Lock();
int item = dlg->m_list.InsertItem(dlg->m_list.GetItemCount(), CString(Buffer[i].FileName).Left(Buffer[i].FileNameLength / 2) + " - " + helper_txt );
dlg->m_list.SetItemText(item, 1, tm.Format("%Y/%m/%d/ - %H:%M:%S"));
i++;
m_Sec.Unlock();
}
while (!Buffer[i].NextEntryOffset);
}
}
|
|
|
|
|

|
hello:
I find the processchangenotication function have some problem.
the code of ASSERT(notify.getAction == FILE_ACTION_RENAMED_NEW_NAME) is not vertified. i do not know why
|
|
|
|

|
Your code snippet work fine if there is only one ore two file added at a time. If I copy >= 6 files into the watched directory then only 4 or 5 files show up.
How to solve this ?
|
|
|
|

|
GameProfessor wrote: How to solve this ?
You can't.
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|

|
Is that supposed to solve the OP's problem? See here to understand why it won't.
"Love people and use things, not love things and use people." - Unknown
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|

|
I fail to see why you are responding to me rather than GameProfessor. The OP's "lack of notification" problem is a known one and cannot be solved. See here.
"Love people and use things, not love things and use people." - Unknown
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|

|
I've made some checks with changes like I've post under XP sp 3 and anything works fine.
I'll update article code as soon as my time allow this.
Vitali
|
|
|
|

|
HI
I am using ur filespy source code.. the program is working well but i don't know how to terminate the spying the file? its always spying files. suppose i want to terminate the file spying how can i? i have one button "End capute". id i click this button the spying file will be stopped? can u help me....
Thanks and Regards
Guna
|
|
|
|

|
The button click should trigger an event, that WaitForMultipleObjects() is waiting for.
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|

|
Hi,
Thanks for the question.
BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode) - also can be used.
Vitali
|
|
|
|

|
I am developing a back up software using vb.net
I have to lock a particular folder or lock a drieve through code.
please help me!!!!!!!!!!!!
Amit kuamr
Viaedge software tech
Thane
|
|
|
|
|

|
I think the codeline
FILE_NOTIFY_INFORMATION Buffer[1024];
does not make sense, because the information of ReadDirectoryChangesW will NOT be returned as an array, but as a continous byte stream with the format
DWORD1 DWORD2 DWORD3 WCHAR[] DWORD1 DWORD2 DWORD3 WCHAR[] ...
Here DWORD1 stands for a DWORD, that tells you, how many bytes to the right you will find the next DWORD1.
DWORD2 tells, as shown in the code, about why the function returned.
DWORD3 gives the length (in bytes) of the filename
WCHAR[] is a variable length wide char array- the filename. It is NOT (!) NULL terminated. So with DWORD1 and DWORD3 is a bit redundand, because with both you can calculate the start of the next structure. However: DWORD1 is NULL, if there is no next structure (which is often the case when only one file is modified in the folder).
I would propose the following code, to determine the file names from the returned buffer:
BYTE buffer[10240]={0};
//
ReadDirectoryChangesW( ...);
do something if the buffer is to small; dynamic allocation might solve that...
//
do{
WCHAR szFileName[MAX_PATH]={0};
// the filename is not terminated, so we should not use wszncpy
CopyMemory( szFileName, pFni->FileName, pFni->FileNameLength);
LOG( _T("Found activity in folder: %S"), szFileName);
if( pFni->NextEntryOffset)
{ // there is a new structure
BYTE* pByte = (BYTE*) pFni;
pByte += (pFni->NextEntryOffset);
pFni = (FILE_NOTIFY_INFORMATION*) pByte;
continue;
}
else
break;
} while( 1);
So: even so the given sample code is nice to demonstrate the function ReadDirectoryChangesW, it does not work in cases, where the function returns more then one set of infromation.
HoM
|
|
|
|

|
i think, it can be usefull
rudozkv
|
|
|
|

|
hi,
when a file is copyed, can I get some message at that time,
even, block the operation?
thanks!
learn,learn and learn
|
|
|
|

|
How can i pre detect, wether the file already open or not, Any API or so...
cheers
Balkrishna Talele
|
|
|
|
|

|
thanks, that reply was too fast, but alas not helped me thought!!!
cheers
Balkrishna Talele
-- modified at 6:00 Thursday 12th January, 2006
|
|
|
|

|
Hi,
Is there a way to be notified when a folder is shared/unshared?
thanks in advance
TBan
|
|
|
|

|
Hi,
you can try to check following noitifications:
FILE_NOTIFY_CHANGE_ATTRIBUTES
and
FILE_NOTIFY_CHANGE_SECURITY
Vitali
|
|
|
|

|
I try to run on Win9x but i can't get the file that was modify.
The list at the bottom has nothing.
I only got event notify on the list at the top.
|
|
|
|

|
Hi Yulaw,
Thanks for the question. Read MSDN regarding platforms for the ReadDirectoryChangesW :
Requirements
Windows NT/2000: Requires Windows NT 3.51 SP3 or later.
Windows 95/98: Unsupported.
Header: Declared in Winbase.h; include Windows.h.
Library: Use Kernel32.lib.
Unicode: Implemented only as Unicode.
Vitali
modified on Tuesday, June 3, 2008 10:19 AM
|
|
|
|

|
Hey Vitali,
Thanks for the sample. Very useful. In getting this concept to work under Delphi, I may have stumbled upon a potential problem and would like your comments.
The MS documentation for ReadDirectoryChanges mentions that the buffer is not a array of objects can be indexed, but will contain an unknown number of variable length records. The first member of the FILE_NOTIFY_INFORMATION structure is NextEntryOffset, which indicates how many bytes forward the next entry sits. A zero for this value indicates that the reocrd is the last one.
I find that your code in treating the returned buffer as an array of FILE_NOTIFY_INFORMATION structures.
Have I missed something?
Perhaps the reason its works is that since it is running in a dedicated thread, the system places at most a single item in the buffer. Even with this, it would seem that the test at line 152 would have problems, since after processing the first item (element 0), you are conditioning the loop continuing based on structure[1], which should be invalid since we are dealing with variable length records.
Your thoughts please. Thanks.
C
|
|
|
|

|
Hi Vitaly. Thanks for your interesting article.
I want to intercept any request for file read before being serviced and also can deny the access based on processing result. (something like antiviruses do)
I already know that by file system filter drivers I can do that, but I have not access to IFS or DDK of microsoft, and you know what is programming without any sample code, specially with the complexity of driver development (with the special case of file system driver).
Is there any other way, or at least any accessible resources to do that (specially sample codes)?
Thanks in advance.
|
|
|
|
|

|
Dear friends,
It's great to come to know your application.
I have a question:
Assuming that I have a shared directory on a Server, if a client connects to that directory, I want to capture some information of that client such as IP address, username, etc...
I need those information to associate with your program.
How can I do that? Please help me.
I am looking forward to your reply,
Thank you so much,
Wall
|
|
|
|

|
I use your application on W2000 SP4 (5.00.2195).
I can't rename any directories in the watched directory.
Google say :
2.2 List of Bugs Fixed in Windows NT 3.51 U.S. Service Pack 5
Service Pack 4
--------------
...
Q140408: Access Denied Attempting to Rename File Across the Network
...
Can I hope there is a solution to my problem ?
|
|
|
|

|
Answer : add |FILE_SHARE_DELETE in the dwShareMode.
For the FAQ
|
|
|
|
|

|
Hello there,
great work.
I would like to ask, how can i convert this tool to a dll, for using it with Java ?
Best Regards
Thomas
|
|
|
|

|
Hi Thomas,
Thank you for "great work" from you
To use this technique in Java apps following steps are needed:
- Make dll project in VC++
- Define dll exportable functins (these functions are the same, with small changes as in the article)
- Make additional definitions in functions prototypes and dll to provide calling them from Java
Hope this can help.
Vitali
modified on Tuesday, June 3, 2008 10:20 AM
|
|
|
|

|
using the ReadDirectoryChangesW function but I get an error: 6 which implies an invalid handle. I call CreateFile prior to ReadDirectoryChangesW to get the handle to a folder and it succeeds. The handle looks plenty valid, but when I pass it to ReadDirectoryChangesW things dont seem to work. My buffer does not get formatted. I'm not even sure what its supposed to look like, but it doest change, and my Bytes Returned DWORD is unchanged too. I have tired using the asynchronous and synchronous method with no luck.
Without posting code, is there anything obvious that I am missing? My buffer is just an array of CHAR’s. I call createfile exactly how it is described in MSDN under the ReadDirectoryChangesW documentation.
Form what I understand, once my buffer is set up using ReadDirectoryChangesW, I can then type case it as a FILE_NOTIFY_INFORMATION* and then pull the info out of that it using that struct. However, I’m not even getting that far. GetLastError returns a 6 after ReadDirectoryChangesW.
Please help, I have spent way too much time in the debugger a this stupid function call.
Thank you
|
|
|
|
|

|
I've had the same problem.
The secret seems to be to properly initialize the OVERLAPPED structure pointed to by one of the ReadDirectoryChanges() parameters. Clearing the structure to zero should help.
Good luck!
Axel Kemper
|
|
|
|

|
this is a nice app. how about an app that even tells you WHO deleted/created a file? do you have any idea how to do that? a link maybe?
Thank you,
Adrian Korsuas
korsuas@yahoo.com
|
|
|
|

|
I know of no Win32 user-mode API way to identify the user responsible for the change. You might look at File Monitor at sysinternals.com, but that works by using a kernel mode installable file system filter driver.
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
|
Article describes how to create a file system spy application
| Type | Article |
| Licence | CPOL |
| First Posted | 15 Sep 2003 |
| Views | 268,448 |
| Bookmarked | 112 times |
|
|