.NET 6 C# WPF 执行内嵌.ps1脚本及结果转DataTable实现问题
核心问题修复与功能实现
1. 现有代码致命问题修复
你当前代码的ConnectToExchange方法中使用了using块管理runspace和pipeline,会导致代码块执行结束后资源立即被释放,后续调用RunScript时拿到的都是已销毁的对象,直接删除这两处using即可,资源可以在类销毁时统一释放。
2. 依赖补充
如果还未安装PowerShell相关依赖,可通过NuGet安装Microsoft.PowerShell.SDK包适配.NET 6环境。
3. 完整实现代码
using System; using System.Data; using System.Linq; using System.Management.Automation.Runspaces; using System.Collections.ObjectModel; using System.Management.Automation; using System.Windows; public class PowerShellStuff : IDisposable { private readonly string PS_UserName = ""; private readonly string PS_Password = ""; private Runspace? runspace; private PowerShell? pipeline; private bool disposedValue = false; public void ConnectToExchange() { if (runspace != null && runspace.RunspaceStateInfo.State == RunspaceState.Opened) return; System.Security.SecureString securePassword = new System.Security.SecureString(); foreach (char c in PS_Password) { securePassword.AppendChar(c); } PSCredential credential = new(PS_UserName, securePassword); WSManConnectionInfo connectionInfo = new(new Uri("https://outlook.office365.com/powershell-liveid/"), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", credential) { AuthenticationMechanism = AuthenticationMechanism.Basic, MaximumConnectionRedirectionCount = 2 }; // 移除using,避免提前释放资源 runspace = RunspaceFactory.CreateRunspace(connectionInfo); pipeline = PowerShell.Create(); runspace.Open(); pipeline.Runspace = runspace; } // 原有参数化命令执行方法,适配SET类无返回值命令 public Collection<PSObject> RunScript(PSCommand command) { if (runspace == null) { try { ConnectToExchange(); } catch (Exception ex) { MessageBox.Show(ex.Message, "User Information", MessageBoxButton.OK, MessageBoxImage.Error); return new Collection<PSObject>(); } } if (runspace.RunspaceStateInfo.State != RunspaceState.Opened) runspace.Open(); pipeline.Commands.Clear(); Command newCommand = new Command(command.Commands[0].ToString()); foreach (var param in command.Commands[0].Parameters) { newCommand.Parameters.Add(param); } pipeline.Commands.AddCommand(newCommand); Collection<PSObject> results = new Collection<PSObject>(); try { results = pipeline.Invoke(); // 处理错误流 if (pipeline.HadErrors) { foreach (var error in pipeline.Streams.Error) { MessageBox.Show(error.ToString(), "PowerShell Error", MessageBoxButton.OK, MessageBoxImage.Error); } } } catch (Exception ex) { MessageBox.Show(ex.Message, "User Information", MessageBoxButton.OK, MessageBoxImage.Error); } return results; } // 新增:执行PS1脚本并返回DataTable public DataTable RunPs1ScriptToDataTable(string ps1Content) { DataTable dt = new DataTable(); if (string.IsNullOrWhiteSpace(ps1Content)) return dt; var results = RunScript(new PSCommand().AddScript(ps1Content)); if (results.Count == 0) return dt; // 自动生成列 var properties = results[0].Members.Where(m => m.MemberType == PSMemberTypes.NoteProperty || m.MemberType == PSMemberTypes.Property).ToList(); foreach (var prop in properties) { dt.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.Value.GetType()) ?? prop.Value.GetType()); } // 填充行 foreach (var psObj in results) { DataRow row = dt.NewRow(); foreach (var prop in properties) { row[prop.Name] = psObj.Properties[prop.Name]?.Value ?? DBNull.Value; } dt.Rows.Add(row); } return dt; } // 资源释放 protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { pipeline?.Dispose(); if (runspace != null && runspace.RunspaceStateInfo.State == RunspaceState.Opened) { runspace.Close(); runspace.Dispose(); } } disposedValue = true; } } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } }
4. 调用示例
执行内嵌PS1脚本获取DataTable
首先将项目中的.ps1文件属性设置为「嵌入的资源」,或者直接放到项目资源文件中,调用方式如下:
// 如果ps1放在Resources.resx中,直接读取字符串 using var psHelper = new PowerShellStuff(); DataTable dt = psHelper.RunPs1ScriptToDataTable(Resources.MyScript);
执行参数化SET类命令
和原有VB.NET写法一致:
using var psHelper = new PowerShellStuff(); PSCommand command = new PSCommand(); command.AddCommand("Set-User").AddParameter("Identity", "test@contoso.com").AddParameter("DisplayName", "Test User"); psHelper.RunScript(command);
内容的提问来源于stack exchange,提问作者Pawel
相关产品推荐
相关产品推荐

