Win 7/UAC 让我发疯。
在我的 C++ 应用程序中,我需要运行一个需要在 Windows 7 上进行提升的可执行文件。我想将其关闭并等待它完成,然后再继续。做到这一点最简单的方法是什么?
我通常通过 CreateProcess() 执行此类操作,但对于需要提升的可执行文件来说,它会失败。
我尝试通过 CreateProcess
使用 cmd.exe /c ...
运行,它可以工作,但会弹出一个丑陋的 cmd 终端窗口。
我读到 ShellExecute()
将允许提升,但在使用 ShellExecute()
时等待 exe 完成似乎并不容易。
像 system()
这样简单的东西可以工作吗?
任何其他想法将不胜感激!
Win 7/UAC is driving me crazy.
From within my C++ application, I need to run an executable that requires elevation on Windows 7. I want to fire this thing off and wait for it to finish before proceeding. What's the easiest way to do this?
I normally do this kind of thing via CreateProcess()
, but it fails for executables that require elevation.
I tried running using cmd.exe /c ...
through CreateProcess
, which works but pops up an ugly cmd terminal window.
I am reading that ShellExecute()
will allow elevation, but it doesn't appear to be easy to wait for the exe to finish when using ShellExecute()
.
Will something simple like system()
work?
Any other ideas are greatly appreciated!
发布评论
评论(3)
使用
ShellExecuteEx
,而不是ShellExecute
。此函数将为创建的进程提供句柄,您可以使用它来调用WaitForSingleObject
在该句柄上阻塞,直到该进程终止。最后,只需调用CloseHandle
进程句柄上的以将其关闭。示例代码(为了清晰和简洁,省略了大部分错误检查):
为
lpVerb
指定“runas”动词会导致 UAC 提升即将启动的应用程序。这相当于将应用程序清单中的权限级别设置为“requireAdministrator”。管理员和受限用户都需要提升 UAC。但值得注意的是,除非绝对必要,否则您应该更喜欢使用“标准”方式将清单添加到要启动的应用程序中,以指定其所需的执行级别。如果您选择这条路线,您只需将“open”作为
lpVerb
传递即可。示例清单如下所示:最后,确保应用程序中触发执行需要 UAC 提升的进程的任何元素是 相应标记。您的工作就是在用户界面中对此进行建模; Windows 不会为你处理它。这是通过在入口点上显示盾牌图标来完成的;例如:
; NBSP ;
Use
ShellExecuteEx
, rather thanShellExecute
. This function will provide a handle for the created process, which you can use to callWaitForSingleObject
on that handle to block until that process terminates. Finally, just callCloseHandle
on the process handle to close it.Sample code (most of the error checking is omitted for clarity and brevity):
Specifying the "runas" verb for the
lpVerb
is what causes UAC to elevate the application that's about to be launched. This is the equivalent of setting the permissions level in the application's manifest to "requireAdministrator". It will require UAC elevation for both an administrator and a limited user.But it's worth noting that unless absolutely necessary, you should prefer the "standard" way of adding a manifest to the application you want to launch that specifies its required execution level. If you go this route, you will simply pass "open" as the
lpVerb
. A sample manifest is shown below:Finally, make sure that whatever element in your application triggers execution of the process requiring UAC elevation is marked accordingly. It's your job to model this in the user interface; Windows doesn't handle it for you. This is done by displaying the shield icon on the entry point; for example:
您可以做的是为子进程“stdin”创建一个管道(就好像您要将输入重定向到该进程一样)并等待管道中断。
请注意,该进程不会真正接收重定向的输入。
例如,如果您尝试从未提升的命令提示符处执行操作,
您将看到提升,并且命令窗口将等待,直到您关闭单独的窗口。
What you can do is create a pipe for the child process "stdin" (as if you were to redirect the input to that process) and wait for the pipe to break.
Note that the process will not really receive the redirected input.
E.g. if you try from unelevated command prompt to do
you will see elevation and the command window will wait until you close the separate window.
要以提升的特权运行,需要启动此进程的进程具有提升的特权。这通常需要安全服务或已经运行的东西来启动您的进程。这是从 Vista 开始的改变。它与拥有启动进程的权限(通过 ACL 令牌)有关,并使用从启动进程继承的适当级别的特权来启动它。微软一直在努力让人们创建一个提升的流程来处理所有提升的功能需求,并将其余的保留在最低特权的用户空间中。自从 Vista 成为 Alpha 版本以来,我们就断断续续地这样做了。这很痛苦,但出于安全原因,微软希望您这样做。
顺便说一句,如果您从 Program Files 目录等安全位置启动应用程序,则 ShellExec 调用将不起作用。几年前在不得不迁移到服务模型之前尝试过这一点。
因此,要启动进程并绕过 UAC,唯一的方法是从已经具有继承安全权限的进程启动
To run with elevated privileged, requires that the process launching this has elevated privileged. This usually require a secure service or something already running to launch your process. This is a change starting with Vista. It has to do with having the authority (via your ACL tokens) to be able to launch a process and launch it with the appropriate level of privileged inherited from the launching process. Microsoft has been pushing hard to have people create an elevated process that handles all elevated functionality needs and leave the rest in least privileged user space. Been doing this off and on since Vista was Alpha. It's a pain, but the way Microsoft would prefer you to do things for security reasons.
By the way, the ShellExec call will not work if you are launching your app from a secure location like Program Files directory, etc. Tried that before having to move to the service model years ago.
So to launch your process and by pass UAC, the only way to do it is to launch from a process that already has the security privileged to inherit