有没有办法通过C#命令打开CMD作为Admin?

时间:2015-06-04 22:04:05

标签: c# cmd wmi admin

我有一个小命令,允许我从CMD查询信息,但它需要管理员权限(不是在我的应用程序级别,但在CMD级别)只有我走这条路线的原因是因为我无法获得WMI在我的生活中查询bitlocker设置,这个项目需要离开我的办公桌。

if (bitA.Text == "Bitlocker Available")
{               
    Process cmd2 = new Process();
    cmd2.StartInfo.Verb = "runas";
    cmd2.StartInfo.FileName = "cmd.exe";
    cmd2.StartInfo.Arguments = "/c ping 8.8.8.8";
    cmd2.StartInfo.UseShellExecute = false;
    cmd2.StartInfo.RedirectStandardOutput = true;
    cmd2.StartInfo.RedirectStandardError = true;
    cmd2.Start();
    //* Read the output (or the error)
    string output2 = cmd2.StandardOutput.ReadToEnd();
    bitB.Text = output2;
    cmd2.WaitForExit();
}

3 个答案:

答案 0 :(得分:2)

您可以通过将startInfo对象的Verb属性设置为' runas'来指示应该使用提升的权限启动新进程,如下所示:

startInfo.Verb = "runas";

这将导致Windows的行为就像使用"以管理员身份运行"从资源管理器启动进程一样菜单命令。将提示用户使用UAC确认他们想要这样做。

编辑:我看到你已经设置了这个动词。你在问你是否可以绕过UAC吗?这将是一种愚蠢的行为,否则病毒编写者等可以用一行代码绕过安全检查。

答案 1 :(得分:1)

正如我在评论中所说,问题在于" runas"动词要求UseShellExecute为true,但重定向要求UseShellExecute为false。这使问题变得棘手,但关键是启动一个流程作为管理员,你可以通过某种IPC进行通信,然后这个过程启动你想要重定向输出的任何进程。它甚至可以是相同的可执行文件,只是打开收到的参数。如果我正在编写库,我可能会将shim可执行文件嵌入到汇编资源中。以下是使用命名管道的简单示例:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using System.IO.Pipes;
using System.IO;

namespace AdminRedirect
{
    class Program
    {
        private static readonly int ProcessId = Process.GetCurrentProcess().Id;

        static void Main(string[] args)
        {
            bool isAdmin = IsAdministrator();
            Console.WriteLine("Id = {0}, IsAdmin = {1}", ProcessId, isAdmin);
            if (!isAdmin)
            {
                Console.WriteLine("Press any key to spawn the admin process");
                Console.ReadKey(intercept: true);
                string pipeName = "mypipe-" + Guid.NewGuid();
                Process cmd = new Process()
                {
                    StartInfo =
                    {
                        Verb = "runas",
                        Arguments = pipeName,
                        FileName = typeof(Program).Assembly.Location,
                        UseShellExecute = true
                    }
                };

                using (var pipeStream = new NamedPipeServerStream(pipeName))
                {
                    cmd.Start();
                    Console.WriteLine("Started {0}", cmd.Id);
                    pipeStream.WaitForConnection();
                    Console.WriteLine("Received connection from {0}", cmd.Id);
                    using (var reader = new StreamReader(pipeStream))
                    {
                        string line;
                        while((line = reader.ReadLine()) != null)
                        {
                            Console.WriteLine(line);
                        }
                    }                
                }

                Console.WriteLine("Hit any key to end");
                Console.ReadKey(intercept: true);
            }
            else
            {
                if (args.Length > 0)
                {
                    string pipeName = args[0];
                    Console.WriteLine("Opening client pipe: {0}", pipeName);
                    using (var pipeStream = new NamedPipeClientStream(pipeName))
                    {
                        pipeStream.Connect();
                        using (var writer = new StreamWriter(pipeStream))
                        {
                            StartChildProcess(writer);
                        }
                    }
                }
                else
                {
                    Console.WriteLine("We are admin and not piping, so just run");
                    StartChildProcess(Console.Out);
                    Console.WriteLine("Hit any key to end");
                    Console.ReadKey(intercept: true);
                }
            }
        }

        private static bool IsAdministrator()
        {
            WindowsIdentity identity = WindowsIdentity.GetCurrent();
            WindowsPrincipal principal = new WindowsPrincipal(identity);
            return principal.IsInRole(WindowsBuiltInRole.Administrator);
        }

        private static void StartChildProcess(TextWriter output)
        {
            var cmd = new Process()
            {
                StartInfo =
                {
                    FileName = "cmd.exe",
                    Arguments = "/c ping 8.8.8.8",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true
                }
            };
            cmd.Start();
            string procOutput = cmd.StandardOutput.ReadToEnd();
            output.Write("Id: {0}, Output:{1}", cmd.Id, procOutput);
        }
    }
}

答案 2 :(得分:0)

要使用runas,您必须UseShellExecute为真,但要使用任何重定向方法,您必须UseShellExecute为假。你不能同时拥有两者。

如果您需要重定向输出并同时提升,则必须执行以下步骤:

  1. 使用runasUseShellExecute = true启动另一个您控制 1 的流程,以生成提升的流程。
  2. 新流程以ping.exe启动UseShellExecute = false并重定向输出。
  3. 使用IPC的形式like WCF over named pipes,将升级的第二个流程的输出转发到非升级的第一个流程。
  4. 1:它可能是你的同一个EXE,但传递一些特殊的命令行参数将它置于这种新模式