【问题标题】:How to start a Process as administrator mode in C# [duplicate]如何在 C# 中以管理员模式启动进程 [重复]
【发布时间】:2023-04-09 22:01:01
【问题描述】:

我有一个 Visual Studio Windows 应用项目。我添加了代码来下载安装程序更新文件。下载完成后的安装程序需要管理员权限才能运行。我已经添加了一个清单文件。

当用户单击 DownloadUpdate.exe 时,UAC 会提示用户提供管理员权限。所以我假设在 DownloadUpdate.exe 中创建和调用的所有进程都将以管理员身份运行。所以我使用以下代码对我下载的文件进行了设置调用:

Process p = new Process();
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.FileName = strFile;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;

【问题讨论】:

  • 不,您不能假设从 DownloadUpdater.exe 运行的所有进程都以管理员模式运行。事实上,这将是一个可怕的安全漏洞。如果您运行另一个需要管理员权限的进程,则会再次提示用户。

标签: c# .net


【解决方案1】:

首先你需要包含在你的项目中

using System.Diagnostics;

之后,您可以编写一个通用方法,用于您想要使用的不同 .exe 文件。如下所示:

public void ExecuteAsAdmin(string fileName)
{
    Process proc = new Process();
    proc.StartInfo.FileName = fileName;
    proc.StartInfo.UseShellExecute = true;
    proc.StartInfo.Verb = "runas";
    proc.Start();
}

例如,如果您想执行 notepad.exe,那么您只需调用此方法:

ExecuteAsAdmin("notepad.exe");

【讨论】:

  • 如何执行管理员弹出的yes或no以及bat文件是否执行并需要按键关闭。
【解决方案2】:
 Process proc = new Process();                                                              
                   ProcessStartInfo info = 
                   new ProcessStartInfo("Your Process name".exe, "Arguments");
                   info.WindowStyle = ProcessWindowStyle.Hidden;
                   info.UseShellExecute =true;
                   info.Verb ="runas";
                   proc.StartInfo = info;
                   proc.Start();

【讨论】:

  • “参数”在 ProcessStartInfo 中不是强制性的,只有进程名称就足以启动进程。
【解决方案3】:

使用这个方法:

public static int RunProcessAsAdmin(string exeName, string parameters)
    {
        try {
            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
            startInfo.UseShellExecute = true;
            startInfo.WorkingDirectory = CurrentDirectory;
            startInfo.FileName = Path.Combine(CurrentDirectory, exeName);
            startInfo.Verb = "runas";
            //MLHIDE
            startInfo.Arguments = parameters;
            startInfo.ErrorDialog = true;

            Process process = System.Diagnostics.Process.Start(startInfo);
            process.WaitForExit();
            return process.ExitCode;
        } catch (Win32Exception ex) {
            WriteLog(ex);
            switch (ex.NativeErrorCode) {
                case 1223:
                    return ex.NativeErrorCode;
                default:
                    return ErrorReturnInteger;
            }

        } catch (Exception ex) {
            WriteLog(ex);
            return ErrorReturnInteger;
        }
    }

希望对你有帮助。

【讨论】:

  • 对调用BAT或CMD脚本有效?
【解决方案4】:

这里是以管理员身份运行过程的示例,没有 Windows 提示

  Process p = new Process();
  p.StartInfo.FileName = Server.MapPath("process.exe");
  p.StartInfo.Arguments = "";
  p.StartInfo.UseShellExecute = false;
  p.StartInfo.CreateNoWindow = true;
  p.StartInfo.RedirectStandardOutput = true;
  p.StartInfo.Verb = "runas";
  p.Start();
  p.WaitForExit();

【讨论】:

  • 这解决了我的问题!提示将来自其他人的答案。 UseShellExecute、CreateNoWindow 和 RedirectStandardOutput 的组合为我阻止了这种情况。
  • 这不能以管理员身份运行。如果您添加清单并请求提升权限,它仍然不起作用。
  • 它也不起作用,它要求我在从应用程序卸载窗口服务时输入管理员密码
【解决方案5】:

您可能需要将您的应用程序设置为 x64 应用程序。

IIS 管理单元仅适用于 64 位,不适用于 32 位,从 32 位应用程序生成的进程似乎是 32 位进程,64 位应用程序也是如此。

看:Start process as 64 bit

【讨论】:

    【解决方案6】:

    试试这个:

    //Vista or higher check
    if (System.Environment.OSVersion.Version.Major >= 6)
    {
       p.StartInfo.Verb = "runas";
    }
    

    或者,go the manifest route for your application

    【讨论】:

    • 请注意,如果没有p.StartInfo.UseShellExecute = true;,此答案可能无法使用。
    【解决方案7】:

    这是对您问题的明确回答: How do I force my .NET application to run as administrator?

    总结:

    右键项目->添加新项目->应用程序清单文件

    然后在该文件中更改如下一行:

    <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
    

    编译运行!

    【讨论】:

    • 如您所见,该行包含在@Hans Passant 的答案中。但是每次程序启动另一个程序时,只有那一行打开UAC的窗口吗?
    • 这非常适合我,谢谢
    【解决方案8】:

    这在我尝试时有效。我仔细检查了两个示例程序:

    using System;
    using System.Diagnostics;
    
    namespace ConsoleApplication1 {
      class Program {
        static void Main(string[] args) {
          Process.Start("ConsoleApplication2.exe");
        }
      }
    }
    

    using System;
    using System.IO;
    
    namespace ConsoleApplication2 {
      class Program {
        static void Main(string[] args) {
          try {
            File.WriteAllText(@"c:\program files\test.txt", "hello world");
          }
          catch (Exception ex) {
            Console.WriteLine(ex.ToString());
            Console.ReadLine();
          }
        }
      }
    }
    

    首先验证我得到了 UAC 炸弹:

    System.UnauthorizedAccessException: 访问路径'c:\program files\test.txt' 被拒绝。
    // 等等。

    然后在 ConsoleApplication1 中添加一个清单,其中包含以下语句:

        <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
    

    没有炸弹。还有一个我不能轻易删除的文件:) 这与之前在运行 Vista 和 Win7 的各种机器上的几次测试一致。启动的程序从启动程序继承安全令牌。如果 starter 已获得管理员权限,则启动的程序也拥有这些权限。

    【讨论】:

    • 无法删除?请详细说明,这听起来很熟悉。
    • @ArlenBeiler:他可能是指应用程序中的嵌入式清单,而不是磁盘上与可执行文件并排的 .exe.manifest 文件。
    • @ThomasW。我认为他指的是需要删除管理员权限的测试文件。如果我没记错的话,我已经多次遇到这种情况,通常需要进入安全选项卡并更改一些设置。我想我最终想出了一个办法。提升的命令提示符也可能有效,但要小心。时间有时会带来答案。 :-)
    【解决方案9】:
    var pass = new SecureString();
    pass.AppendChar('s');
    pass.AppendChar('e');
    pass.AppendChar('c');
    pass.AppendChar('r');
    pass.AppendChar('e');
    pass.AppendChar('t');
    Process.Start("notepad", "admin", pass, "");
    

    也适用于ProcessStartInfo:

    var psi = new ProcessStartInfo
    {
        FileName = "notepad",
        UserName = "admin",
        Domain = "",
        Password = pass,
        UseShellExecute = false,
        RedirectStandardOutput = true,
        RedirectStandardError = true
    };
    Process.Start(psi);
    

    【讨论】:

    • 好的,但是为什么要使用 AppendChar?你不能写pass="secret"吗?
    • 因为这是个秘密
    • @Jet 否,因为它需要一个安全字符串而不是字符串,并且这些永远不会作为内存中的 1 个未加密块提供
    • 假设你的密码是password,你可以for (int x = 0; x &lt; password.Length; x++) { pass.AppendChar(password[x]); }
    • @MarkRichman 违背了使用SecureString 的目的。 - 你应该从某个地方(即键盘或加密源等)一次读取一个字符。 -- 如果你有一个实际的string 无论如何都包含数据,那么它是不安全的。
    猜你喜欢
    • 1970-01-01
    • 2016-09-29
    • 2011-05-05
    • 1970-01-01
    • 2012-11-30
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多