C# .NET项目中如何等待已启动的高权限PowerShell进程退出?
问题:C#中等待高权限PowerShell实例关闭后再继续执行代码
我在C#中编写了如下函数:
public static void RunPowerShellScriptFromElevatedPowerShell(string strPowerShellScriptFileName) { Console.WriteLine($"Running powershell script from elevation: {strPowerShellScriptFileName}"); string strCallPowerShellCommand = "powershell.exe"; string command = $"-ExecutionPolicy Bypass -File {CDataAccess.Instance.ReadLocalParam(CDataAccess.ELocalParamList.E_SCRIPT_REPO_PATH)}\\{strPowerShellScriptFileName} {CDataAccess.Instance.ReadLocalParam(CDataAccess.ELocalParamList.E_SCRIPT_REPO_PATH)}"; Process process = Process.Start("powershell", $"cd '{CDataAccess.Instance.ReadLocalParam(CDataAccess.ELocalParamList.E_MANIFEST_REPO_PATH)}';Start-Process {strCallPowerShellCommand} '{command}' -Verb runAs"); process.WaitForExit(); }
运行该函数时,尽管PowerShell脚本仍在运行,代码却继续执行。如何修改才能让代码等待高权限PowerShell实例关闭后再继续?
注:我认为这并非《How to tell PowerShell to wait for each command to end before starting the next?》的重复问题,因为该问题及我在StackOverflow找到的其他相关问题均未涉及高权限Shell场景,而本次场景为高权限,存在差异。我已知晓这些问题,但它们无法解决我的需求,恳请不要标记为重复问题。
解决方案
你的代码核心问题是:Process.Start启动的是普通权限的PowerShell进程,这个进程仅执行Start-Process启动高权限实例后就直接退出了,所以WaitForExit()等待的是这个普通权限进程,而非你实际需要等待的高权限PowerShell实例。
方案一:给Start-Process添加-Wait参数
让中间的普通权限PowerShell进程等待高权限实例关闭后再退出,这样C#代码就能正确等待到目标进程结束:
public static void RunPowerShellScriptFromElevatedPowerShell(string strPowerShellScriptFileName) { Console.WriteLine($"Running powershell script from elevation: {strPowerShellScriptFileName}"); string scriptRepoPath = CDataAccess.Instance.ReadLocalParam(CDataAccess.ELocalParamList.E_SCRIPT_REPO_PATH); string manifestRepoPath = CDataAccess.Instance.ReadLocalParam(CDataAccess.ELocalParamList.E_MANIFEST_REPO_PATH); string strCallPowerShellCommand = "powershell.exe"; // 给路径添加引号,避免路径含空格时出错 string command = $"-ExecutionPolicy Bypass -File \"{scriptRepoPath}\\{strPowerShellScriptFileName}\" \"{scriptRepoPath}\""; // 给Start-Process添加-Wait参数,强制等待高权限进程结束 Process process = Process.Start("powershell", $"cd '{manifestRepoPath}';Start-Process {strCallPowerShellCommand} -ArgumentList '{command}' -Verb runAs -Wait"); process.WaitForExit(); }
方案二:直接在C#中启动高权限PowerShell(更简洁)
跳过中间的普通权限PowerShell进程,直接用C#的ProcessStartInfo配置高权限启动:
using System.Diagnostics; using System.IO; public static void RunPowerShellScriptFromElevatedPowerShell(string strPowerShellScriptFileName) { Console.WriteLine($"Running powershell script from elevation: {strPowerShellScriptFileName}"); string scriptRepoPath = CDataAccess.Instance.ReadLocalParam(CDataAccess.ELocalParamList.E_SCRIPT_REPO_PATH); string manifestRepoPath = CDataAccess.Instance.ReadLocalParam(CDataAccess.ELocalParamList.E_MANIFEST_REPO_PATH); string fullScriptPath = Path.Combine(scriptRepoPath, strPowerShellScriptFileName); string arguments = $"-ExecutionPolicy Bypass -File \"{fullScriptPath}\" \"{scriptRepoPath}\""; ProcessStartInfo startInfo = new ProcessStartInfo("powershell.exe", arguments) { Verb = "runAs", // 启用高权限 WorkingDirectory = manifestRepoPath, UseShellExecute = true // 必须设为true,否则Verb参数无效 }; Process process = Process.Start(startInfo); process.WaitForExit(); }
内容的提问来源于stack exchange,提问作者Eyal Gerber
相关产品推荐
相关产品推荐

