Windows API - определить, когда открыт файл определенного типа

Возможно ли, чтобы определенный код выполнялся всякий раз, когда открывается файл определенного типа? В моем случае я хочу «слушать», когда открываются видеофайлы (.avi, mp4 и т. д.) (либо через оболочку проводника Windows, либо, может быть, непосредственно из видеоплеера?), чтобы я мог хранить историю воспроизведенных видео.

Час гугления ничего не дал, поэтому я обращаюсь к вам, stackoverflow. Пожалуйста, укажите мне правильное направление.

Спасибо.


person Rafe    schedule 10.01.2014    source источник
comment
А если я открою видеофайл в шестнадцатеричном редакторе, вы тоже попадете в историю ПРОИГРЫВАЕМЫХ видео???   -  person user2120666    schedule 10.01.2014
comment
@user2120666 user2120666 Да, это было бы приемлемо для моего варианта использования.   -  person Rafe    schedule 10.01.2014
comment
Так что перехватывайте CreateFile и/или ShellExecute.   -  person user2120666    schedule 10.01.2014
comment
Спасибо @ user2120666. Думаю попробовать реализовать IShellExecuteHook   -  person Rafe    schedule 10.01.2014
comment
Перехват ShellExecute будет перехватывать только те случаи, когда пользователь открывает файл из Explorer. Если пользователь уже находится в медиаплеере и делает File/Open для файла, он, скорее всего, не увидит его. Перехват CreateFile перехватит их все (хотя и множество других файлов тоже, поэтому накладные расходы будут намного выше).   -  person Carey Gregory    schedule 10.01.2014


Ответы (2)


Лучший (и единственный разумный способ) захватывать события файловой системы (открытие/чтение/запись) из произвольных процессов — это написать Мини-фильтр файловой системы

Если вы разрабатываете коммерческий продукт, воздержитесь от «перехвата» API-интерфейсов режима пользователя, таких как CreateFile. Для этого требуются многочисленные хаки для конкретных платформ, и это кошмар совместимости.

person Bukes    schedule 10.01.2014

Я бы не взял CreateFile на эту работу. В Windows есть встроенные механизмы для более аккуратной обработки подобных заданий.

Самый простой способ справиться с этим — использовать ReadDirectoryChangesW с флаг FILE_NOTIFY_CHANGE_LAST_ACCESS. Каждый раз, когда файл открывается, его время последнего доступа будет обновляться, поэтому это сообщает вам каждый раз, когда файл был открыт.

Хотя это довольно редко, может "пропустить" изменения в редких случаях1. Если вам нужна точность 100 % (вместо, скажем, 99,9 %), вы можете прочитать журналы изменений вместо этого, но это изрядная дополнительная работа для преимущества, о котором вы, возможно, не заботитесь.


1. Есть одно обстоятельство, которое не является (обязательно) редким, но о котором вам может быть интересно: ReadDirectoryChangesW будет работать только тогда, когда/если ваша программа запущена. Журналы изменений сообщат вам о том, что произошло, даже если ваш код вообще не работает.

person Jerry Coffin    schedule 10.01.2014
comment
Это вряд ли будет работать с современными (после Windows XP) разновидностями окон, поскольку обновления отметки времени последнего доступа отключены по умолчанию из соображений производительности. - person Bukes; 10.01.2014
comment
Я также добавлю, что журналы изменений NTFS, очевидно, специфичны для NTFS и не помогут, если OP захочет отслеживать такие открытия для файлов, которые находятся на томах, отличных от NTFS. - person Bukes; 10.01.2014
comment
Если этот параметр включен, отметка времени последнего доступа обновляется, когда соответствующий файл HANDLE закрыт. Вы не будете получать уведомления при открытии файла. - person IInspectable; 11.01.2014