使用的技术
语言:C#
脚本:cmd.exe 和命令
前端:WIN UI、Xaml
框架:.Net 5
- 我想从 c# 安装 10 个软件作为自动化过程。
- 目前要安装软件,我使用 cmd.exe 作为使用 C# Process 类的进程,这应该以管理员身份运行,否则我的安装将由于管理员权限而失败。
- 这里的问题是当我的自动化启动时,系统总是要求我弹出 UAC(用户帐户控制)来安装每个软件(我想总是跳过 UAC 弹出)。
查询:当我使用 cmd.exe 作为 C# 进程类的管理员时,如何避免此 UAC 弹出。
其他人提出的解决方案:在我的应用程序(WIN UI)启动时,创建一个单例进程,将 cmd.exe/powershell.exe 提升为管理员并使用此进程安装所有软件。(在这种情况下,我们将获得一次 UAC弹出,这没关系)。所以我可以调用这个进程/服务来执行我的所有命令,以避免 UAC 弹出,因为这个进程以管理员身份运行
为提议的解决方案尝试的方法:
public class CmdService : IDisposable
{
private Process _cmdProcess;
private StreamWriter _streamWriter;
private AutoResetEvent _outputWaitHandle;
private string _cmdOutput;
public CmdService(string cmdPath)
{
_cmdProcess = new Process();
_outputWaitHandle = new AutoResetEvent(false);
_cmdOutput = String.Empty;
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = cmdPath;
processStartInfo.UseShellExecute = false;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardInput = true;
processStartInfo.Verb = "runas";
processStartInfo.CreateNoWindow = true;
_cmdProcess.OutputDataReceived += _cmdProcess_OutputDataReceived;
_cmdProcess.StartInfo = processStartInfo;
_cmdProcess.Start();
_streamWriter = _cmdProcess.StandardInput;
_cmdProcess.BeginOutputReadLine();
}
public string ExecuteCommand(string command)
{
_cmdOutput = String.Empty;
_streamWriter.WriteLine(command);
_streamWriter.WriteLine("echo end");
_outputWaitHandle.WaitOne();
return _cmdOutput;
}
private void _cmdProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data == null || e.Data == "end")
_outputWaitHandle.Set();
else
_cmdOutput += e.Data + Environment.NewLine;
}
public void Dispose()
{
_cmdProcess.Close();
_cmdProcess.Dispose();
_streamWriter.Close();
_streamWriter.Dispose();
}
}
}
- 在这种方法中,由于 useShellExecute 设置为 false,cmd.exe 进程没有以管理员身份运行。
- 如果将 useShellExecute 设置为 false 进程在非管理员模式下运行,那么我的软件安装失败。
查询:在这种情况下如何以管理员身份运行 cmd.exe
方法 2:通过设置 useShellExecute = true; 创建一个以管理员身份打开 cmd.exe 的进程;
startInfo.FileName = "cmd.exe"; startInfo.Verb = "runas"; startInfo.UseShellExecute = true; startInfo.RedirectStandardInput = false; startInfo.Arguments = @"msiexec.exe /qn /norestart /i C:\Temp\somesoftware.msi INSTALLDIR=c:\tep\somesoftware ALLUSERS=1 REBOOT=ReallySupress /log C:\Logs\somesoftwarelog.txt"; var pro = new Process(); pro.StartInfo = startInfo; pro.Start();
问题:在这种方法中,由于 UseShellExecute 属性为 true,我无法通过标准输入执行命令。由于如果使用 UseShellExecute 为 true 存在限制,我们无法将标准输入/输出重定向到进程。
查询:当 UseShellExecute 为 true 时,我如何向 cmd.exe 提供输入命令
注意:由于 WIN UI ( https://github.com/microsoft/microsoft-ui-xaml/issues/3046 )中的问题,我无法以管理员身份运行我的 WIN UI 应用程序。