Одна из причин, почему ShellExecute возвращает SE_ERR_ACCESSDENIED, а ShellExecuteEx возвращает ERROR_ACCESS_DENIED

Spread the love

Это перевод One possible reason why ShellExecute returns SE_ERR_ACCESSDENIED and ShellExecuteEx returns ERROR_ACCESS_DENIED. Автор: Реймонд Чен.

(этот странный заголовок написан для поисковой оптимизации)

Один клиент сообщил, что при вызове ShellExecute эта функция иногда завершалась с ошибкой SE_ERR_ACCESSDENIED (= 5) — в зависимости от того, что они пытались открыть (а если бы они использовали ShellExecuteEx, то они получали бы ошибку ERROR_ACCESS_DENIED (перевод поста)).

После долгой «игры в пинг-понг», проверки файловых ассоциаций и т.п., один из разработчиков из нашей команды использовал свой хрустальный шар и спросил: «А вы случайно не вызываете её из MTA?» (MTA = multi-threaded apartment, многопоточный апартмент).

«Да», — ответил клиент. — «ShellExecute вызывается из специально выделенного MTA-потока. Проблема в этом?».

Ну, вообще-то, да. И об этом явно сказано в документации к ShellExecute:

Поскольку ShellExecute может делегировать выполнение расширениям Оболочки (источникам данных, обработчикам контекстных меню, реализациям действий), которые активируются через COM, то COM должен быть инициализирован до того, как ваш код вызовет ShellExecute. Некоторые расширения Оболочки требуют, чтобы COM был инициализирован в однопоточном апартменте (STA).

Как правило, функции Оболочки требуют STA. Вспомните, что MTA подразумевает отсутствие интерфейса пользователя. Если вы попытаетесь использовать apartment-threaded объект из MTA-потока, вам потребуется маршаллер, а если такого маршаллера нет, то вызов провалится.

Это также объясняет, почему вызов ShellExecute завершается неудачей только для некоторых типов файлов: если обработка типа файла не требует создания объекта COM, то ситуация с несовпадением MTA/STA никогда не произойдёт.

Читать на сайте автора.

0 ответы

Ответить

Хотите присоединиться к обсуждению?
Не стесняйтесь вносить свой вклад!

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *