InvokePowerShell アクティビティの使用
このトピックの内容は、Windows Workflow Foundation 4 に該当します。
InvokePowerShell サンプルでは、InvokePowerShell
アクティビティを使用して Windows PowerShell コマンドを呼び出す方法を示します。
使用例
Windows PowerShell コマンドの簡便さと革新性。
Windows PowerShell の出力パイプラインから値を取得してワークフロー変数に格納する。
実行するコマンドのための入力パイプラインとして Windows PowerShell にデータを渡す。
![]() |
---|
サンプルは、既にコンピューターにインストールされている場合があります。続行する前に、次の (既定の) ディレクトリを確認してください。
<InstallDrive>:\WF_WCF_Samples
このディレクトリが存在しない場合は、「.NET Framework 4 向けの Windows Communication Foundation (WCF) および Windows Workflow Foundation (WF) のサンプル」にアクセスして、Windows Communication Foundation (WCF) および WF のサンプルをすべてダウンロードしてください。このサンプルは、次のディレクトリに格納されます。
<InstallDrive>:\WF_WCF_Samples\WF\Scenario\ActivityLibrary\PowerShell
|
説明
このサンプルには次の 3 つのプロジェクトが含まれています。
プロジェクト名 | 説明 | メイン ファイル |
---|---|---|
CodedClient |
PowerShell アクティビティを使用するサンプル クライアント アプリケーション。 |
|
DesignerClient |
|
|
PowerShell |
|
アクティビティのファイル
デザイナーのファイル:
|
PowerShell アクティビティの使用方法を把握しているとその内部機能を理解しやすくなるため、クライアント プロジェクトから先に説明します。
このサンプルの使用
以降では、このサンプルの 3 つのプロジェクトの使用方法について説明します。
CodedClient プロジェクトの使用
このサンプル クライアントは、InvokePowerShell
アクティビティのさまざまな使用方法の例を含むシーケンス アクティビティをプログラムで作成します。最初の呼び出しでは、メモ帳を起動します。
new InvokePowerShell()
{
CommandText = "notepad"
},
2 番目の呼び出しでは、ローカル コンピューターで実行されているプロセスのリストを取得します。
new InvokePowerShell<Process>()
{
CommandText = "Get-Process",
Output = processes1,
},
Output
は、コマンドの出力を格納するための変数です。
その次の呼び出しは、PowerShell の呼び出しの個々の出力に対して後処理のステップを実行する方法を示しています。InitializationAction
は、各プロセスの文字列形式を出力する関数に設定されています。それらの文字列のコレクションは、InvokePowerShell<string>
アクティビティによって Output
変数で返されます。
その後に続く一連の InvokePowerShell
の呼び出しは、アクティビティにデータを渡して出力とエラーを取得する方法を示しています。
DesignerClient プロジェクトの使用
DesignerClient プロジェクトは一連のカスタム アクティビティで構成されていますが、それらのほぼすべてに InvokePowerShell
アクティビティが含まれています。ほとんどのアクティビティは、非ジェネリック バージョンの InvokePowerShell
アクティビティを呼び出します。したがって、戻り値を受け取りません。ジェネリック バージョンの InvokePowerShell
アクティビティを使用するその他のアクティビティは、InitializationAction
引数を使用して結果の後処理を行います。
PowerShell プロジェクトの使用
アクティビティの主要なアクションは ExecutePowerShell
クラスで実行されます。PowerShell コマンドの実行によってメインのワークフロー スレッドがブロックされないようにする必要があるため、アクティビティは、AsyncCodeActivity クラスを継承して非同期アクティビティとして作成されています。
ワークフロー ランタイムによって BeginExecute メソッドが呼び出されると、アクティビティの実行が開始されます。このメソッドは、まず最初に、PowerShell API を呼び出して PowerShell パイプラインを作成します。
runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
pipeline = runspace.CreatePipeline();
次に、PowerShell コマンドを作成してパラメーターと変数を設定します。
Command cmd = new Command(this.CommandText, this.IsScript);
// loop over parameters and run: cmd.Parameters.Add(...)
// loop over variables and run: runspace.SessionStateProxy.SetVariable(...)
pipeline.Commands.Add(cmd);
この時点で、パイプ入力された入力がパイプラインにも送信されます。最後に、パイプラインが PipelineInvokerAsyncResult
オブジェクトでラップされて返されます。PipelineInvokerAsyncResult
オブジェクトは、リスナーを登録してパイプラインを呼び出します。
pipeline.InvokeAsync();
実行が終了すると、出力とエラーが同じ PipelineInvokerAsyncResult
オブジェクトに格納され、最初に BeginExecute に渡されたコールバック メソッドが呼び出されてワークフロー ランタイムに制御が返されます。
メソッドの実行の最後に、ワークフロー ランタイムがアクティビティの EndExecute メソッドを呼び出します。
InvokePowerShell
クラスは ExecutePowerShellCommand
クラスをラップして、ジェネリック バージョンと非ジェネリック バージョンの 2 つのバージョンのアクティビティを作成します。非ジェネリック バージョンは PowerShell の実行の出力をそのまま返しますが、ジェネリック バージョンは個々の結果をジェネリック型に変換します。
ジェネリック バージョンのアクティビティは、ExecutePowerShellCommand
を呼び出してその結果の後処理を行うシーケンシャル ワークフローとして実装されています。後処理のステップでは、結果のコレクションの各要素に対して、InitializationAction
が設定されている場合にはそれが呼び出され、設定されていない場合には単純なキャストが行われます。
new ForEach<PSObject>
{
Values = psObjects,
Body = new ActivityAction<PSObject>
{
Argument = psObject,
Handler = new Sequence
{
Activities =
{
new If
{
Condition = // Is InitializationAction set?
Then = new InvokeFunc<PSObject, TResult>
{
Argument = psObject,
Result = outputObject,
Func = this.InitializationAction
},
Else = new Assign<TResult>
{
To = outputObject,
Value = new InArgument<TResult>(ctx => (TResult) psObject.Get(ctx).BaseObject),
}
},
new AddToCollection<TResult>
{
Collection = outputObjects,
Item = outputObject
},
}
}
}
},
2 つの InvokePowerShell
アクティビティ (ジェネリックと非ジェネリック) のそれぞれにデザイナーが用意されています。InvokePowerShellDesigner.xaml とその関連 .cs ファイルは、非ジェネリック バージョンの InvokePowerShell
アクティビティのワークフロー デザイナーでの外観を定義します。InvokePowerShellDesigner.xaml では、DockPanel を使用してグラフィカル インターフェイスを表しています。
<DockPanel x:Uid="DockPanel_1" LastChildFill="True">
<TextBlock x:Uid="TextBlock_1" Text="CommandText" />
<TextBox x:Uid="TextBox_1" Text="{Binding Path=ModelItem.CommandText, Mode=TwoWay}"
TextWrapping="WrapWithOverflow" AcceptsReturn="True" MinLines="4" MaxLines="4"
Background="{x:Null}" Margin="3" />
</DockPanel>
テキスト ボックスの Text
プロパティが双方向のバインドになっているため、アクティビティの CommandText
プロパティの値がデザイナーに入力された値と同じになります。
GenericInvokePowerShellDesigner.xaml とその関連 .cs ファイルは、ジェネリック InvokePowerShell
アクティビティのグラフィカル インターフェイスを定義します。このデザイナーは、InitializationAction
を設定できるようになっているため、非ジェネリック バージョンのデザイナーに比べてやや複雑です。ここでのポイントは、WorkflowItemPresenter を使用して、InvokePowerShell
のデザイナー画面に子アクティビティをドラッグ アンド ドロップできるようにしていることです。
<sap:WorkflowItemPresenter x:Uid="sap:WorkflowItemPresenter_1" Margin="0,10,0,10"
HintText="Drop Activities Here"
AllowedItemType="{x:Type sa:Activity}"
Item="{Binding Path=ModelItem.InitializationAction.Handler, Mode=TwoWay}"
Grid.Row="1" Grid.Column="1" />
デザイナーでカスタマイズできるのは、デザイン キャンバスでのアクティビティの外観を定義する .xaml ファイルだけではありません。アクティビティのパラメーターを表示するために使用されるダイアログ ボックスもカスタマイズできます。これらのパラメーターや PowerShell 変数は、PowerShell コマンドの動作に影響します。アクティビティはこれらを Dictionary 型として公開します。これらの型を編集できるダイアログ ボックスは、ArgumentDictionaryEditor.cs、PropertyEditorResources.xaml、および PropertyEditorResources.cs で定義されています。
サンプルを設定、ビルド、および実行するには
このサンプルを実行するには Windows PowerShell をインストールする必要があります。Windows PowerShell は、Windows PowerShell からインストールできます。
コード クライアントを実行するには
Visual Studio 2010 を使用して PowerShell.sln を開きます。
ソリューションを右クリックしてビルドします。
[CodedClient] プロジェクトを右クリックし、[スタートアップ プロジェクトに設定] をクリックします。
Ctrl キーを押しながら F5 キーを押してアプリケーションを実行します。
デザイナー クライアントを実行するには
Visual Studio 2010 を使用して PowerShell.sln を開きます。
ソリューションを右クリックしてビルドします。
[DesignerClient] プロジェクトを右クリックし、[スタートアップ プロジェクトに設定] をクリックします。
Ctrl キーを押しながら F5 キーを押してアプリケーションを実行します。
既知の問題
InvokePowerShell
アクティビティのアセンブリやプロジェクトを別のプロジェクトから参照してビルド エラーが発生した場合は、必要に応じて、新しいプロジェクトの .csproj ファイル (InvokePowerShell
を参照している行の下) に<SpecificVersion>True</SpecificVersion>
要素を手動で追加してください。Windows PowerShell がインストールされていない場合は、
InvokePowerShell
アクティビティをワークフローに追加するとすぐに、Visual Studio で次のエラー メッセージが表示されます。"ワークフロー デザイナーはドキュメントで問題を検出しました。ファイルまたはアセンブリ 'System.Management.Automation'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりません。
"Windows PowerShell 2.0 では、プログラムで
$input.MoveNext()
を呼び出すと呼び出しが失敗します。そのため、$input.MoveNext()
を使用するスクリプトで予想外のエラーと結果が生成されます。この問題を回避するには、配列を反復処理するときに、MoveNext()
を呼び出す代わりに PowerShell の動詞foreach
を使用することを検討してください。
![]() |
---|
サンプルは、既にコンピューターにインストールされている場合があります。続行する前に、次の (既定の) ディレクトリを確認してください。
<InstallDrive>:\WF_WCF_Samples
このディレクトリが存在しない場合は、「.NET Framework 4 向けの Windows Communication Foundation (WCF) および Windows Workflow Foundation (WF) のサンプル」にアクセスして、Windows Communication Foundation (WCF) および WF のサンプルをすべてダウンロードしてください。このサンプルは、次のディレクトリに格納されます。
<InstallDrive>:\WF_WCF_Samples\WF\Scenario\ActivityLibrary\PowerShell
|