Есть ли более надежный метод трассировки системных вызовов Win32, чем procmon?

Я создаю приложение командной строки Haskell в Windows 10 и пытаюсь отладить проблему, связанную с ограничением пути к файлу Windows в 260 символов, отслеживая системные вызовы и выявляя, какие из них терпят неудачу.

Я использовал procmon (https://docs.microsoft.com/en-us/sysinternals/downloads/procmon) для этого, что кажется довольно хорошим, но, хотя он отображает много связанных записей журнала, я был удивлен, обнаружив, что он не отображает запись для конкретного вызова CreateFileW, который фактически превышает 260 символов и вылетает мое приложение.

Я ненадолго попробовал Win32 API Monitor (https://www.apimonitor.com), но не смог понять или хвосты его; кажется, что он лучше подходит для подключения к уже запущенным приложениям с графическим интерфейсом, чем к приложениям командной строки, которые необходимо запускать в определенном каталоге и т. д.

Есть ли лучшая альтернатива им или лучший подход?


person arya    schedule 27.09.2019    source источник
comment
Я был удивлен, обнаружив, что он не отображает запись для конкретного вызова CreateFileW, который на самом деле превышает 260 символов и приводит к сбою моего приложения, потому что ему нечего регистрировать. Вызов, скорее всего, будет отклонен на уровне API более высокого уровня, когда входные данные впервые проверяются, задолго до того, как они достигнут уровня файловой системы. Procmon регистрирует активность более низкого уровня, а не API более высокого уровня. Такие инструменты, как API Monitor, — это то, что вам нужно. Если у вас возникли проблемы с этим, задайте новый вопрос об этом.   -  person Remy Lebeau    schedule 27.09.2019
comment
Procmon перехватывает на уровне ядра. Ядро, системные компоненты и низкоуровневые реализации библиотеки API используют собственный API NT, который использует подсчитываемые строки Unicode (UTF-16LE), которые могут иметь до 32767 кодовых точек. Ограничение MAX_PATH существует из-за того, как библиотеки пользовательского режима транслируют пути из DOS в собственный NT. Он использовался для совместимости с устаревшими приложениями, но также позволял безоговорочно использовать относительно небольшие статические (для каждого потока) буферы перевода, которые были более эффективны, чем динамические строки в начале 90-х, когда это имело значение.   -  person Eryk Sun    schedule 27.09.2019
comment
Для длинных путей к файлам ваше приложение может вручную нормализовать с помощью GetFullPathNameW и преобразовать результат в путь к устройству. Последний начинается с каталога объектов вызывающей стороны для соединения устройств. В Windows есть два префикса для этого каталога объектов — \\.\ нормализуется, а \\?\ не нормализуется для создания/открытия. Вам нужен ненормализованный префикс, например. \\?\С:\Виндовс. Если путь уже начинается с \\.\, просто замените его на \\?\. Если это UNC, но не путь к устройству, например \\server\share, явно преобразуйте его в соединение устройств UNC, например. \\?\UNC\сервер\общий ресурс.   -  person Eryk Sun    schedule 27.09.2019
comment
@ErykSun обратите внимание, что, начиная с Windows 10 v1607, ограничения MAX_PATH можно избежать, не прибегая к \\?\ или \\?\UNC\ или путям устройств, но поведение должно включаться вручную, подробности см. в MSDN.   -  person Remy Lebeau    schedule 27.09.2019
comment
@RemyLebeau, даже если приложение соглашается, для поддержки длинных путей DOS по-прежнему требуется, чтобы политика была включена на системном уровне, что отключено по умолчанию, поэтому в конечном итоге мы не находимся в той точке, где приложение может полагаться на длинные пути даже в Windows 10. Он также не поддерживается в Windows 7 и 8, поэтому приложения, которым требуются длинные пути, должны взять это в свои руки, вручную нормализуя и передавая \\?\ пути устройств в контексте создания или открытия.   -  person Eryk Sun    schedule 27.09.2019
comment
@RemyLebeau, а также \\?\ или \\?\UNC\ или пути к устройствам - необычная формулировка. \\?\ - это путь к устройству, как и \\.\, но он ограничен MAX_PATH, потому что он нормализуется в контексте создания или открытия, чтобы заменить косую черту обратной косой чертой и обрезать конечные пробелы и точки из конечного компонента. \\?\ обходит нормализацию в контексте создания или открытия. Это обход нормализации и трансляции путей DOS, от которого мы зависим при использовании \\?\ путей устройств, потому что это то, что ограничено MAX_PATH, если длинные пути DOS не поддерживаются в текущем процессе.   -  person Eryk Sun    schedule 27.09.2019
comment
@RemyLebeau Я полагаю, что ваш оригинальный комментарий - настоящий ответ на мой вопрос. Ваш второй комментарий re. opt-in — это то, чего я хочу — я перевернул ключ реестра, но неправильно понял часть, касающуюся манифеста приложения. (Я думал, что это требование ИЛИ, а не требование И.) Я отправлю отдельный вопрос о том, как предоставить манифест приложения для моего приложения командной строки; хотя, если бы ответ появился здесь, я бы не стал жаловаться. ????   -  person arya    schedule 28.09.2019


Ответы (1)


Мне нужен был комментарий @RemyLebeau:

Я был удивлен, обнаружив, что он не отображает запись для конкретного вызова CreateFileW, который на самом деле превышает 260 символов и приводит к сбою моего приложения.

Потому что там нечего регистрировать. Вызов, скорее всего, будет отклонен на уровне API более высокого уровня, когда входные данные впервые проверяются, задолго до того, как они достигнут уровня файловой системы. Procmon регистрирует активность более низкого уровня, а не API более высокого уровня. Такие инструменты, как API Monitor, — это то, что вам нужно. Если у вас возникли проблемы с этим, задайте новый вопрос об этом.

Мое окончательное решение проблемы, вызвавшей это, заключалось в обновлении с base-4.11 до base-4.12, которое лучше обрабатывает пути Windows › 260 символов.

Я не думаю, что мне даже понадобится переключатель реестра.

person arya    schedule 29.09.2019
comment
Ссылка в этом ответе на самом деле не имеет смысла ... она просто ссылается на себя? Можете ли вы напрямую скопировать комментарий Реми, на который вы ссылались, в ответ? - person StayOnTarget; 07.07.2021
comment
Это постоянная ссылка SO на первый комментарий к вопросу. Ваш браузер может вести себя неправильно, если он не прокручивается до него при загрузке ссылки. - person arya; 08.07.2021
comment
Я отредактировал комментарий прямо в ваш ответ. Комментарии могут быть удалены без предупреждения. - person StayOnTarget; 08.07.2021