首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在运行具有C#中管理员权限的进程时,如何使用C#?

在运行具有C#中管理员权限的进程时,如何使用C#?
EN

Stack Overflow用户
提问于 2022-03-03 20:31:52
回答 2查看 356关注 0票数 0

我试图使用磁盘运行一个进程,但要做到这一点,我需要管理员权限,因为我在工作中使用了PC。为了以管理员身份运行进程,我需要Process.StartInfo.Verb = "runas“,还需要Process.StartInfo.UseShellExecute = true。当UseShellExecute设置为true时,我不能将命令传递到标准输入,但是如果我将其设置为false,我会收到一个错误,上面写着“请求的操作需要提升”(也就是我需要管理权限)。如果我尝试在Process.StartInfo.Arguments中传递一个脚本,它似乎什么也不做。下面是我到目前为止尝试过的代码的几个版本(其中没有一个有效):

第1版:

代码语言:javascript
运行
复制
Process p = new Process();
p.StartInfo.UseShellExecute = true;
p.StartInfo.FileName = @"C:\Windows\System32\diskpart.exe";
p.StartInfo.Verb = "runas";
p.StartInfo.Arguments = "vhdScript.txt";
p.Start();

第2版:

代码语言:javascript
运行
复制
Process p = new Process();
p.StartInfo.UseShellExecute = true;
p.StartInfo.FileName = @"C:\Windows\System32\diskpart.exe";
p.StartInfo.Verb = "runas";
p.StartInfo.Arguments = "/s vhdScript.txt";
p.Start();

第3版:

代码语言:javascript
运行
复制
Process p = new Process();
p.StartInfo.UseShellExecute = true;
p.StartInfo.FileName = @"C:\Windows\System32\cmd.exe";
p.StartInfo.Verb = "runas";
p.StartInfo.Arguments = "/c diskpart /s vhdScript.txt";
p.Start();

第4版:

代码语言:javascript
运行
复制
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = @"C:\Windows\System32\cmd.exe";
p.StartInfo.Verb = "runas";
p.StartInfo.Arguments = "/c diskpart";
p.StartInfo.RedirectStandardInput = true;
p.Start();
p.StandardInput.WriteLine("select vdisk 1");

有什么想法吗?谢谢。

EN

回答 2

Stack Overflow用户

发布于 2022-03-03 23:23:02

下面演示如何创建盘片脚本,然后使用System.Diagnostics.Process执行脚本。

Windows Forms App (.NET Framework) 创建一个新的项目(名称: ProcessDiskPartTest)

向项目添加应用程序说明

注意事项:它用于提示用户以管理员身份执行程序。

  • 在VS菜单中,单击Project
  • 选择添加新项.
  • 选择应用程序报表文件(仅Windows)(名称: app.manifest)
  • 单击添加

app.manifest,替换中

代码语言:javascript
运行
复制
<requestedExecutionLevel level="asInvoker" uiAccess="false" />

使用

代码语言:javascript
运行
复制
<requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />

使用语句添加以下内容

  • using System.IO;
  • using System.Diagnostics;

下面的代码将使用流程执行diskpart脚本。

代码语言:javascript
运行
复制
private void RunDiskPart(string arguments)
{
    string diskpartPath = Path.Combine(Environment.GetEnvironmentVariable("windir"), "System32", "diskpart.exe");

    if (!System.IO.File.Exists(diskpartPath))
        throw new Exception(String.Format("'{0}' doesn't exist.", diskpartPath));

    Debug.WriteLine("diskpartPath: " + diskpartPath);

    ProcessStartInfo psInfo = new ProcessStartInfo(diskpartPath);
    psInfo.Arguments = arguments;
    
    psInfo.CreateNoWindow = true;
    psInfo.RedirectStandardError = true; //redirect standard Error
    psInfo.RedirectStandardOutput = true; //redirect standard output
    psInfo.RedirectStandardInput = false;
    psInfo.UseShellExecute = false; //if True, uses 'ShellExecute'; if false, uses 'CreateProcess'
    psInfo.Verb = "runas"; //use elevated permissions
    psInfo.WindowStyle = ProcessWindowStyle.Hidden;
    
    //create new instance and set properties
    using (Process p = new Process() { EnableRaisingEvents = true, StartInfo = psInfo })
    {
        //subscribe to event and add event handler code
        p.ErrorDataReceived += (sender, e) =>
        {
            if (!String.IsNullOrEmpty(e.Data))
            {
                //ToDo: add desired code 
                Debug.WriteLine("Error: " + e.Data);
            }
        };

        //subscribe to event and add event handler code
        p.OutputDataReceived += (sender, e) =>
        {
            if (!String.IsNullOrEmpty(e.Data))
            {
                //ToDo: add desired code
                Debug.WriteLine("Output: " + e.Data);
            }
        };

        p.Start(); //start

        p.BeginErrorReadLine(); //begin async reading for standard error
        p.BeginOutputReadLine(); //begin async reading for standard output

        //waits until the process is finished before continuing
        p.WaitForExit();
    }
}

下面,演示如何将磁盘部分脚本添加为嵌入式资源。

为您的DiskPart脚本创建一个文件夹

  • 在VS菜单中,单击View
  • 选择解决方案资源管理器
  • 在解决方案资源管理器中,右击.选择添加。选择新建文件夹(名称: DiskPartScripts)

向项目添加DiskPart脚本

注意事项:下面的磁盘部分脚本仅用于测试。将其重命名为所需的名称,并将命令替换为所需的diskpart命令。

  • 在解决方案资源管理器中,右击DiskPartScripts文件夹.选择添加。选择新项目.
  • 选择文本文件(名称: DiskPartListDisk.txt)

DiskPartListDisk.txt

代码语言:javascript
运行
复制
list disk
list volume

使文本文件成为嵌入式资源

  • 在VS菜单中,单击View
  • 选择属性窗口
  • 在解决方案资源管理器中,单击"DiskpartListDisk.txt“
  • 在“属性”窗口中,设置“构建操作:嵌入式资源

下面的内容用于读取嵌入的文本文件。

创建一个类(名称: HelperLoadResource.cs)

HelperLoadResource.cs

代码语言:javascript
运行
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Reflection;
using System.Diagnostics;

namespace ProcessDiskPartTest
{
    public static class HelperLoadResource
    {
        public static string ReadResource(string filename)
        {
            //use UTF8 encoding as the default encoding
            return ReadResource(filename, Encoding.UTF8);
        }

        public static string ReadResource(string filename, Encoding fileEncoding)
        {
            string fqResourceName = string.Empty;
            string result = string.Empty;

            //get executing assembly
            Assembly execAssembly = Assembly.GetExecutingAssembly();

            //get resource names
            string[] resourceNames = execAssembly.GetManifestResourceNames();

            if (resourceNames != null && resourceNames.Length > 0)
            {
                foreach (string rName in resourceNames)
                {
                    if (rName.EndsWith(filename))
                    {

                        //set value to 1st match
                        //if the same filename exists in different folders,
                        //the filename can be specified as <folder name>.<filename>
                        //or <namespace>.<folder name>.<filename>
                        fqResourceName = rName;

                        //exit loop
                        break;
                    }
                }

                //if not found, throw exception
                if (String.IsNullOrEmpty(fqResourceName))
                {
                    throw new Exception($"Resource '{filename}' not found.");
                }

                //get file text
                using (Stream s = execAssembly.GetManifestResourceStream(fqResourceName))
                {
                    using (StreamReader reader = new StreamReader(s, fileEncoding))
                    {
                        //get text
                        result = reader.ReadToEnd();
                    }
                }
            }

            return result;
        }
    }
}

Note:"ReadResource“的代码来自这里

使用

代码语言:javascript
运行
复制
//temp filename that we'll use for diskpart
string diskpartScriptFilename = Path.Combine(Path.GetTempPath(), String.Format("diskpart_{0}.txt", System.Reflection.Assembly.GetExecutingAssembly().GetName().Name));

//get embedded diskpart script
string diskpartScript = HelperLoadResource.ReadResource("DiskpartListDisk.txt");

//write script to file
File.WriteAllText(diskpartScriptFilename, diskpartScript);

//execute script
RunDiskPart("/s " + diskpartScriptFilename);

if (File.Exists(diskpartScriptFilename))
    File.Delete(diskpartScriptFilename); //delete file

资源

票数 0
EN

Stack Overflow用户

发布于 2022-03-03 23:33:30

我遵循了本文中的一个建议-- UseShellExecute=false与高程的提高

当我使用下面的代码创建命令行exe并以管理员身份运行时,我将得到预期的结果。可能为你工作也可能不为你工作。(从示例中选择的VDISK 1语法是不正确的,因此我临时编写了)。这可能会有帮助

代码语言:javascript
运行
复制
using (Process p = new())
{
    p.StartInfo.UseShellExecute = false;
    p.StartInfo.FileName = @"C:\Windows\System32\diskpart.exe";
    p.StartInfo.Verb = "runas";
    //p.StartInfo.Arguments = "/c diskpart";
    p.StartInfo.RedirectStandardInput = true;

    p.Start();

    StreamWriter myStreamWriter = p.StandardInput;
    myStreamWriter.WriteLine("LIST DISK");
    myStreamWriter.Close();
    p.WaitForExitAsync();

}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71343454

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档