从多线程单元调用 shell 函数和接口

从已初始化为多线程单元的线程调用或访问 shell 函数或 shell 接口时,函数或接口的功能可能受损或完全失败。

原始版本: Windows shell 和接口
原始 KB 编号: 287087

原因

调用 允许 CoInitializeEx (COINIT_MULTITHREADED) 在任何线程上运行对调用线程上创建的对象的调用。 从多线程单元访问使用单元线程模型的对象时,COM 将同步对对象的访问。 为了进行此同步,COM 必须封送对 对象的调用。 由于 shell 当前未通过类型库或代理/存根代码提供必要的信息,以便将其对象封送,因此尝试从多线程单元访问 shell 对象失败。

可能影响 shell 函数的调用

下面是对 的调用 CoInitializeEx (COINIT_MULTITHREADED) 如何影响依赖于 shell 对象的函数的示例:

  • GetOpenFileName/GetSaveFileName

    用户可以通过“打开和另存为”对话框导航到命名空间扩展文件夹,例如“我的文档”。 但是,无法浏览到这些文件夹,因为浏览器无法创建所需的接口,例如 IShellFolder

  • ShellExecute/ShellExecuteExecuteEx

    ShellExecute可以通过实现 IShellExecuteHook 接口来编写挂钩以扩展 或 ShellExecuteEx 的功能ShellExecute。 调用 或 ShellExecuteExShellExecute,无法加载已注册ShellExecute的挂钩。

在这两个示例中,尝试获取指向具有 CoCreateInstanceIUnknown::QueryInterface等的 shell 对象的接口指针的组件在从多线程单元调用时通常会失败并显示错误 E_NOINTERFACE 。 如上所述,原因是请求的对象没有类型信息或代理/存根代码。

References

进程、线程和单元