Windows文件变更监控

来源:互联网 发布:网络玄幻小说典藏版27 编辑:程序博客网 时间:2024/04/30 01:22

有的时候需要在新建、修改和删除文件时执行一些操作,这就需要监控文件的变更。http://zhanyonhu.blog.163.com/blog/static/16186044200882484143208/提出了3种方法来实现:

1. 函数FindFirstChangeNotification和FindNextChangeNotification

2. 系统核心工具软件,比如FileMon(文件监视),开放源代码

3. Hook API,钩住CreateFile函数,分析其参数,借此来判断是创建文件还是读写文件;钩住DeleteFile函数,监视文件删除操作;钩住CreateDirectory和RemoveDirectory,借此判断是否是删除文件;钩住回收站相关函数,借此判断是否是移动到回收站。

后面两种方法一个使用驱动相关的技术,一个使用Hook,都比较复杂。通过Windows提供的API已经可以满足一些基本的文件监控需求。下面主要看下2个函数:

FindFirstChangeNotification Function

Creates a change notification handle and sets up initial change notification filter conditions. A wait on a notification handle succeeds when a change matching the filter conditions occurs in the specified directory or subtree. The function does not report changes to the specified directory itself.

This function does not indicate the change that satisfied the wait condition. To retrieve information about the specific change as part of the notification, use the ReadDirectoryChangesW function.

HANDLE WINAPI FindFirstChangeNotification(
  __in          LPCTSTR lpPathName,
  __in          BOOL bWatchSubtree,
  __in          DWORD dwNotifyFilter
);

Parameters
lpPathName 
The path of the directory to be watched. 

In the ANSI version of this function, the name is limited to MAX_PATH characters. To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path. For more information, see Naming a File.

bWatchSubtree 
If this parameter is TRUE, the function monitors the directory tree rooted at the specified directory; if it is FALSE, it monitors only the specified directory.

dwNotifyFilter 
The filter conditions that satisfy a change notification wait. This parameter can be one or more of the following values.

 

http://www.codeproject.com/KB/files/DirCheck.aspx提供了一个用FindFirstChangeNotification实现的封装类。

ReadDirectoryChangesW Function

Retrieves information that describes the changes within the specified directory. The function does not report changes to the specified directory itself.


To track changes on a volume, see change journals.


Syntax

BOOL WINAPI ReadDirectoryChangesW(
  __in         HANDLE hDirectory,
  __out        LPVOID lpBuffer,
  __in         DWORD nBufferLength,
  __in         BOOL bWatchSubtree,
  __in         DWORD dwNotifyFilter,
  __out_opt    LPDWORD lpBytesReturned,
  __inout_opt  LPOVERLAPPED lpOverlapped,
  __in_opt     LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
Parameters

hDirectory [in]
A handle to the directory to be monitored. This directory must be opened with the FILE_LIST_DIRECTORY access right.

lpBuffer [out]
A pointer to the DWORD-aligned formatted buffer in which the read results are to be returned. The structure of this buffer is defined by the FILE_NOTIFY_INFORMATION structure. This buffer is filled either synchronously or asynchronously, depending on how the directory is opened and what value is given to the lpOverlapped parameter. For more information, see the Remarks section.

nBufferLength [in]
The size of the buffer that is pointed to by the lpBuffer parameter, in bytes.

bWatchSubtree [in]
If this parameter is TRUE, the function monitors the directory tree rooted at the specified directory. If this parameter is FALSE, the function monitors only the directory specified by the hDirectory parameter.

dwNotifyFilter [in]
The filter criteria that the function checks to determine if the wait operation has completed. This parameter can be one or more of the following values.

lpBytesReturned [out, optional]
For synchronous calls, this parameter receives the number of bytes transferred into the lpBuffer parameter. For asynchronous calls, this parameter is undefined. You must use an asynchronous notification technique to retrieve the number of bytes transferred.

lpOverlapped [in, out, optional]
A pointer to an OVERLAPPED structure that supplies data to be used during asynchronous operation. Otherwise, this value is NULL. The Offset and OffsetHigh members of this structure are not used.

lpCompletionRoutine [in, optional]
A pointer to a completion routine to be called when the operation has been completed or canceled and the calling thread is in an alertable wait state. For more information about this completion routine, see FileIOCompletionRoutine.

http://www.codeproject.com/KB/files/directorychangewatcher.aspx提供了一个用ReadDirectoryChangesW实现的封装类。

http://www.codeproject.com/KB/files/FileSpyArticle.aspx给出了FindFirstChangeNotification和ReadDirectoryChangesW的一些详细介绍和示例。可以参考一下。

 

其他相关的解决方案:

FileSystemWatcher侦听文件系统更改通知,并在目录或目录中的文件发生更改时引发事件。可监视指定目录中的文件或子目录的更改。可以创建一个组件来监视本地计算机、网络驱动器或远程计算机上的文件。

下面的示例创建一个 FileSystemWatcher,以便在运行时监视指定的目录。组件设置为监视 LastWrite 和 LastAccess 时间方面的更改,以及目录中文本文件的创建、删除或重命名。如果更改、创建或删除文件,文件路径将被输出到控制台。在文件重命名后,旧路径和新路径都输出到控制台。在此示例中使用 System.Diagnostics 和 System.IO 命名空间。

[cpp] view plaincopy
  1. <pre class="cpp" name="code">public ref class Watcher  
  2. {  
  3. private:  
  4.    // Define the event handlers.  
  5.    static void OnChanged( Object^ /*source*/, FileSystemEventArgs^ e )  
  6.    {  
  7.       // Specify what is done when a file is changed, created, or deleted.  
  8.       Console::WriteLine( "File: {0} {1}", e->FullPath, e->ChangeType );  
  9.    }  
  10.   
  11.    static void OnRenamed( Object^ /*source*/, RenamedEventArgs^ e )  
  12.    {  
  13.       // Specify what is done when a file is renamed.  
  14.       Console::WriteLine( "File: {0} renamed to {1}", e->OldFullPath, e->FullPath );  
  15.    }  
  16.   
  17. public:  
  18.    [PermissionSet(SecurityAction::Demand, Name="FullTrust")]  
  19.    int static run()  
  20.    {  
  21.       array<String^>^args = System::Environment::GetCommandLineArgs();  
  22.   
  23.       // If a directory is not specified, exit program.  
  24.       if ( args->Length != 2 )  
  25.       {  
  26.          // Display the proper way to call the program.  
  27.          Console::WriteLine( "Usage: Watcher.exe (directory)" );  
  28.          return 0;  
  29.       }  
  30.   
  31.       // Create a new FileSystemWatcher and set its properties.  
  32.       FileSystemWatcher^ watcher = gcnew FileSystemWatcher;  
  33.       watcher->Path = args[ 1 ];  
  34.   
  35.       /* Watch for changes in LastAccess and LastWrite times, and  
  36.           the renaming of files or directories. */  
  37.       watcher->NotifyFilter = static_cast<NotifyFilters>(NotifyFilters::LastAccess |  
  38.             NotifyFilters::LastWrite | NotifyFilters::FileName | NotifyFilters::DirectoryName);  
  39.   
  40.       // Only watch text files.  
  41.       watcher->Filter = "*.txt";  
  42.   
  43.       // Add event handlers.  
  44.       watcher->Changed += gcnew FileSystemEventHandler( Watcher::OnChanged );  
  45.       watcher->Created += gcnew FileSystemEventHandler( Watcher::OnChanged );  
  46.       watcher->Deleted += gcnew FileSystemEventHandler( Watcher::OnChanged );  
  47.       watcher->Renamed += gcnew RenamedEventHandler( Watcher::OnRenamed );  
  48.   
  49.       // Begin watching.  
  50.       watcher->EnableRaisingEvents = true;  
  51.   
  52.       // Wait for the user to quit the program.  
  53.       Console::WriteLine( "Press \'q\' to quit the sample." );  
  54.       while ( Console::Read() != 'q' )  
  55.          ;  
  56.    }  
  57. };  
  58.   
  59. int main() {  
  60.    Watcher::run();  
  61. }</pre>  
  62. <pre></pre>  
  63. <pre></pre>  
  64. FileSyncProvider是同步的同步提供程序,它可用于同步 NTFS、FAT 或 SMB 文件系统中的文件、文件夹和子文件夹。详细参见MSDN<a href="http://msdn.microsoft.com/zh-cn/library/microsoft.synchronization.files.filesyncprovider(v=SQL.100).aspx">http://msdn.microsoft.com/zh-cn/library/microsoft.synchronization.files.filesyncprovider(v=SQL.100).aspx</a><br>  
  65. <br>  
  66. <pre></pre>  
  67. <pre></pre>