简体   繁体   English

使用ProcessStartInfo重定向标准输出并提示输入UAC

[英]Redirect standard output and prompt for UAC with ProcessStartInfo

I'm working on a WPF application targeting .NET 3.0. 我正在开发针对.NET 3.0的WPF应用程序。 I need to call an exe which requires administrative privileges. 我需要调用一个需要管理特权的exe。 I can get the UAC to prompt for permission by using something like: 我可以使用以下方法让UAC提示许可:

ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.Verb = "runas";
startInfo.UseShellExecute = true;
startInfo.FileName = "target.exe";

Process p = new Process();
p.StartInfo = startInfo;
p.Start();

My problem is I need to redirect standard output, and doing so with UseShellExecute = true results in an exception stating that: 我的问题是我需要重定向标准输出,并且使用UseShellExecute = true这样做会导致异常,说明:

The Process object must have the UseShellExecute property set to false in order to redirect IO streams Process对象必须将UseShellExecute属性设置为false才能重定向IO流

However, setting it to false results in the UAC not prompting for permission and I get an exception stating: 但是,将其设置为false会导致UAC不提示许可,并且出现异常,说明:

The requested operation requires elevation 请求的操作需要提升

How can I redirect standard output and prompt for UAC? 如何重定向标准输出并提示输入UAC?

I have seen this similar question , however the solution is to use the app.manifest to give my application administrative privileges. 我已经看到了类似的问题 ,但是解决方案是使用app.manifest赋予我的应用程序管理权限。 This is something I cannot do due to requirements. 由于要求,这是我无法做到的。

UseShellExecute must be set to false to redirect IO, and to true to use the Verb property. UseShellExecute必须设置为false才能重定向IO,设置为true才能使用Verb属性。 So you can't. 所以你不能。

But this article seems do the magic, although I haven't tested it. 但是,尽管我尚未对其进行测试,但本文似乎具有魔力。

It's written in C++, but a wrapper API can easily be created to be called from C# by using DllImport . 它是用C ++编写的,但是可以使用DllImport轻松创建包装API以便从C#调用。


Note: If you want to pass data between the two programs and have access to the target program's source code, you can easily re-design you application to use Named Pipes instead of redirecting standard I/O. 注意:如果要在两个程序之间传递数据并有权访问目标程序的源代码,则可以轻松地重新设计应用程序以使用Named Pipes而不用重定向标准I / O。

There is another pretty simple solution: 还有另一个非常简单的解决方案:

If you want to run a child-executable elevated AND redirect the output (optionally including window hiding), then your main code must be running elevated too. 如果要运行子级可执行的提升权限并重定向输出(可选地包括窗口隐藏),那么您的主代码也必须运行提升权限。 This is a security requirement . 这是安全要求

To accomplish this: 要做到这一点:

  1. Manually edit your ´app.manifest´ in your project folder. 在项目文件夹中手动编辑“ app.manifest”。
  2. Find the comment regarding UAC Manifest Options, you will see the 3 examples of ´requestedExecutionLevel´. 找到有关UAC清单选项的注释,您将看到3个“ requestedExecutionLevel”示例。
  3. Under the comment, locate the tricky ´asInvoker´ which is currently enabled, and replace it with ´requireAdministrator´. 在评论下,找到当前启用的棘手的“ asInvoker”,并将其替换为“ requireAdministrator”。
  4. Restart Visual Studio in order to take into effect, and after re-building your app it should have the typical UAC shield icon. 重新启动Visual Studio以使其生效,并且在重新构建应用程序之后,它应该具有典型的UAC盾牌图标。

Now your code will run elevated, everything that it launches will be elevated too, and you can also capture output streams. 现在,您的代码将提升运行,其启动的所有内容也将提升,您还可以捕获输出流。 Here is an example in VB.NET: 这是VB.NET中的一个示例:

Dim startInfo As New ProcessStartInfo
startInfo.Verb = "runas"
startInfo.FileName = "subprocess-elevated.exe"
startInfo.Arguments = "arg1 arg2 arg3"
startInfo.WorkingDirectory = Environment.CurrentDirectory
startInfo.WindowStyle = ProcessWindowStyle.Hidden
startInfo.CreateNoWindow = True
Dim p As Process = New Process()
p.StartInfo = startInfo
p.StartInfo.UseShellExecute = False
p.StartInfo.RedirectStandardOutput = True
p.StartInfo.RedirectStandardError = True
p.Start()
Console.WriteLine(p.StandardOutput.ReadToEnd)
Console.WriteLine(p.StandardError.ReadToEnd)
p.WaitForExit()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM