我正在处理的应用程序中有一个非常令人沮丧的错误。该例程应该在一个窗口中执行某些操作,然后在方法结束时将焦点返回到另一个窗口,但是当我在前一天开始使用大型数据集时,焦点在结束时停止返回。我一次一行地执行代码,错误停止了。所以,我认为它是某种时间问题。我追查直到找到我怀疑是罪魁祸首。调用ShellExecute(...),终止我使用的图像编辑器。 (http://msdn.microsoft.com/en-us/library/bb762153(VS.85).aspx)
现在,如果我跳过此调用,然后继续运行该程序,一切正常,但如果我只是跑过这一行,则会发生错误。怎么会这样?我在这个方法的最后调用了SetFocus()。不管怎样,程序都不会打这个?
这一切都非常令人沮丧......
答案 0 :(得分:4)
首先应该明确的是Win32 API调用与windows / messages / focus等相关。不取决于时间。 每个线程都有自己的窗口/消息子系统,这里没有竞争条件。
你描述的是别的东西。您实际上启动了另一个与您同时运行的进程(应用程序)。
请注意,ShellExecute
是异步功能。它在创建流程后立即返回,从现在开始,您的应用程序和您创建的流程将同时运行。
现在,由于系统中只有一个窗口可能同时具有焦点 - 您创建的过程很可能只会从您那里窃取焦点。 为了避免这种情况,您应该先等待该过程完成工作,然后将焦点恢复到窗口并继续工作。
为此,您必须获取已创建进程的句柄,并在其上调用Win32等待函数。 ShellExecute
不会返回已创建进程的句柄。但是ShellExecuteEx
- 确实如此。
顺便说一句,它还允许您启动一个过程,其中包含不显示UI的说明,如果这是您想要的。
你应该这样写:
SHELLEXECUTEINFO sei;
memset(&sei, 0, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.lpFile = L"notepad.exe";
sei.nShow = SW_SHOWNORMAL; // or SW_HIDE if you don't want to show it
if (ShellExecuteEx(&sei))
{
// wait for completion
WaitForSingleObject(sei.hProcess, INFINITE);
CloseHandle(sei.hProcess);
}
这应该有用
P.S。当然,您应该关闭创建过程的句柄。也就是说,CloseHandle
之后必须调用WaitForSingleObject
。
答案 1 :(得分:0)
正如你所说,这个问题听起来像是时间问题。
我不熟悉ShellExecute函数,但是从你链接的页面开始:
“因为ShellExecute可以将执行委托给使用组件对象模型(COM)激活的Shell扩展(数据源,上下文菜单处理程序,动词实现),所以在调用ShellExecute之前应该初始化COM。一些Shell扩展需要COM单个 - 螺纹公寓(STA)类型。“
也许那是相关的?