在我的C ++应用程序中,我需要在Windows 7上运行需要提升的可执行文件。我想解决这个问题并等待它继续完成。最简单的方法是什么?
我通常会通过CreateProcess()
执行此类操作,但对于需要提升的可执行文件,它会失败。
我尝试使用cmd.exe /c ...
通过CreateProcess
运行,但它可以正常运行,但会弹出一个丑陋的cmd终端窗口。
我正在读ShellExecute()
允许提升,但在使用ShellExecute()
时等待exe完成似乎并不容易。
像system()
这样简单的东西会起作用吗?
非常感谢任何其他想法!
答案 0 :(得分:42)
使用 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提升即将启动的应用程序的原因。这相当于将应用程序清单中的权限级别设置为“requireAdministrator”。管理员和受限用户都需要UAC提升。
但值得注意的是,除非绝对必要,否则您应该更喜欢向要启动的应用程序添加清单的“标准”方式,以指定其所需的执行级别。如果你走这条路线,你只需将“开放”作为lpVerb
。示例清单如下所示:
<?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>
最后,确保应用程序中的任何元素触发执行需要UAC提升的进程marked accordingly。在用户界面中对此进行建模是您的工作; Windows无法为您处理它。这是通过在入口点上显示盾牌图标来完成的;例如:
答案 1 :(得分:0)
您可以做的是为子进程“stdin”创建一个管道(就像您将输入重定向到该进程一样)并等待管道中断。
请注意,该过程不会真正收到重定向的输入。
E.g。如果你尝试从无法使用的命令提示符
echo help | diskpart
您将看到高程,命令窗口将等待您关闭单独的窗口。
答案 2 :(得分:0)
要使用提升的特权运行,需要启动此进程的进程具有提升的特权。这通常需要安全的服务或已经运行的东西才能启动您的流程。这是从Vista开始的变化。它与拥有权限(通过您的ACL令牌)能够启动进程并使用从启动进程继承的适当级别的特权启动它有关。微软一直在努力让人们创建一个处理所有提升功能需求的高级流程,并将其余部分留在最不具有权限的用户空间中。自从Vista成为Alpha之后,一直在这样做。这是一种痛苦,但出于安全原因,微软希望你做的事情。
顺便说一下,如果你从Program Files目录等安全位置启动你的应用程序,那么ShellExec调用将不起作用。在多年前不得不转移到服务模型之前尝试过。
因此,要启动您的流程并通过UAC,唯一的方法是从已具有继承权限的流程启动