3

在 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 对 UAC 的 Windows 7 中的 RunDll32 进行了一些更改,从这些实验中看起来,其中一项更改可能涉及生成一个额外的进程来显示窗口,并允许原始进程退出。唯一让我认为情况可能并非如此的是,使用显示进程创建和销毁的进程资源管理器,我看不到除了调用的 rundll32 进程本身之外还有任何其他创建。

我还有什么办法可以解决这个问题吗?我只是不希望函数在控制面板窗口关闭之前返回。

4

1 回答 1

3

以防其他人偶然发现同样的问题:我终于在 Microsoft 技术支持的帮助下解决了这个问题。

他们能够确认原来的 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
于 2010-03-11T16:58:04.827 回答