У меня есть приложение Visual Studio 2008 C ++ для Windows 7, где я хотел бы посмотреть файл на предмет изменений.
Файл может быть изменен следующим образом:
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, и FindFirstChangeNotification с флагами 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
. Но ни один из этих API не будет обнаруживать изменения файла, пока дескриптор файла не будет фактически закрыт.
Есть ли способ обнаружить изменение, когда файл действительно записан, но до закрытия дескриптора файла?
Спасибо,
PaulH
Обновление
По предложению @ Edwin, я пытаюсь использовать функцию журнала. Но у меня есть пара вопросов.
- FSCTL_READ_USN_JOURNAL возвращается мгновенно. Это не блокирует. (хотя, это может быть связано с проблемой 2)
- Независимо от того, на что указывает мой дескриптор (я пытался открыть дескриптор для каталога "C: \ Foo \ Bar" и для файла "C: \ Foo \ Bar \ 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"%s\r\n", 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