Просмотр файла изменений в Windows 7 - PullRequest
2 голосов
/ 14 февраля 2012

У меня есть приложение 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, я пытаюсь использовать функцию журнала. Но у меня есть пара вопросов.

  1. FSCTL_READ_USN_JOURNAL возвращается мгновенно. Это не блокирует. (хотя, это может быть связано с проблемой 2)
  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

Ответы [ 4 ]

2 голосов
/ 14 февраля 2012

Вы можете использовать

Изменить операции журнала

(см. Документы MSDN)

Это единственный гарантированный способ 100% обнаружить любое изменение вфайловая система.Но это довольно сложно.

1 голос
/ 15 февраля 2012

Чтобы прочитать данные для определенного файла или каталога, я считаю, что вы хотите использовать FSCTL_READ_FILE_USN_DATA вместо FSCTL_READ_USN_JOURNAL. Я считаю, что последний всегда извлекает данные для всего тома. Однако это не заполняет поля TimeStamp, Reason или SourceInfo полученной вами записи USN. Если вам они нужны, я думаю, вы можете прочитать их с помощью FSCTL_READ_USN_JOURNAL, указав точный номер USN, который вы хотите прочитать.

0 голосов
/ 14 февраля 2012

Это можно сделать с помощью драйвера фильтра, который контролирует операции FASTIO_WRITE и IRP_MJ_WRITE. Здесь - довольно хорошая статья с инструкциями.

0 голосов
/ 14 февраля 2012

Нет, потому что до тех пор, пока вы не закроете дескриптор файла, не гарантируется, что ОС будет записан один байт.

Исключением, вероятно, будет вызов flush для вашего дескриптора файла, а затем вызов функции Windows API FlushFileBuffers, но если программа, записывающая в файл, не делает этого, вероятно, не будет записано ни одного байта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...