更新:我在下面提到的技术适用于任意 GUI 操作,但出于我的目的(以清理格式显示 PowerShell 输出),结果证明更容易实现自定义 PSHost、PSHostUserInterface 和 PSHostRawUserInterface,以便脚本侧保持更简单(您使用熟悉的 Write-Output、Write-Host、Write-Error 等,而不是一些定制的输出 API。这也使脚本保持灵活,以防您也想在主机之外运行它) . 有关一个很好的示例,请参阅https://msdn.microsoft.com/en-us/library/ee706570%28v=vs.85%29.aspx。
Cmdlet 被证明是错误的方法——要走的路是通过“SessionState”API 向 PowerShell 公开 GUI 对象实例,然后 PowerShell 代码可以直接使用这些。这是你如何做到的:
引入正确的命名空间:
using System.Management.Automation;
using System.Management.Automation.Runspaces;
然后创建一个运行空间并将您的 GUI 对象实例作为 PowerShell 变量注入。(在这里,我传递了一个公开消息集合的视图模型,但您可能希望在现实世界中更好地分层。)您可以在创建运行空间时使用 InitialSessionState,例如:
var iss = InitialSessionState.CreateDefault();
iss.Variables.Add(new SessionStateVariableEntry("thing", this.DataContext, "it's the data context"));
using (Runspace runspace = RunspaceFactory.CreateRunspace(iss))
{
runspace.ThreadOptions = PSThreadOptions.UseCurrentThread;
runspace.Open();
using (PowerShell ps = PowerShell.Create())
{
ps.Runspace = runspace;
ps.AddScript(@"$thing.Messages.Add('in which PowerShell can make stuff happen on the GUI via InitialSessionState')");
ps.Invoke();
}
runspace.Close();
}
或者,您可以在创建和打开运行空间后使用 Runspace.SessionStateProxy.SetVariable(name, object) 注入对象实例。那个代码是一样的,除了你不必注入 InitialSessionState。
Doug Finke得到了这个功劳,因为我从他的截屏视频中学到了这项技术,我发现:
http://www.dougfinke.com/blog/index.php/2009/09/02/how-to-host-powershell-in-a-wpf-application/