单文件发布时PowerShell.Invoke()抛出异常,求解决方案
.NET6单文件发布PowerShell.SDK依赖应用时Invoke()异常的解决办法
我需要制作一个单EXE格式的命令行应用,依赖Microsoft.PowerShell.SDK包。调试模式下运行正常,但单文件发布后,创建PowerShell对象调用Invoke()方法时抛出异常,使用的是.NET6和最新版PowerShell.SDK。
不同SDK版本的错误信息
Microsoft.PowerShell.SDK 7.0.0版本错误
Unhandled exception. System.TypeInitializationException: The type initializer for 'System.Management.Automation.PSVersionInfo' threw an exception. ---> System.ArgumentException: The path is empty. (Parameter 'path') at System.IO.Path.GetFullPath(String path) at System.Diagnostics.FileVersionInfo.GetVersionInfo(String fileName) at System.Management.Automation.PSVersionInfo..cctor() --- End of inner exception stack trace --- at System.Management.Automation.PSVersionInfo.get_GitCommitId() at Microsoft.PowerShell.Telemetry.ApplicationInsightsTelemetry.SendPSCoreStartupTelemetry(String mode) at Microsoft.PowerShell.Telemetry.ApplicationInsightsTelemetry.SendTelemetryMetric(TelemetryType metricId, String data) at System.Management.Automation.PowerShell..ctor(PSCommand command, Collection`1 extraCommands, Object rsConnection) at System.Management.Automation.PowerShell.Create() at LanguageStickRemover.SettingsReader.GitConnector(String commandType, String pathToRepo) at LanguageStickRemover.SettingsReader.ReadSettings() at LanguageStickRemover.Program.Main(String[] args)
Microsoft.PowerShell.SDK 7.2.6版本错误
Unhandled exception. System.TypeInitializationException: The type initializer for 'System.Management.Automation.ExperimentalFeature' threw an exception. ---> System.TypeInitializationException: The type initializer for 'System.Management.Automation.Configuration.PowerShellConfig' threw an exception. ---> System.ArgumentNullException: Value cannot be null. (Parameter 'path1') at System.IO.Path.Combine(String path1, String path2) at System.Management.Automation.Configuration.PowerShellConfig..ctor() at System.Management.Automation.Configuration.PowerShellConfig..cctor() --- End of inner exception stack trace --- at System.Management.Automation.ExperimentalFeature..cctor() --- End of inner exception stack trace --- at System.Management.Automation.Runspaces.InitialSessionState.AddVariables(IEnumerable`1 variables) at System.Management.Automation.Runspaces.InitialSessionState.CreateDefault() at System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(PSHost host) at System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace() at System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace rsToUse, Boolean isSync) at System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings) at System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings) at System.Management.Automation.PowerShell.Invoke(IEnumerable input, PSInvocationSettings settings) at System.Management.Automation.PowerShell.Invoke() at LanguageStickRemover.SettingsReader.GitConnector(String commandType, String pathToRepo) at LanguageStickRemover.SettingsReader.ReadSettings() at LanguageStickRemover.Program.Main(String[] args)
我的PowerShell调用代码
private static void GitConnector(string commandType, string pathToRepo) { using (PowerShell ps = PowerShell.Create()) { ps.AddCommand("param([string]$command, [string]$pathToRepo)") .AddCommand("if($command -eq \"clone\")") .AddCommand("{git clone $pathToRepo}") .AddCommand("if($command -eq \"pull\")") .AddCommand("{git pull}") .AddParameter("command", commandType) .AddParameter("pathToRepo", pathToRepo) .Invoke(); } }
可行的解决方案
1. 调整项目发布配置
单文件发布时需要确保PowerShell的原生依赖被正确包含并可提取,修改项目文件(.csproj)添加以下配置:
<PropertyGroup> <PublishSingleFile>true</PublishSingleFile> <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract> <SelfContained>true</SelfContained> <RuntimeIdentifier>win-x64</RuntimeIdentifier> <!-- 根据目标平台调整,比如linux-x64、osx-x64 --> </PropertyGroup>
或者使用命令行发布时添加参数:
dotnet publish -c Release -r win-x64 /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true /p:SelfContained=true
2. 禁用PowerShell遥测
在创建PowerShell对象前添加环境变量,避免遥测模块因路径问题报错:
// 在GitConnector方法开头添加 Environment.SetEnvironmentVariable("POWERSHELL_TELEMETRY_OPTOUT", "1");
3. 指定自包含文件提取目录
设置DOTNET_BUNDLE_EXTRACT_BASE_DIR环境变量,让单文件应用的依赖文件提取到指定目录,解决PowerShell配置文件路径为空的问题:
// 在程序启动时添加 string extractDir = Path.Combine(AppContext.BaseDirectory, "ps_extract"); Directory.CreateDirectory(extractDir); Environment.SetEnvironmentVariable("DOTNET_BUNDLE_EXTRACT_BASE_DIR", extractDir);
4. 优化PowerShell命令调用方式
原代码的AddCommand方式存在语法问题,改用AddScript更规范,同时添加错误捕获:
private static void GitConnector(string commandType, string pathToRepo) { Environment.SetEnvironmentVariable("POWERSHELL_TELEMETRY_OPTOUT", "1"); using (PowerShell ps = PowerShell.Create()) { string script = @" param([string]$command, [string]$pathToRepo) if ($command -eq 'clone') { git clone $pathToRepo } if ($command -eq 'pull') { git pull } "; ps.AddScript(script) .AddParameter("command", commandType) .AddParameter("pathToRepo", pathToRepo); try { var results = ps.Invoke(); // 处理PowerShell内部错误 if (ps.HadErrors) { foreach (var error in ps.Streams.Error) { Console.WriteLine($"PowerShell执行错误: {error.ToString()}"); } } } catch (Exception ex) { Console.WriteLine($"调用异常: {ex.ToString()}"); } } }
5. 升级PowerShell.SDK版本
尝试升级到最新稳定版的Microsoft.PowerShell.SDK(如7.4+),新版本对单文件发布的兼容性更好。
内容的提问来源于stack exchange,提问作者k1t3k
相关产品推荐
相关产品推荐

