拡張機能で PowerShell を使用する

Windows Admin Center Extensions SDK について詳しく説明します。拡張機能に PowerShell コマンドを追加する方法について説明します。

TypeScript での PowerShell

Gulp ビルド プロセスにある生成手順では、\src\resources\scripts フォルダーにある {!ScriptName}.ps1 を取得して、\src\generated フォルダーの下で powershell-scripts クラスに組み入れます。

注意

powershell-scripts.tsstrings.ts のどちらのファイルも手動で更新しないでください。 変更を加えても、次の生成時に上書きされます。

PowerShell スクリプトの実行

ノードで実行したいスクリプトはすべて、\src\resources\scripts\{!ScriptName}.ps1 に置くことができます。

重要

{!ScriptName}.ps1 ファイルに加えられた変更がプロジェクトに反映されるのは、gulp generate の実行後です。

API が機能するには、まずターゲットとするノードで PowerShell セッションを作成し、渡す必要があるパラメーターを使用して PowerShell スクリプトを作成し、作成されたセッションでスクリプトを実行します。

たとえば、スクリプト \src\resources\scripts\Get-NodeName.ps1 があるとします。

Param
 (
    [String] $stringFormat
 )
 $nodeName = [string]::Format($stringFormat,$env:COMPUTERNAME)
 Write-Output $nodeName

ターゲット ノードの PowerShell セッションを作成します。

const session = this.appContextService.powerShell.createSession('{!TargetNode}');

次に、入力パラメーターを使用して PowerShell スクリプトを作成します。

const command = PowerShell.createCommand(PowerShellScripts.Get_NodeName, {stringFormat: 'The name of the node is {0}!'});

最後に、作成したセッションでそのスクリプトを実行する必要があります。

  public ngOnInit(): void {
    this.session = this.appContextService.powerShell.createAutomaticSession('{!TargetNode}');
  }

  public getNodeName(): Observable<any> {
    const command = PowerShell.createCommand(PowerShellScripts.Get_NodeName, { stringFormat: 'The name of the node is {0}!'});
    return this.appContextService.powerShell.run(this.session, command)
    .pipe(
        map(
        response => {
            if (response && response.results) {
                return response.results;
            }
            return 'no response';
        }
      )
    );
  }

  public ngOnDestroy(): void {
    this.session.dispose()
  }

ここで、作成したばかりの observable 関数をサブスクライブする必要があります。 PowerShell スクリプトを実行する関数を呼び出す必要がある場所に this を置きます。

this.getNodeName().subscribe(
     response => {
	console.log(response)
     }
);

CreateSession メソッドにノード名を指定すると、新しい PowerShell セッションが作成され、使用されてから、PowerShell 呼び出しの完了後すぐに破棄されます。

キー オプション

PowerShell API を呼び出すときに使用できるオプションがいくつかあります。 セッションが作成されるたびに、キーの有無に関係なく作成できます。

キー: これにより、コンポーネント間でも検索と再利用が可能なキー付きセッションが作成されます (つまり、Component 1 はキー "SME-ROCKS" を使用してセッションを作成でき、Component 2 は同じセッションを使用できます)。 キーが指定されている場合、作成されるセッションは、上の例で行われたように dispose() を呼び出して破棄する必要があります。 セッションは、5分を超えて、破棄されることなく保持されることはありません。

  const session = this.appContextService.powerShell.createSession('{!TargetNode}', '{!Key}');

キーなし: セッションのキーが自動的に作成されます。 このセッションは、3 分後に自動的に破棄されます。 キーなしを使用すると、セッションの作成時に既に使用可能な実行空間の使用を拡張機能でリサイクルできます。 使用可能な実行空間がない場合は、新しい実行空間が作成されます。 この機能は 1 回限りの呼び出しに適していますが、繰り返し使用するとパフォーマンスに影響する場合があります。 セッションの作成には約 1 秒かかるため、連続したセッションのリサイクルによって、パフォーマンスが低下する可能性があります。

  const session = this.appContextService.powerShell.createSession('{!TargetNodeName}');

または

const session = this.appContextService.powerShell.createAutomaticSession('{!TargetNodeName}');

ほとんどの場合、ngOnInit() メソッドでキー付きセッションを作成し、ngOnDestroy() で破棄します。 1 つのコンポーネントに複数の PowerShell スクリプトがあるにもかかわらず、基になるセッションがコンポーネント間で共有されない場合は、このパターンに従います。 最良の結果を得るには、セッションの作成がサービスではなく、コンポーネント内で管理されることを確認してください。これにより、有効期間とクリーンアップを適切に管理できるようになります。

最良の結果を得るには、セッションの作成がサービスではなく、コンポーネント内で管理されることを確認してください。これにより、有効期間とクリーンアップを適切に管理できるようになります。

PowerShell ストリーム

実行時間の長いスクリプトがあり、データが段階的に出力される場合、PowerShell ストリームを使用すると、スクリプトが終了するのを待たずにデータを処理できます。 データが受信されるとすぐに、observable next() が呼び出されます。

this.appContextService.powerShellStream.run(session, script);

実行時間の長いスクリプト

実行時間の長いスクリプトをバックグラウンドで実行したい場合は、作業項目を送信できます。 スクリプトの状態はゲートウェイによって追跡され、状態の更新を通知に送信できます。

const workItem: WorkItemSubmitRequest = {
	typeId: 'Long Running Script',
	objectName: 'My long running service',
	powerShellScript: script,

	//in progress notifications
	inProgressTitle: 'Executing long running request',
	startedMessage: 'The long running request has been started',
	progressMessage: 'Working on long running script – {{ percent }} %',

	//success notification
	successTitle: 'Successfully executed a long running script!',
	successMessage: '{{objectName}} was successful',
	successLinkText: 'Bing',
	successLink: 'http://www.bing.com',
	successLinkType: NotificationLinkType.Absolute,

	//error notification
	errorTitle: 'Failed to execute long running script',
	errorMessage: 'Error: {{ message }}'

	nodeRequestOptions: {
	   logAudit: true,
	   logTelemetry: true
	}
};

return this.appContextService.workItem.submit('{!TargetNode}', workItem);

注意

進行状況を表示するには、作成したスクリプトに Write-Progress が含まれている必要があります。 次に例を示します。

 Write-Progress -Activity ‘The script is almost done!' -percentComplete 95

作業項目オプション

関数 (function) 説明
submit() 作業項目を送信します
submitAndWait() 作業項目を送信し、実行が完了するまで待機します
wait() 既存の作業項目が完了するまで待機します
query() ID 別に既存の作業項目のクエリを実行します
find() TargetNodeName、ModuleName、または typeId で既存の作業項目を検索します。

PowerShell Batch API

同じスクリプトを複数のノードで実行する必要がある場合は、バッチ PowerShell セッションを使用できます。 次に例を示します。

const batchSession = this.appContextService.powerShell.createBatchSession(
	['{!TargetNode1}', '{!TargetNode2}', sessionKey);
  this.appContextService.powerShell.runBatchSingleCommand(batchSession, command).subscribe((responses: PowerShellBatchResponseItem[]) => {
	for (const response of responses) {
	  if (response.error || response.errors) {
	    //handle error
	  } else {
	    const results = response.properties && response.properties.results;
	    //response.nodeName
	    //results[0]
	  }
	}
     },
     Error => { /* handle error */ });

PowerShellBatch オプション

オプション 説明
runSingleCommand 配列内のすべてのノードに対して 1 つのコマンドを実行します
[実行] ペアリングされたノードで対応するコマンドを実行します
cancel 配列内のすべてのノードでコマンドを取り消します