1

PowerShell 実行空間をホストする .NET アプリケーションで、UI に影響を与える PowerShell コマンドレットを使用できるように、ホスト アプリケーション関数をその実行空間にエクスポートすることはできますか?

私の目標は、実行時間の長い PowerShell スクリプトから進行状況メッセージをホスト アプリケーションの UI に報告できるようにすることです (PowerShell をホストしているため、コンソール ウィンドウがありません)。次のようなものを想像しています。

C#:

// Speculative pseudocode:

class ReportProgressCmdlet : Cmdlet { ... } // Reports a message on the UI.
...
myRunspace.Register(new ReportProgressCmdlet(myUI)); 

パワーシェル:

Report-Progress "Starting step 1." # UI shows "Starting step 1."
...
Report-Progress "Step 1 failed."

これは可能ですか?私が間違っている場合は、さまざまな解決策 (イベント?) を聞いて喜んでいます。次の質問をすべて読み、他の多くの質問も読みましたが、それらが私が探しているものではないと思います:

アプリケーション内から PowerShell に機能を公開する方法

Powershell コール アセンブリ デリゲート

プログラムで PSCmdlet を Powershell パイプラインに追加する方法は?

デリゲート コールバックとして .NET メソッドを提供する

4

2 に答える 2

0

更新: 以下でヒットした手法は、任意の GUI アクションに適していますが、私の目的 (クリーンアップされた形式で PowerShell 出力を表示する) では、カスタム PSHost、PSHostUserInterface、および PSHostRawUserInterface を実装する方が簡単であることがわかりました。サイド側はよりシンプルなままです (特注の出力 API ではなく、使い慣れた Write-Output、Write-Host、Write-Error などを使用します。これにより、ホストの外部でもスクリプトを実行する場合に備えて、スクリプトが柔軟に保たれます) . 良い例については、https://msdn.microsoft.com/en-us/library/ee706570%28v=vs.85%29.aspxを参照してください。


コマンドレットは間違ったアプローチであることが判明しました。その方法は、「SessionState」API を介して GUI オブジェクト インスタンスを PowerShell に公開し、PowerShell コードがそれらを直接使用できるようにすることです。方法は次のとおりです。

適切な名前空間を導入します。

using System.Management.Automation;
using System.Management.Automation.Runspaces;

次に、実行空間を作成し、GUI オブジェクト インスタンスを PowerShell 変数として挿入します。(ここでは、Messages コレクションを公開するビューモデルを渡していますが、実際にはより適切にレイヤー化することをお勧めします。) 実行空間を作成するときに、次のように 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) を使用して、Runspace を作成して開いた後にオブジェクト インスタンスを挿入できます。そのコードは同じですが、InitialSessionState を挿入する必要はありません。

Doug Finkeは、私が見つけた彼のスクリーンキャストからテクニックを学んだので、これの功績を認められています。

http://www.dougfinke.com/blog/index.php/2009/09/02/how-to-host-powershell-in-a-wpf-application/

于 2015-03-09T16:10:25.247 に答える