为什么 RunDLL32 进程在 Windows 7 上提前退出?
在 Windows XP 和 Vista 上,我可以运行此代码:
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL bResult = FALSE;
ZeroMemory(&pi, sizeof(pi));
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
bResult = CreateProcess(NULL,
"rundll32.exe shell32.dll,Control_RunDLL modem.cpl",
NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL,
&si, &pi);
if (bResult)
{
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
并且它按我的预期运行,即,直到用户关闭调制解调器控制面板窗口后,WaitForSingleObject 才会返回。
在 Windows 7 上,相同的代码 WaitForSingleObject 立即返回(返回代码 0 表示对象发出了请求的状态信号)。
同样,如果我将它带到命令行,在 XP 和 Vista 上我可以运行
start /wait rundll32.exe shell32.dll,Control_RunDLL modem.cpl
,并且在关闭控制面板窗口之前它不会将控制权返回到命令提示符,但在 Windows 7 上它会立即返回。
这是 RunDll32 中的更改吗?我知道 MS 对 Windows 7 中的 UAC 中的 RunDll32 进行了一些更改,从这些实验来看,其中一项更改可能涉及生成一个附加进程来显示窗口,并允许原始进程退出。唯一让我认为情况可能并非如此的是,使用显示进程创建和销毁的进程资源管理器,我没有看到除了调用的 rundll32 进程本身之外还创建了任何其他内容。
我还有什么办法可以解决这个问题吗?我只是不希望该函数在控制面板窗口关闭之前返回。
On Windows XP and Vista, I can run this code:
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL bResult = FALSE;
ZeroMemory(&pi, sizeof(pi));
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
bResult = CreateProcess(NULL,
"rundll32.exe shell32.dll,Control_RunDLL modem.cpl",
NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL,
&si, &pi);
if (bResult)
{
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
and it operates as I would expect, i.e. the WaitForSingleObject does not return until the Modem Control Panel window has been closed by the user.
On Windows 7, the same code, WaitForSingleObject returns straight away (with a return code of 0 indicating that the object signalled the requested state).
Similarly, if I take it to the command line, on XP and Vista I can run
start /wait rundll32.exe shell32.dll,Control_RunDLL modem.cpl
and it does not return control to the command prompt until the Control Panel window is closed, but on Windows 7 it returns immediately.
Is this a change in RunDll32? I know MS made some changes to RunDll32 in Windows 7 for UAC, and it looks from these experiments as though one of those changes might have involved spawning an additional process to display the window, and allowing the originating process to exit. The only thing that makes me think this might not be the case is that using a process explorer that shows the creation and destruction of processes, I do not see anything additional being created beyond the called rundll32 process itself.
Any other way I can solve this? I just don't want the function to return until the control panel window is closed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果其他人遇到同样的问题:我终于在 Microsoft 技术支持的帮助下解决了这个问题。
他们能够确认原始 RunDll32 进程仍在运行(它没有生成新进程),但无论出于何种原因,他们不知道答案,WaitForSingleObject() 会立即在该进程上返回。
解决方法是使用 CPLApplet 以不同方式关闭控制面板窗口,如下例所示: http://support .microsoft.com/kb/232536
然而,由于 32 位调制解调器控制面板无法在 64 位 Windows 中运行(它会显示,但“添加”按钮不起作用),问题变得更加复杂。我已经在 64 位平台上的 RunDLL 解决方案中关闭了 WOW64 重定向,并且效果很好,但是您无法在 32 位应用程序中加载 64 位库,因此我必须生成一个新进程来执行此操作。
总之:
In case anyone else stumbles on the same problem: I finally worked around this with some help from Microsoft Tech Support.
They were able to confirm that the original RunDll32 process is still running (it hasn't spawned a new process) but for whatever reason that they don't know the answer to, WaitForSingleObject() is returning immediately on that process.
The workaround is to fire off the control panel window differently, using CPLApplet as in this example: http://support.microsoft.com/kb/232536
However the issue is complicated further by the fact that the 32-bit modem control panel doesn't work in 64-bit Windows (it displays but "Add" button has no effect). I was already turning off WOW64 redirection in my RunDLL solution on 64-bit platforms, and that worked fine, but you can't load a 64-bit library in a 32-bit app so I had to spawn a new process to do this.
In summary: