c - Hvordan håndteres Windows 'ReadDirectoryChangesW () og dens blandede lange/korte filnavn output?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg udvikler et stykke C-kode, der bruger ReadDirectoryChangesW () til at overvåge ændringer under en mappe i Windows. Jeg har læst de relaterede MSDN-poster til ReadDirectoryChangesW () og FILE\_NOTIFY\_INFORMATION-strukturen samt flere andre stykker dokumentation. På dette tidspunkt har jeg formået at overvåge flere mapper uden tilsyneladende problemer i selve overvågningen. Problemet er, at filnavne, der er sat i FILE\_NOTIFY\_INFORMATION struktur med denne funktion, ikke er kanoniske.


Ifølge MSDN kan de være i enten lang eller kort form. Jeg har fundet flere indlæg, der tyder på at cache både korte og lange vejnavne til at håndtere denne sag. Desværre er det ifølge min egen test på et Windows 7-system ikke tilstrækkeligt til at fjerne problemet, fordi der ikke kun er to alternativer til hvert filnavn. Problemet er, at i et stinavn kan hver komponent være i enten lang eller kort form. Følgende vejnavne kan alle referere til den samme fil:


c: \ PROGRA ~ 1 \ MYPROG ~ 1 \ Mydata ~ 1.txt


c: \ PROGRA ~ 1 \ MYPROG ~ 1 \ MyDataFile.txt


c: \ PROGRA ~ 1 \ mappen Mine \ Mydata ~ 1.txt


c: \ PROGRA ~ 1 \ mappen Mine \ MyDataFile.txt


c: \ Programmer \ MYPROG ~ 1 \ MYDATA ~ 1.TXT


...


og så vidt jeg kan fortælle fra min testning ved hjælp af cmd.exe er de alle helt acceptable. I det væsentlige stiger antallet af gyldige vejnavne for hver fil eksponentiel med antallet af komponenter i dets stinavn.


Desværre synes ReadDirectoryChangesW () at udfylde sin outputbuffer med filnavnet som angivet til systemopkaldet, der forårsager hver operation. Hvis du for eksempel bruger cmd.exe-kommandoer til at oprette, omdøbe, slette e.t.c. filer, FILE\_NOTIFY\_INFORMATION vil indeholde filnavnet som angivet på kommandolinjen.


Nu kunne jeg i de fleste tilfælde bruge GetLongPathName () og venner til at få en unik vej til min brug. Desværre kan det ikke gøres ved sletning af filer - når jeg får beskeden, er filen allerede væk, og funktionerne Get * PathName () fungerer ikke.


I øjeblikket tænker jeg på at bruge mere omfattende caching for at bestemme, hvilke alternative stienavne der bruges af applikationer til hver fil, hvilket ville kunne håndtere ethvert tilfælde, bortset fra den, hvor en person beslutter at slette en fil ud af det blå ved hjælp af et uset blandet stinavn . Og jeg tænker på kreativ data mining fra moderselskab modifikationshændelser og falder tilbage til at tjekke den faktiske mappe for den sag.


Eventuelle forslag til en nemmere måde at gøre dette på?


PS1: Mens Change Journaler ville håndtere dette effektivt (jeg håber) tror jeg ikke, jeg kan bruge dem på grund af deres bånd til NTFS og manglen på administrator privilegier til min ansøgning. Jeg vil hellere ikke gå der, medmindre jeg er absolut tvunget til.


PS2: Vær venlig at huske på, at jeg hovedsagelig koder for Unix, så vær forsigtig ...

Bedste reference


Du behøver ikke at cache hver kombination. Det gør, hvis du cache hver undervej for at kunne konvertere den til den lange form. For eksempel gem dette:



  • C:PROGRA~1 => c:Program Files

  • c:Program FilesMYPROG~1 => c:Program FilesMyProgram

  • c:Program FilesMyProgramMYDATA~1.TXT => c:Program FilesMyProgramMyDataFile.txt

  • c:Program FilesMyProgramMYDATA~2.TXT => c:Program FilesMyProgramMyDataFile2.txt



Nu, hvis du får en anmeldelse af c:PROGRA~1MYPROG~1MYDATA~1.TXT, opdelt den på hver , og kig på hver del for den lange form.


Glem ikke, at MyDataFile.txt og MYDATAFILE.TXT også peger på den samme fil. Så sammenlign case-insensitive eller konvertere alt til store bogstaver.


Og hvis c:PROGRA~1MYPROG~1MYDATA~1.TXT slettes, kan du stadig bruge GetLongPathName()c:PROGRA~1MYPROG~1.