вторник, 13 января 2015 г.

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

Это перевод 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 никогда не произойдёт.

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.