Как правильно выгрузить C++ Shell Extension DLL

У меня есть расширение оболочки DLL, написанные на C++ и COM. DLL зарегистрирована и загружена в память. Моя программа установки обновлений сделает следующее:

  • Отмените регистрацию расширения оболочки dll, убейте explorer.exe
  • Скопируйте более позднюю версию DLL расширения оболочки (Шаг 2)
  • Запустите файл explorer.exe

Работает нормально. Но проблема в следующем:

Если пользователь открыл какие-либо другие приложения ( Internet Explorer, иногда диспетчер задач Windows, блокнот и т. Д.), Шаг Шаг 2 не выполняется.

Есть ли способ закрыть все крючки расширения оболочки DLL при обновлении DLL.

В DLL я использую GetOverlayInfo, контекстное меню, подключение к базе данных и т. Д.

2 ответа

Решение

Проще говоря: не делайте этого (т.е. не выгружайте его принудительно). Вам нужно будет перечислить все процессы, в которых загружено ваше расширение оболочки, и затем "перезапустить" их. Это очень агрессивно и откровенно говоря: плохое поведение (для установщика). Это также требует особых привилегий, которые могут не понадобиться вашему установщику.

То, что большинство людей до сих пор, кажется, не знают о том, что MoveFile (а также MoveFileEx) можно использовать для перемещения DLL или EXE-файлов , которые в данный момент используются запущенным приложением.

Это подход, который использует установщик Windows. Вы когда-нибудь замечали папку \Config.msi в корне данного диска после установки некоторых .msi? Эта папка фактически содержит (перемещенные и обычно переименованные в какое-то уникальное "временное" имя) исходные файлы, которые были перемещены, но все еще использовались в то время. Затем они обычно планируются для удаления при загрузке (MoveFileEx с MOVEFILE_DELAY_UNTIL_REBOOT).

Вы можете использовать тот же механизм в установщике homebrew, переместить старый используемый файл из его исходного местоположения и сразу же переместить другой. Любой новый экземпляр приложения будет затем использовать новое расширение оболочки (*), в то время как старое будет продолжать использоваться любым из запущенных приложений, которые загрузили его в тот или иной момент.

(*) Я не уверен на 100% в этом из-за правил, которые применяются к загрузке DLL и не позволяют загружать модули с одинаковыми именами при некоторых обстоятельствах.

В зависимости от вашего установщика, вы можете использовать поддержку Restart Manager в Windows Vista+. Это позволит вашей установке запрашивать все приложения, использующие вашу DLL, и попытаться корректно завершить их работу. Если они не могут быть, то вам нужно будет зарегистрировать его для замены при перезагрузке. После завершения установки Диспетчер перезапуска попытается перезапустить все программы, которые он выключил (перезапуск поддержки).

Другие вопросы по тегам