【问题标题】:Windows (COM) API behaving differently w/o specific libraryWindows (COM) API 在没有特定库的情况下表现不同
【发布时间】:2020-09-27 10:14:29
【问题描述】:

根据我是否链接到特定库,Windows API 的行为似乎有所不同。不幸的是,它是一个相当大的库,很难追踪问题,我不知道从哪里开始。

我可以为多个 API 重现此行为。例如,我使用基于 COM 的 shell API 来确定特定文件扩展名的“打开方式”应用程序。

CComPtr<IEnumAssocHandlers> enumerator;
HRESULT hr = SHAssocEnumHandlers(L".jpg", ASSOC_FILTER_RECOMMENDED, &enumerator);

for (CComPtr<IAssocHandler> handler; enumerator->Next(1, &handler, nullptr) == S_OK; handler.Release()) {
    CComHeapPtr<wchar_t> wAppName;
    handler->GetName(&wAppName);

    std::wcout << std::wstring(wAppName) << std::endl;
}

这在不执行任何其他操作的测试应用程序中完美运行。如果我链接到上述库,它会停止工作,而不是 UWP 应用程序条目,它只会打印 TWINUI
实际上打开应用程序然后使用IAssocHandler::Invoke 的行为也不同,在 Adob​​e Photoshop 的情况下,它会令人惊讶地让用户退出 Adob​​e 帐户(这始终是可重现的 - 也许由于不同的上下文而发挥了一些许可保护作用?)。
我过去遇到的另一个例子是 WIC(Windows Imaging Component)API,也是基于 COM 的,它返回有关编解码器不可用的错误(在最小测试中可用)。

所以问题是:是否存在可能导致这些问题的编译器标志或宏? (例如 WinSDK 版本控制)
我还能寻找什么?

提前致以诚挚的问候和感谢

【问题讨论】:

  • 没有“让 COM 做不同的事情” 编译器开关或预处理器宏。你将不得不产生一个minimal reproducible example
  • 可能是其他库初始化 COM 的方式与您的程序不同。
  • 你用什么调用来初始化 COM?
  • 我无法生成一个最小的可重现示例,因为库太大而不能轻易丢弃东西。这就是我寻找线索的原因。另一个库没有使用 COM,在我的应用程序中我使用 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); 来初始化 COM。此外,我的应用程序中的所有 API 调用都发生在应用程序(而不是库)专用的线程中。

标签: c++ windows winapi visual-c++ com


【解决方案1】:

原来是加载 OpenBLAS 库导致了这个问题。它甚至可以用一个最小的例子来重现:

// code in the original post --> works

LoadLibraryA("libopenblas.dll");
// not reproducible with LoadLibraryExA("libopenblas", NULL, DONT_RESOLVE_DLL_REFERENCES);
// to avoid calling DllMain

// code in the original post --> doesn't work

因此,OpenBLAS 库中的某些内容似乎破坏了 Windows API。令人惊讶的是,删除该库还修复了许多我们过去无法修复且乍一看似乎无关的其他问题。

虽然我们使用的是相当旧的版本(0.2.9;DYNAMIC_ARCH 启用),所以它可能会在以后的版本中修复,但由于我们不再需要 OpenBLAS,我还没有尝试过。

【讨论】:

猜你喜欢
  • 2013-10-15
  • 1970-01-01
  • 1970-01-01
  • 2013-02-18
  • 2019-03-02
  • 1970-01-01
  • 2023-04-03
  • 2019-01-23
  • 2010-11-05
相关资源
最近更新 更多