2010-11-14 23 views
8

Tôi đang phát triển một đoạn mã C sử dụng ReadDirectoryChangesW() để giám sát các thay đổi trong một thư mục trong Windows. Tôi đã đọc các mục MSDN liên quan cho ReadDirectoryChangesW() và cấu trúc FILE_NOTIFY_INFORMATION, cũng như một số tài liệu khác. Tại thời điểm này tôi đã quản lý để theo dõi nhiều thư mục mà không có vấn đề rõ ràng trong việc giám sát chính nó. Vấn đề là các tên tệp được đặt trong cấu trúc FILE_NOTIFY_INFORMATION bởi hàm này không phải là chuẩn.Làm thế nào để đối phó với Windows 'ReadDirectoryChangesW() và đầu ra tên tệp dài/ngắn hỗn hợp của nó?

Theo MSDN, chúng có thể ở dạng dài hoặc ngắn. Tôi đã tìm thấy một số bài viết đề nghị bộ nhớ đệm cả tên đường dẫn ngắn và dài để xử lý trường hợp này. Thật không may, theo thử nghiệm của riêng tôi trên một hệ thống Windows 7, điều này là không đủ để loại bỏ vấn đề, bởi vì không chỉ có hai lựa chọn thay thế cho mỗi tên tập tin. Vấn đề là trong một tên đường dẫn MACHI COMPONENT có thể ở dạng dài hoặc ngắn. Các tên đường dẫn sau tất cả có thể tham khảo với cùng file:

c: \ PROGRA ~ 1 \ MYPROG ~ 1 \ MyData ~ 1.TXT

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

c: \ PROGRA ~ 1 \ MyProgram \ MyData ~ 1.TXT

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

c: \ Program Files \ MYPROG ~ 1 \ MyData ~ 1 .TXT

...

và theo như tôi có thể nói từ thử nghiệm của tôi bằng cách sử dụng cmd.exe, tất cả đều được chấp nhận hoàn toàn. Về cơ bản, số lượng tên đường dẫn hợp lệ cho mỗi tệp tăng lên theo cấp số mũ với số lượng thành phần trong tên đường dẫn của nó.

Thật không may, ReadDirectoryChangesW() dường như điền vào bộ đệm đầu ra của nó với tên tệp như được cung cấp cho cuộc gọi hệ thống gây ra từng thao tác. Ví dụ: nếu bạn sử dụng lệnh cmd.exe để tạo, đổi tên, xóa e.t.c. tệp, FILE_NOTIFY_INFORMATION sẽ chứa tên tệp như được chỉ định tại dòng lệnh.

Bây giờ, trong hầu hết các trường hợp, tôi có thể sử dụng GetLongPathName() và bạn bè để có được một đường dẫn duy nhất để tôi sử dụng. Thật không may là không thể thực hiện được khi xóa các tập tin - khi tôi nhận được thông báo, tập tin đã biến mất và các chức năng Get * PathName() sẽ không hoạt động.

Hiện tại tôi đang nghĩ đến việc sử dụng bộ nhớ đệm rộng hơn để xác định tên đường dẫn thay thế nào được sử dụng bởi các ứng dụng cho mỗi tệp, điều này sẽ xử lý mọi trường hợp ngoại trừ trường hợp ai đó quyết định xóa tệp ra khỏi màu xanh dương một tên đường dẫn hỗn hợp không nhìn thấy. Và tôi đang nghĩ về khai phá dữ liệu sáng tạo từ các sự kiện sửa đổi thư mục mẹ và quay trở lại để kiểm tra thư mục thực sự cho trường hợp đó.

Bất kỳ đề xuất nào cho cách dễ dàng hơn để thực hiện việc này?

PS1: Trong khi thay đổi tạp chí sẽ đối phó với điều này một cách hiệu quả (tôi hy vọng) Tôi không tin rằng tôi có thể sử dụng chúng, do mối quan hệ của chúng với NTFS và thiếu quyền quản trị cho ứng dụng của tôi. Tôi không muốn đến đó, trừ khi tôi hoàn toàn bị buộc phải.

PS2: Xin lưu ý rằng tôi mã chủ yếu trên Unix, vì vậy hãy nhẹ nhàng ...

+0

Nếu vẫn thất bại, có thể trình điều khiển minifilter sẽ hoạt động? – wj32

+0

Tôi tin rằng đó là những gì hầu hết các chương trình chống vi-rút làm và tôi cho rằng đó sẽ là giải pháp cho vấn đề này. Thật không may, nó đòi hỏi quyền quản trị hệ thống cài đặt, và giống như Change Journals nó sẽ làm cho kiến ​​trúc của ứng dụng của tôi trở nên phức tạp hơn, vì tôi sẽ phải cân nhắc vấn đề bảo mật và ổn định mà tôi không phải giải quyết ngay bây giờ. Và đừng quên những khó khăn vốn có của việc viết trình điều khiển chế độ hạt nhân hoặc chế độ nhân-quasi cho bất kỳ hệ điều hành nào. – thkala

+0

Ồ, và tại thời điểm này có vẻ như một chút quá mức cần thiết để theo dõi mọi thứ chỉ để xem một vài thư mục người dùng. Cảm ơn đề xuất mặc dù ... – thkala

Trả lời

1

Bạn không cần phải cache mọi kết hợp. Nó sẽ làm gì nếu bạn cache mỗi subpath để có thể chuyển đổi nó thành dạng dài.ví dụ cửa hàng này:

  • 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

Bây giờ nếu bạn nhận được một thông báo của c:\PROGRA~1\MYPROG~1\MYDATA~1.TXT, chia nó ở mọi \, và tra cứu từng phần cho đó là hình thức dài.

Đừng quên rằng MyDataFile.txtMYDATAFILE.TXT cũng trỏ đến cùng một tệp. Vì vậy, so sánh phân biệt chữ hoa chữ thường hoặc chuyển đổi mọi thứ thành chữ hoa.

Và nếu c:\PROGRA~1\MYPROG~1\MYDATA~1.TXT bị xóa, bạn vẫn có thể sử dụng GetLongPathName() trên c:\PROGRA~1\MYPROG~1.

+0

Khi tôi đề cập đến bộ nhớ đệm rộng lớn và khai thác dữ liệu, tôi đã ghi nhớ một phiên bản nâng cao hơn một chút về những gì bạn đề xuất. Ngay bây giờ tôi đang lưu trữ cả tên ngắn và dài khi có sẵn và khi một con đường đã được nhìn thấy tôi đã có thể tìm ra tất cả các tên đường dẫn thay thế. Sử dụng liên kết c: \ A \ B \ C -> c: \ a \ b \ c Tôi có thể phát hiện tất cả các kết hợp c: \ {A, a} \ {B, b} \ {C, c}. Vẫn tồn tại sự cố với việc xóa các tệp không nhìn thấy. Tôi đang suy nghĩ về đệ quy lưu trữ một trạng thái ban đầu của thư mục để đối phó với điều này - không chắc chắn nếu tôi có thể tránh nó anyway ... – thkala

Các vấn đề liên quan