Win 7/UAC使我发疯。

从我的C++应用程序内部,我需要运行一个需要在Windows 7上进行提升的可执行文件。我想先将其放开并等待其完成再继续。最简单的方法是什么?

我通常通过CreateProcess()来执行这种操作,但是对于需要提升的可执行文件却无法执行。

我尝试通过cmd.exe /c ...使用CreateProcess运行,它可以运行,但会弹出一个难看的cmd终端窗口。

我正在阅读ShellExecute()将允许提升,但是使用ShellExecute()时似乎不容易等待exe完成。
system()这样简单的东西会起作用吗?

任何其他想法将不胜感激!

最佳答案

使用 ShellExecuteEx 而不是ShellExecute。此函数将为创建的进程提供一个句柄,您可以使用该句柄在该句柄上调用 WaitForSingleObject 来阻止该进程终止。最后,只需在进程句柄上调用 CloseHandle 即可将其关闭。

示例代码(为清楚起见,省略了大多数错误检查):

SHELLEXECUTEINFO shExInfo = {0};
shExInfo.cbSize = sizeof(shExInfo);
shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shExInfo.hwnd = 0;
shExInfo.lpVerb = _T("runas");                // Operation to perform
shExInfo.lpFile = _T("C:\\MyApp.exe");       // Application to start
shExInfo.lpParameters = "";                  // Additional parameters
shExInfo.lpDirectory = 0;
shExInfo.nShow = SW_SHOW;
shExInfo.hInstApp = 0;

if (ShellExecuteEx(&shExInfo))
{
    WaitForSingleObject(shExInfo.hProcess, INFINITE);
    CloseHandle(shExInfo.hProcess);
}

lpVerb指定“runas”动词是导致UAC提升将要启动的应用程序的原因。这等效于将应用程序 list 中的权限级别设置为“requireAdministrator”。管理员和受限用户都需要UAC提升权限。

但是,值得注意的是,除非绝对必要,否则您应该首选“标准”方式将 list 添加到要启动的应用程序中,以指定其所需的执行级别。如果走这条路线,您只需将“open”作为lpVerb传递。示例 list 如下所示:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
        <dependency>
                <dependentAssembly>
                        <assemblyIdentity
                                type="win32"
                                name="Microsoft.Windows.Common-Controls"
                                version="6.0.0.0"
                                processorArchitecture="X86"
                                publicKeyToken="6595b64144ccf1df"
                                language="*"
                        />
                </dependentAssembly>
        </dependency>
        <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
                <security>
                        <requestedPrivileges>
                                <requestedExecutionLevel
                                       level="requireAdministrator"
                                       uiAccess="false"/>
                        </requestedPrivileges>
                </security>
        </trustInfo>
</assembly>

最后,确保marked accordingly是应用程序中的任何元素触发需要UAC提升的过程的执行。在用户界面中对此建模是您的工作; Windows无法为您处理。这是通过在入口点上显示盾牌图标来完成的。例如:

09-10 04:31
查看更多