【问题标题】:Redirect standard output and prompt for UAC with ProcessStartInfo使用 ProcessStartInfo 重定向标准输出并提示 UAC
【发布时间】:2013-09-10 16:27:59
【问题描述】:

我正在开发一个面向 .NET 3.0 的 WPF 应用程序。我需要调用一个需要管理权限的 exe。我可以让 UAC 使用类似的方式提示许可:

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

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

我的问题是我需要重定向标准输出,并且使用UseShellExecute = true 这样做会导致异常说明:

Process 对象的 UseShellExecute 属性必须设置为 false 为了重定向 IO 流

但是,将其设置为 false 会导致 UAC 不提示许可,并且我收到异常说明:

请求的操作需要提升

如何重定向标准输出并提示 UAC?

我见过this similar question,但是解决方案是使用 app.manifest 授予我的应用程序管理权限。由于要求,这是我无法做到的。

【问题讨论】:

  • 基于我在许多应用程序中看到的有关特殊运行属性的行为(例如,作为 shell),我假设 UAC 在这些情况下不会按设计提示。根据您的描述,这是我可以右键单击并以管理员身份运行的程序。
  • 您可以编写一个实用程序 ElevateRedir.exe 来帮助您。例如,“ElevateRedir.exe /port 54321 /path Target.exe”。 ElevateRedir 将使用通过 STDOUT 重定向接收的套接字将来自 Target.exe 的输出发送回您的应用程序。您将以管理员身份启动 ElevateRedir,它可以启动 Target.exe(我相信现在不需要 runas,因为父进程是管理员)。重定向它的标准输出,并通过预定义的套接字端口将其转发到您的应用程序。您的初始应用程序只需要侦听 TCP 端口即可获得输出
  • 你能测试名称管道吗?或者你可以测试 UseShellExecute =, true and Verb = runas, and process.ErrorDataReceived += actionWriteEvent ?或者您可以测试@Alan 解决方法

标签: c# wpf


【解决方案1】:

还有一个非常简单的解决方案:

如果您想运行提升的子可执行文件并重定向输出(可选地包括窗口隐藏),那么您的主代码也必须运行提升。这是安全requirement

要做到这一点:

  1. 在您的项目文件夹中手动编辑您的app.manifest
  2. 找到关于 UAC Manifest Options 的评论,您将看到 requestedExecutionLevel 的 3 个示例。
  3. 在评论下,找到当前已启用的棘手asInvoker,并将其替换为requireAdministrator
  4. 重新启动 Visual Studio 以使其生效,并且在重新构建您的应用后,它应该具有典型的 UAC 盾牌图标。

现在您的代码将运行提升,它启动的所有内容也将提升,您还可以捕获输出流。这是 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()

【讨论】:

    【解决方案2】:

    UseShellExecute 必须设置为 false 才能重定向 IO,true 才能使用 Verb 属性。所以你不能。

    但是this article 似乎有魔力,虽然我还没有测试过。

    它是用 C++ 编写的,但可以通过使用 DllImport 轻松创建包装 API 以从 C# 中调用。


    注意:如果您想在两个程序之间传递数据并访问目标程序的源代码,您可以轻松地重新设计您的应用程序以使用 Named Pipes 而不是重定向标准 I/O。

    【讨论】:

    • 恕我直言,命名管道的测试和调试更复杂。也许没有重定向和使用 Trace.Writeline 到文件,不是更好更简单?当然,我是新手,我没有使用命名管道的良好做法。
    猜你喜欢
    • 2012-08-15
    • 2014-01-20
    • 2011-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-28
    • 1970-01-01
    相关资源
    最近更新 更多