如何从C#直接调用PowerShell命令Do-Something(.NET Framework 4.5)
直接调用PowerShell命令对应的.NET DLL执行Do-Something操作
要直接调用C:\dosth.dll中的Do-Something命令(本质是.NET Cmdlet类),可以按以下步骤实现:
1. 加载目标程序集
注意C#中路径需要转义,使用@符号避免转义问题:
using System.Reflection; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Linq; // 加载DLL程序集 Assembly dosthAssembly = Assembly.LoadFrom(@"C:\dosth.dll");
2. 定位Do-Something对应的Cmdlet类
PowerShell命令Do-Something由带有CmdletAttribute的.NET类实现,属性中的VerbName和NounName分别对应命令的动词和名词部分:
// 查找匹配的Cmdlet类型 Type cmdletType = dosthAssembly.GetTypes() .FirstOrDefault(t => t.GetCustomAttribute<CmdletAttribute>() is CmdletAttribute attr && attr.VerbName.Equals("Do", StringComparison.OrdinalIgnoreCase) && attr.NounName.Equals("Something", StringComparison.OrdinalIgnoreCase)); if (cmdletType == null) { throw new InvalidOperationException("未找到Do-Something对应的Cmdlet类"); }
3. 构造Cmdlet实例并设置参数
Cmdlet的参数对应类的属性,带有ParameterAttribute标记。如果命令需要参数,直接给对应属性赋值即可:
// 创建Cmdlet实例 Cmdlet cmdletInstance = (Cmdlet)Activator.CreateInstance(cmdletType); // 示例:给命令的Path参数赋值(如果存在该参数) PropertyInfo pathParam = cmdletType.GetProperty("Path"); if (pathParam != null) { pathParam.SetValue(cmdletInstance, @"C:\target\file.txt"); }
4. 执行Cmdlet并处理结果
为保证Cmdlet在正确的PowerShell上下文执行,推荐使用Runspace和Pipeline方式,避免直接调用方法导致的上下文缺失问题:
using (Runspace runspace = RunspaceFactory.CreateRunspace()) { runspace.Open(); using (Pipeline pipeline = runspace.CreatePipeline()) { // 将Cmdlet实例加入执行管道 pipeline.Commands.Add(cmdletInstance); // 执行命令并获取输出结果 Collection<PSObject> results = pipeline.Invoke(); // 遍历输出结果 foreach (PSObject result in results) { Console.WriteLine(result.ToString()); } // 检查执行过程中的错误 if (pipeline.Error.Count > 0) { foreach (object error in pipeline.Error.ReadToEnd()) { Console.WriteLine($"执行错误:{error.ToString()}"); } } } }
注意事项
- 项目必须引用
System.Management.Automation程序集,可从PowerShell安装目录的GAC中获取,或通过NuGet包Microsoft.PowerShell.5.1.ReferenceAssemblies添加(针对.NET Framework 4.5)。 - 如果目标类继承自
PSCmdlet而非Cmdlet,上述代码同样适用,PSCmdlet依赖运行空间上下文,Runspace方式能满足其执行要求。 - 不要直接调用
cmdletInstance.ProcessRecord()执行,这种方式会缺少PowerShell的运行环境支持,容易引发异常。
内容的提问来源于stack exchange,提问作者BrandonStudio
相关产品推荐
相关产品推荐

