2010-11-14 7 views
8

Opracowuję fragment kodu C, który używa ReadDirectoryChangesW() do monitorowania zmian w katalogu w systemie Windows. Czytałem pokrewne wpisy MSDN dla ReadDirectoryChangesW() i strukturę FILE_NOTIFY_INFORMATION, a także kilka innych elementów dokumentacji. W tym momencie udało mi się monitorować wiele katalogów bez widocznych problemów w samym monitorowaniu. Problem polega na tym, że nazwy plików umieszczane w strukturze FILE_NOTIFY_INFORMATION przez tę funkcję nie są kanoniczne.Jak radzić sobie z Windows ReadDirectoryChangesW() i jego mieszanym długim/krótkim plikiem wyjściowym?

Według MSDN mogą być w formie długiej lub krótkiej. Znalazłem kilka postów, które sugerują buforowanie zarówno krótkich, jak i długich ścieżek do obsługi tej sprawy. Niestety, zgodnie z moimi własnymi testami w systemie Windows 7 nie jest to wystarczające, aby wyeliminować problem, ponieważ nie ma tylko dwóch alternatyw dla każdej nazwy pliku. Problem polega na tym, że w ścieżce EACH COMPONENT może być w długiej lub krótkiej formie. Następujące ścieżki: wszystko może odnosić się do tego samego pliku:

c: \ progra ~ 1 \ myprog ~ 1 \ MYDATA ~ 1.txt

c: \ progra ~ 1 \ myprog ~ 1 \ MyDataFile.txt

c: \ progra ~ 1 \ MojProgram \ MYDATA ~ 1.txt

c: \ progra ~ 1 \ MojProgram \ MyDataFile.txt

c: \ Program Files \ myprog ~ 1 \ MYDATA ~ 1 .TXT

...

i o ile mogę stwierdzić z moich testów przy użyciu cmd.exe są one całkowicie dopuszczalne. Zasadniczo liczba poprawnych nazw ścieżek dla każdego pliku rośnie wykładniczo wraz z liczbą składników w ścieżce dostępu.

Niestety, ReadDirectoryChangesW() wydaje się wypełniać swój bufor wyjściowy z nazwami plików dostarczonymi do wywołania systemowego, które powoduje każdą operację. Na przykład, jeśli używasz poleceń cmd.exe do tworzenia, zmiany nazwy, usuwania pliku e.t.c. pliki, plik FILE_NOTIFY_INFORMATION będzie zawierał nazwy plików określone w wierszu poleceń.

Teraz w większości przypadków mogę używać GetLongPathName() i znajomych, aby uzyskać unikalną ścieżkę do mojego użytku. Niestety nie można tego zrobić podczas usuwania plików - do czasu otrzymania powiadomienia plik już nie istnieje, a funkcje Get * PathName() nie działają.

W tej chwili myślę o użyciu szerszego buforowania, aby określić, które alternatywne nazwy ścieżek są używane przez aplikacje dla każdego pliku, który obsługiwałby każdy przypadek, z wyjątkiem tego, w którym ktoś decyduje się usunąć plik z niebieskiego za pomocą niewidoczna mieszana nazwa ścieżki. I myślę o wydobywaniu danych kreatywnych ze zdarzeń modyfikacji katalogu nadrzędnego i cofam się do sprawdzania rzeczywistego katalogu dla tej sprawy.

Wszelkie sugestie na łatwiejszy sposób to zrobić?

PS1: Podczas gdy "Change Journals" poradziłoby sobie z tym skutecznie (mam nadzieję), nie wierzę, że mogę z nich korzystać, ze względu na ich powiązania z NTFS i brak przywilejów administratora dla mojej aplikacji. Wolałbym tam nie iść, chyba że jestem do tego absolutnie zmuszony.

PS2: Proszę pamiętać, że I Kod głównie na systemach Unix, więc być delikatny ...

+0

Jeśli wszystko inne zawiedzie, może zadziała sterownik minifiltru? – wj32

+0

Uważam, że to właśnie robi większość programów antywirusowych i przypuszczam, że byłoby to rozwiązanie dla tego problemu. Niestety wymaga instalacji praw administratora systemu, i podobnie jak w przypadku Change Journals, sprawiłoby, że architektura mojej aplikacji stałaby się dużo bardziej skomplikowana, ponieważ musiałbym wziąć pod uwagę kwestie bezpieczeństwa i stabilności, z którymi nie muszę się teraz borykać. I nie zapominajmy o nieodłącznych trudnościach pisania sterownika trybu jądra lub quasi-jądra dla dowolnego systemu operacyjnego. – thkala

+0

Aha, i w tej chwili wydaje się trochę przesady, aby monitorować wszystko tylko po to, aby obejrzeć kilka katalogów użytkownika. Dzięki za sugestię ... – thkala

Odpowiedz

1

Nie trzeba buforować każdą kombinację. To zrobi, jeśli buforujesz każdą ścieżkę podrzędną, aby móc przekonwertować ją na długą.na przykład sklepu to:

  • C:\PROGRA~1 => c:\Program Files
  • c:\Program Files\MYPROG~1 => c:\Program Files\MyProgram
  • c:\Program Files\MyProgram\MYDATA~1.TXT => c:\Program Files\MyProgram\MyDataFile.txt
  • c:\Program Files\MyProgram\MYDATA~2.TXT => c:\Program Files\MyProgram\MyDataFile2.txt

Teraz, jeśli otrzymasz powiadomienie o c:\PROGRA~1\MYPROG~1\MYDATA~1.TXT, podzielić ją na każdym \ i odnośnika każdą część do to długa forma.

Nie zapominaj, że MyDataFile.txt i MYDATAFILE.TXT również wskazują ten sam plik. Więc porównuj wielkość liter lub konwertuj wszystko na wielkie.

Jeśli usunięto c:\PROGRA~1\MYPROG~1\MYDATA~1.TXT, nadal można użyć GetLongPathName() na c:\PROGRA~1\MYPROG~1.

+0

Kiedy wspomniałem o dużym buforowaniu i eksploracji danych, miałem na myśli nieco bardziej udoskonaloną wersję tego, co proponujesz. Obecnie przechowuję zarówno krótkie, jak i długie imiona, gdy są dostępne, a gdy zobaczę ścieżkę, mogę już znaleźć wszystkie alternatywne ścieżki. Używanie skojarzenia c: \ A \ B \ C -> c: \ a \ b \ c Wykrywam wszystkie kombinacje c: \ {A, a} \ {B, b} \ {C, c}. Nadal występuje problem z usunięciem niewidocznych plików. Zastanawiam się nad rekurencyjnym przechowywaniem początkowego stanu katalogu, aby sobie z tym poradzić - nie jestem pewien, czy i tak mogę tego uniknąć ... – thkala