为什么在 Win 服务中调用 ShellExecute 会导致不相关的传入 COM 连接失败并显示 E_ACCESSDENIED?

Why does calling ShellExecute in Win Service cause unrelated incoming COM connections to fail with E_ACCESSDENIED?

我维护的产品有一个用 C++ 编写的 Windows 服务,该服务提供了一个 COM 接口,托管脚本环境(由 dllhost 托管)可以调用该接口,以便用户可以在 powershell 和让他们与服务接口。该服务维护几个继承自 IActiveScriptSite/IActiveScript 的 COM 类,以向托管环境提供此功能。

此功能已经运行良好一段时间了,但我们最近遇到了一个导致整个功能崩溃的错误。当在 IActiveScriptSite 接口上调用 OnStateChange() 函数时托管环境开始变得 E_ACCESSDENIED 时,该错误就显现出来了。这恰好是第一次调用接口。

在找出导致问题的更改后,我们最终发现可以通过在我们的服务初始化中调用一个 ShellExecute() 来重现整个问题,如下所示:

HRESULT CServiceObject::Run(int nShowCmd)
{
    ShellExecuteW(nullptr, nullptr, L"ipconfig", L"/all", nullptr, SW_HIDE);

    // Other initializeation code which ultimately 
    // leads to a thread which starts the hosted environment

这似乎与出现问题的代码完全不相关。

阅读 ShellExecute 文档引导我尝试:

所以,令人费解的是,ShellExecute 破坏了我们的整个服务。谁能想到在 运行 之后它可能会做什么影响程序的状态?我实际上可以通过不调用 ShellExecute() 来解决这个问题,但它担心一些如此微不足道且看似与其他代码无关的东西会破坏它所以我想了解问题所在。

这个问题原来是因为我们的代码在调用CoInitializeSecurity()。在此之前调用 ShellExecute() 会导致 CoInitializeSecurity() 安全性被隐式调用,然后当我们调用它时它会失败,这会阻止我们的托管脚本环境联系服务。