C++ 什么可能导致ShellExecute返回SE_ERR_OOM(错误8)?
我经常从本机C++/Win32应用程序调用ShellExecute,以执行最终用户从GUI中选择的任何shell项。项目是可执行文件/脚本或链接(.lnk)。在一些我仍然不清楚的情况下,下面的函数有时返回C++ 什么可能导致ShellExecute返回SE_ERR_OOM(错误8)?,c++,windows,winapi,out-of-memory,shellexecute,C++,Windows,Winapi,Out Of Memory,Shellexecute,我经常从本机C++/Win32应用程序调用ShellExecute,以执行最终用户从GUI中选择的任何shell项。项目是可执行文件/脚本或链接(.lnk)。在一些我仍然不清楚的情况下,下面的函数有时返回8(SE_ERR\u OOMerror;仅简要说明)。因此,不会执行该项。什么可能导致此错误 int doExecute(LPCTSTR file, LPCTSTR args, LPCTSTR workDir) { assert(file && *file); H
8
(SE_ERR\u OOM
error;仅简要说明)。因此,不会执行该项。什么可能导致此错误
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,但可能必须调用间接使用COM的Win32 API,因为它与shell交互非常频繁。在这些情况下,COM总是使用与上面所示相同的标志进行初始化
- 传递给
的标志是在MSDN推荐后盲目选择的(参见文档),而不是因为个人选择CoInitializeEx
- 这很少见
- 它只在一次或几次休眠后发生(我的应用程序总是在我的笔记本电脑上运行,我经常使用它)
- 调用
后立即调用始终返回ShellExecute
0
- 就我记忆所及,它总是在尝试执行
文件时发生,但并不总是同一个文件.lnk
- 快速查看机器上运行的
(sysinternals.com),不会显示任何内存使用峰值Process Explorer
- edit:我在这里发布之前做了最后一次测试,连续调用
200次。所有进程都是无错误生成的doExecute
- 将
调用替换为ShellExecuteEx
ShellExecuteEx
- 为每个新线程调用一次
,而不使用其CoInitializeEx
计数器部分。但保留了以下嵌套的counInitializeEx
-CoInitializeEx
对CoUninitialize
编辑:如果有人需要,只是为了确认问题不再发生,即使经过几个月的测试,应用了这些修改。如果需要正确的错误处理,请使用ShellExecuteEx。“我经常调用ShellExecute”。如果你不检查你启动和节流的过程发生了什么,那么这就在某个地方停止了。进程是迄今为止可以创建的最昂贵的操作系统对象。通常会耗尽的资源是内核的未分页内存池,当这种情况发生时,您确实会得到OOM。“系统内存不足”,尽可能描述。如果您仍然可以启动任务管理器,它应该显示许多活动进程。
doExecute
不调用。因此,在doExecute
返回后调用是没有意义的(请参见备注部分)。如果每个线程调用CoInitializeEx
和coInitialize
不止一次,我会尽量避免。大多数应用程序每个线程只调用一次coInitializeX
,许多应用程序从未调用coInitialize
@HansPassant,我忘了提到这一点,在这里发布之前,我做了一个测试,循环调用了200个doExecute
。所有进程都是在没有任何错误的情况下生成的。谢谢,我编辑了我的帖子。