在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进程本身之外创建的任何其他内容。
我能解决这个问题吗?我只是不希望函数返回,直到控制面板窗口关闭。
答案 0 :(得分:3)
如果其他人遇到同样的问题:我最终在微软技术支持的帮助下解决了这个问题。
他们能够确认原始RunDll32进程仍在运行(它没有生成新进程),但由于任何原因他们不知道答案,WaitForSingleObject()会立即返回该进程。
解决方法是以不同的方式触发控制面板窗口,使用CPLApplet,如下例所示:http://support.microsoft.com/kb/232536
然而,由于32位调制解调器控制面板在64位Windows中不起作用(显示但“添加”按钮无效),问题进一步复杂化。我已经在64位平台上的RunDLL解决方案中关闭了WOW64重定向,并且工作正常,但是您无法在32位应用程序中加载64位库,因此我必须生成一个新进程来执行此操作。
总结:
Win 7 64 bit: call CPLApplet via CreateProcess in 64-bit executable
Win 7 32 bit: call CPLApplet within my installer
XP / Vista 64 bit: turn off WOW64 redirection, use RunDll32
XP / Vista 32 bit: use RunDll32