在Windows 7中监视文件的更改
Watching a file for changes in Windows 7
我有一个适用于Windows 7的Visual Studio 2008 C++应用程序,我想在其中查看文件的更改。
文件可能会这样更改:
std::ofstream myfile_;
void LogData( const char* data )
{
myfile_ << data << std::endl;
// note that the file output buffer is flushed by std::endl, but the file is not closed.
}
我尝试使用ReadDirectoryChangesW和带有FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_SECURITY | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_FILE_NAME
标志的FindFirstChangeNotification来监视文件的目录。但是,在文件句柄实际关闭之前,这两个API都不会检测到文件更改。
是否有任何方法可以在实际写入文件时,但在关闭文件句柄之前检测更改?
谢谢,PaulH
更新根据@Edwin的建议,我正在尝试使用Journal功能。但是,我有几个问题。
- FSCTL_READ_USN_JOURNAL立即返回。它不会阻塞。(不过,这可能与问题2有关)
- 不管我的句柄指向哪里(我已经尝试打开目录"C:\Foo\Bar"和文件"C:\Foo\Par\MyFile.txt"的句柄),我似乎都会对C:卷进行任何更改。有没有办法限制
FSCTL_READ_USN_JOURNAL
给我的东西
为简洁起见,省略了错误检查。
boost::shared_ptr< void > directory(
::CreateFileW( L"C:\Foo\Bar\Myfile.txt",
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL ),
::CloseHandle );
USN_JOURNAL_DATA journal = { 0 };
DWORD returned = 0;
::DeviceIoControl( directory.get(), FSCTL_QUERY_USN_JOURNAL, NULL, 0, &journal, sizeof( journal ), &returned, NULL );
BYTE buffer[ 4096 ] = { 0 };
READ_USN_JOURNAL_DATA read = { 0, USN_REASON_DATA_EXTEND | USN_REASON_DATA_TRUNCATION, FALSE, 0, 0, journal.UsnJournalID };
::DeviceIoControl( directory.get(), FSCTL_READ_USN_JOURNAL, &read, sizeof( read ), &buffer, sizeof( buffer ), &returned, NULL );
for( USN_RECORD* record = ( USN_RECORD* )( buffer + sizeof( USN ) );
( ( BYTE* )record - buffer ) < returned;
record = ( USN_RECORD* )( ( BYTE* )record + record->RecordLength ) )
{
ATLTRACE( L"%srn", record->FileName );
}
示例输出(这些都不在C:\Foo\Bar目录中):
AeXProcessList.txt`
AeXProcessList.txt`
AeXAMInventory.txt`
AeXAMInventory.txt`
AeXProcessList.txt`
AeXProcessList.txtP
access.log`
mysqlgeneral.log
E804.tmp
apache_error.log
E804.tmp
CHROME.EXE-5FE9909D.pfh
CHROME.EXE-5FE9909D.pfp
SyncData.sqlite3-journal
CHROME.EXE-5FE9909D.pfh
CHROME.EXE-5FE9909D.pfP
1211.tmp
SyncData.sqlite3-journal
AeXAMInventory.txt
您可以使用
更改日记账操作
(请参阅MSDN文档)
这是检测文件系统中任何更改的唯一100%保证的方法。但这相当复杂。
要读取特定文件或目录的数据,我认为您需要使用FSCTL_READ_FILE_USN_DATA
而不是FSCTL_READ_USN_JOURNAL
。我相信后者总是检索整个卷的数据。但是,这不会填充您获得的USN记录的TimeStamp
、Reason
或SourceInfo
字段。如果你需要这些,我相信你可以用FSCTL_READ_USN_JOURNAL
读取它们,指定你想要读取的确切USN。
否,因为在关闭文件句柄之前,无法保证操作系统会写入一个字节。
例外情况可能是在文件句柄上调用flush
,然后调用Windows API函数FlushFileBuffers
,但除非写入文件的程序这样做,否则可能不会写入任何字节。
这可以通过监视FASTIO_WRITE和IRP_MJ_WRITE操作的筛选器驱动程序来完成。这是一篇非常好的操作文章。
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 文本文件中的单词链表
- CMake-按正确顺序将项目与C运行时对象文件链接
- 是否有一个标准函数可以打印/监视stdin文件的内容,同时将数据留在stdin中
- C++ 使用读取目录更改监视文件更改W不触发所有操作?
- 如何:监视Windows中另一个进程的文件访问?
- 切割和粘贴后监视文件(Windows shell扩展?)
- 如何使用 C++ 中的 BIOS 中断监视 Windows 中的所有文件更改
- 使用INotify可以监视具有多个符号链接的文件
- 如何同步 2 个或更多监视文件夹
- NodeJS 文件系统 监视抛出事件两次或更多次
- 如何监视远程计算机上的文件更改
- 在Windows 7中监视文件的更改
- 如何监视包含所有子文件夹和文件的文件夹
- 监视新文件并获取它们的名称?如何使用函数
- 从python启动多个二进制文件并监视它们的状态
- 如何监视和同步文件集合
- 寻找一种在Unix c++中被动监视目录中的文件活动的方法
- 监视日志文件(C++)时崩溃