using System.Diagnostics; using System.IO; namespace OneClickRun.Services; /// 定位 PowerShell 7(pwsh.exe)并构造脚本启动参数 public static class PowerShellLocator { /// 依次从 PATH、标准安装目录查找 pwsh.exe public static string? Find() { var pathVar = Environment.GetEnvironmentVariable("PATH") ?? string.Empty; foreach (var dir in pathVar.Split(';', StringSplitOptions.RemoveEmptyEntries)) { var candidate = Path.Combine(dir.Trim(), "pwsh.exe"); if (File.Exists(candidate)) return candidate; } var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); string[] candidates = { Path.Combine(programFiles, "PowerShell", "7", "pwsh.exe"), Path.Combine(localAppData, "Programs", "PowerShell", "7", "pwsh.exe"), }; foreach (var c in candidates) if (File.Exists(c)) return c; return null; } public static string? GetVersion(string? pwshPath) { if (string.IsNullOrEmpty(pwshPath) || !File.Exists(pwshPath)) return null; try { using var process = Process.Start(new ProcessStartInfo { FileName = pwshPath, Arguments = "-NoProfile -Command \"$PSVersionTable.PSVersion.ToString()\"", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, }); if (process == null) return null; var output = process.StandardOutput.ReadToEnd(); process.WaitForExit(5000); return string.IsNullOrWhiteSpace(output) ? null : output.Trim(); } catch (Exception ex) { Logger.Warn($"获取 PowerShell 版本失败: {ex.Message}"); return null; } } /// 构造 pwsh 启动参数(脚本路径加引号,兼容含空格路径) public static string BuildScriptArguments(string scriptPath, string? extraArgs) { var quoted = "\"" + scriptPath + "\""; return string.IsNullOrWhiteSpace(extraArgs) ? $"-NoProfile -ExecutionPolicy Bypass -File {quoted}" : $"-NoProfile -ExecutionPolicy Bypass -File {quoted} {extraArgs.Trim()}"; } }