什么可能导致ShellExecute返回SE_ERR_OOM(错误8)

What could possibly cause ShellExecute to return SE_ERR_OOM (error 8)?

本文关键字:OOM ERR 错误 SE 返回 ShellExecute 什么      更新时间:2023-10-16

我经常从本地c++/Win32应用程序调用ShellExecute来执行最终用户从GUI中选择的任何shell项。项要么是可执行文件/脚本,要么是链接(. link)。在一些对我来说仍然模糊的条件下,下面的函数有时返回8 (SE_ERR_OOM错误;只有非常简短的记录)。因此,该项不会被执行。什么可能导致这个错误?

int doExecute(LPCTSTR file, LPCTSTR args, LPCTSTR workDir)
{
    assert(file && *file);
    HRESULT hRes = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
    assert(hRes == S_OK || hRes == S_FALSE);
    int code = (int)ShellExecute(NULL, NULL, file, args, workDir, SW_SHOWNORMAL);
    doLog("ShellExecute returned: %d, %u", code, GetLastError()); // EDIT
    CoUninitialize();
    return code;
}

的背景:

  • Windows8 64位,应用程序是32位,无法在任何其他机器上尝试
  • 应用是多线程的
  • 根据设计,总是专门创建一个新线程来执行此调用
  • 这段代码中的断言在我的调试会话期间从未中断
  • 应用程序本身不直接使用COM,但可能不得不调用Win32 api间接使用它,因为它与shell交互非常频繁。在这些情况下,COM总是使用与上面显示的相同的标志进行初始化。
  • 传递给CoInitializeEx的标志是在MSDN推荐后盲目选择的(参见ShellExecute文档),而不是因为个人选择

到目前为止关于bug的观察:

  • 很少
  • 它只发生在一次或几次休眠后(我的应用程序总是在我的笔记本电脑上运行,我经常使用它)
  • 调用ShellExecute后立即调用GetLastError总是返回0
  • 据我所知,它总是发生,而试图执行.lnk文件,但并不总是相同的文件
  • 快速查看在机器上运行的Process Explorer (sysinternals.com)没有显示任何内存使用峰值
  • 编辑:我通过连续200次调用doExecute在这里发布之前做了最后一次测试。

经过相当长时间的测试,在我按照@DavidHeffernan和@RossRidge的建议对代码进行了一些更改之后,这个错误再也没有发生过。虽然我不能真正认为这是一个明确的答案本身,因为我仍然不知道到底发生了什么,我还没有能够重现到目前为止的错误。

修改应用:

  • ShellExecute呼叫替换为ShellExecuteEx
  • 对每个新线程调用CoInitializeEx一次,不调用对应的CoUninitialize。但保留了以下嵌套的CoInitializeEx - CoUninitialize对。

编辑:以防有人需要它,只是为了确认问题不再发生,即使经过几个月的测试,有这些修改应用。