如何从 C# 运行 PowerShell 脚本
一篇关于从 C# 程序中嵌入和/或启动 PowerShell 脚本的文章。
引言
本文包含一个简单的示例,说明如何将 PowerShell 脚本添加到 C# 程序中。用电影中的话来说:“Shell 的力量迫使你!”
背景
随着 2006 年 11 月 Windows PowerShell 1.0 的发布,我们终于有了一个强大的 Windows 命令行 Shell,它甚至可以与常见的 Unix/Linux Shell(如 csh 和 bash)相媲美甚至超越它们。原因是 PowerShell 命令可以读取和写入对象,而不是只能处理文本字符串的传统 Shell。由于 PowerShell 在 .NET 平台上运行,因此使用的对象是 .NET 对象,这使其成为 .NET 程序的理想脚本语言。
必备组件
在编译示例代码之前,您需要准备一些东西。首先,当然,您必须安装 PowerShell 本身,您可以在以下位置找到它:PowerShell 主页。示例程序还引用了一些标准 PowerShell 安装未包含的程序集,因此您必须通过安装 Windows SDK for Windows Server 2008 and .NET Framework 3.5 来获取这些程序集。不用担心:即使后者名称中包含“Server 2008”,它也会安装在 Vista 和 XP 上。
Using the Code
要将 PowerShell 脚本添加到您的程序,您首先必须添加对 System.Management.Automation
程序集的引用。SDK 将此程序集安装在 C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0 目录中。
然后,您必须添加以下 'using
' 语句来导入所需的类型
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
以下代码块显示了执行所有繁重工作的 RunScript
方法。它接受脚本文本,执行它,并将结果作为字符串返回。
private string RunScript(string scriptText)
{
// create Powershell runspace
Runspace runspace = RunspaceFactory.CreateRunspace();
// open it
runspace.Open();
// create a pipeline and feed it the script text
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);
// add an extra command to transform the script
// output objects into nicely formatted strings
// remove this line to get the actual objects
// that the script returns. For example, the script
// "Get-Process" returns a collection
// of System.Diagnostics.Process instances.
pipeline.Commands.Add("Out-String");
// execute the script
Collection<psobject /> results = pipeline.Invoke();
// close the runspace
runspace.Close();
// convert the script result into a single string
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject obj in results)
{
stringBuilder.AppendLine(obj.ToString());
}
return stringBuilder.ToString();
}
如何让脚本与您的程序交互
在使用 pipeline.Invoke()
调用执行脚本之前,可以通过使用 runspace.SessionStateProxy.SetVariable("someName", someObject)
方法将程序的对象公开给脚本。这将创建一个脚本可以访问的命名变量(获取/设置属性,甚至调用方法)。例如,假设我们将示例的主窗体通过添加如下的 SetVariable()
调用公开给脚本
...
// open it
runspace.Open();
runspace.SessionStateProxy.SetVariable("DemoForm", this);
....
然后,以下脚本将打印窗口的标题
$DemoForm.Text
以下脚本将显示窗口的所有属性和方法
$DemoForm | Get-Member
但是请注意,脚本对您的对象的所有调用都将来自另一个线程上下文,因为 pipeline.Invoke()
似乎启动了自己的工作线程。这意味着您公开的对象必须是线程安全的。
关注点
作为一个额外的功能,我添加了将脚本拖放到表单上的能力,这样您就不必一直将 PowerShell 脚本复制粘贴到文本框中。
有关 PowerShell 的更多信息
- 有关如何处理脚本的异步执行的信息,请参阅我的第二篇 CodeProject PowerShell 文章。
- PowerShell 上的维基百科
历史
- 2007 年 4 月 1 日:首次发布
- 2007 年 4 月 4 日:小更新
- 2008 年 8 月 28 日:修复了 SDK 的链接和我的第二篇 powershell 文章的链接