托管PowerShell:PowerShell与Runspace vs. RunspacePool与Pipeline

Jar*_*ger 17 powershell powershell-hosting

我试图在我的应用程序中添加一些相当有限的PowerShell支持:我希望能够定期运行用户定义的PowerShell脚本并显示任何输出,并且(最终)能够处理进度通知和用户提示请求.我并不需要命令行式的交互式支持,或(我认为),远程访问或同时运行多个脚本的能力,除非用户脚本做本身从shell我主内.我最终想要异步或在后台线程上运行脚本,并可能与种子一些初始变量和外壳,也许一个小命令但那是因为"看中",因为这功能是可能得到的.

我一直在阅读关于编写主机应用程序代码MSDN文档,但是它很乐意解释如何创建一个PowerShell对象,或者Runspace,或者RunspacePool,或者Pipeline,没有任何迹象表明为什么会选择这些方法而不是另一种方法.

我已经归结为这两个中的一个,但是我想要一些关于哪种方法更好的反馈意见:

PowerShell shell = PowerShell.Create();
shell.AddCommand(/* set initial state here? */);
shell.AddStatement();
shell.AddScript(myScript);
shell.Invoke(/* can set host! */);
Run Code Online (Sandbox Code Playgroud)

要么:

Runspace runspace = RunspaceFactory.CreateRunspace(/* can set host and initial state! */);
PowerShell shell = PowerShell.Create();
shell.Runspace = runspace;
shell.AddScript(myScript);
shell.Invoke(/* can set host here, too! */);
Run Code Online (Sandbox Code Playgroud)

(其中一个必需的PSHost类方法是EnterNestedPrompt(),我不知道我运行的用户定义的脚本是否会导致它被调用.如果可以,那么我将负责"开始一个新的嵌套输入循环"(按照此处)...如果这会影响上面的路径,那么这也是很好的.)

谢谢!

T-M*_*-Me 6

这些是什么?

  • 管道

管道是一种在 powershell 脚本内连接命令的方法。示例:您可以通过“管道”将输出从Get-ChildeItemto过滤掉Where-Object|

Get-ChildItem | Where-Object {$_}
Run Code Online (Sandbox Code Playgroud)
  • PowerShell对象

PowerShell 对象指的是 powershell 会话,就像启动 powershell.exe 时获得的会话一样。

  • 运行空间

每个 powershell 会话都有自己的运行空间(您始终会从 获得输出Get-Runspace)。它定义了 powershell 会话的状态。因此是InitialSessionState运行空间的对象/属性。您可能决定创建一个新的 powershell 会话,并在 powershell 内拥有自己的运行空间,以启用某种多线程。

  • 运行空间池

最后但并非最不重要的一点是 RunspacePool。正如其名称所示,它是一个运行空间(或 powershell 会话)池,可用于处理大量复杂的任务。一旦池中的一个运行空间完成其任务,它就可以执行下一个任务,直到一切完成。(10 个运行空间需要做 100 件事:平均每个运行空间处理 10 件事,但其中一个可能处理 8 个,而另外两个可能处理 11 个……)


什么时候用什么?

  • 管道

该管道用于插入脚本。它使构建复杂的脚本变得更加容易,并且应该尽可能经常使用。

  • PowerShell对象

当您需要新的 powershell 会话时,就会使用 powershell 对象。您可以在现有脚本(C# 或 Powershell)内部创建一个脚本。它对于轻松的多线程处理很有用。它将自行创建一个默认会话。

  • 运行空间

如果要创建非标准的 powershell 会话,可以在使用运行空间对象创建 powershell 会话之前对其进行操作。当您想要在额外的运行空间中共享同步变量、函数或类时,它非常有用。稍微复杂一点的多线程。

  • 运行空间池

就像之前提到的,它是一个用于繁重工作的重型工具。当一个脚本的执行需要几个小时并且您需要经常执行时。例如,与远程处理相结合,您可以同时在大型集群等的每个节点上安装某些内容。


Ser*_*x86 0

你想太多了。您在示例中显示的代码是一个好的开始。现在您只需要读取结果Invoke()并检查错误和警告流。

PowerShell 主机提供了一些 RunSpace 可以用来与用户通信的钩子,例如流和格式输出、显示进度、报告错误等。对于您想做的事情,您不需要 PowerShell 主机。您可以使用 PowerShell 类从脚本执行中读回结果、检查错误、警告、读取输出流并使用应用程序的功能向用户显示通知。这比编写整个 PowerShell 主机以在检测到错误时显示消息框更加简单和有效。

此外,PowerShell 对象在创建时就有一个运行空间,您不需要为其提供一个。如果您需要保留运行空间来保护环境,只需在每次调用 Invoke 后保留整个 PowerShell 对象并清除命令和所有流。

您应该问的下一个问题是如何处理PowerShell::Invoke()和 read的结果PowerShell::Streams