c ++ - Se en fil til ændringer i Windows 7

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har en Visual Studio 2008 C ++ applikation til Windows 7, hvor jeg gerne vil se en fil for ændringer.


Filen kan ændres som denne:


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.
}


Jeg har forsøgt at se filens katalog ved hjælp af både ReadDirectoryChangesW og FindFirstChangeNotification med 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 flag. Men ingen af ​​disse API'er vil registrere filændringer, indtil filhåndtaget faktisk er lukket.


Er der nogen måde at registrere en ændring, når filen faktisk er skrevet, men inden filhåndtaget er lukket?


Tak,
PaulH





Opdater
På @Edwins forslag foreslår jeg at bruge funktionen Journal. Men jeg har nogle problemer.



  1. FSCTL\_READ\_USN\_JOURNAL vender øjeblikkeligt tilbage. Det blokerer ikke. (selvom dette kan være relateret til nummer 2)

  2. Uanset hvor mit håndtag peger på (jeg har forsøgt at åbne et håndtag til mappen 'C: \ Foo \ Bar' og til filen 'C: \ Foo \ Bar \ MyFile.txt') synes jeg at få nogen ændringer foretaget til C: volumen. Er der en måde at begrænse, hvad FSCTL\_READ\_USN\_JOURNAL giver mig?



Fejlkontrol udeladt for kortfattet.


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
", record->FileName );
}


Eksempel output (ingen af ​​disse er i C: \ Foo \ Bar-mappen):


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

Bedste reference


Du kan bruge



  Skift journaloperationer



(se MSDN-dokumenter)


Det er den eneste 100\% garanterede måde at registrere enhver ændring i filsystemet på.
Men det er ret kompliceret.

Andre referencer 1


For at læse data for en bestemt fil eller mappe, tror jeg, du vil bruge FSCTL\_READ\_FILE\_USN\_DATA i stedet for FSCTL\_READ\_USN\_JOURNAL. Jeg tror, ​​at sidstnævnte altid henter data for et helt volumen. Det fylder dog ikke felterne i TimeStamp, Reason eller SourceInfo af den USN-post, du får. Hvis du har brug for dem, tror jeg, du kan læse dem med FSCTL\_READ\_USN\_JOURNAL og angive det nøjagtige USN, du vil læse. [14]

Andre referencer 2


Nej, for indtil du lukker filhåndtaget, er der ingen garanti for, at en enkelt byte nogensinde bliver skrevet af operativsystemet.


Undtagelsen vil sandsynligvis være ved at kalde flush på dit filhåndtag og derefter ringe til Windows API-funktionen FlushFileBuffers, men medmindre programmet skriver ind i filen, bliver det muligvis ikke skrevet bytes.

Andre referencer 3


Dette kan gøres med en filterdriver, der overvåger FASTIO\_WRITE og IRP\_MJ\_WRITE operationerne. Her er en ret god, hvordan-artiklen. [15]