分享方式:


在擴充功能中使用 PowerShell

適用於:Windows Admin Center、Windows Admin Center 預覽版

讓我們深入了解 Windows Admin Center 延伸模組 SDK - 讓我們來討論如何將 PowerShell 命令新增至延伸模組。

TypeScript 中的 PowerShell

gulp 建置程序包含一個產生步驟,其會採用在 \src\resources\scripts 資料夾中放置的任何 {!ScriptName}.ps1,並將其建置為 \src\generated 資料夾下的 powershell-scripts 類別。

注意

請勿手動更新 powershell-scripts.tsstrings.ts 檔案。 將在下一次產生時覆寫您所做的任何變更。

正在執行 PowerShell 指令碼

您想要在節點上執行的任何指令碼都可以放在 \src\resources\scripts\{!ScriptName}.ps1 中。

重要

在執行 gulp generate 之前,{!ScriptName}.ps1 檔案中的任何變更都不會在專案中反映。

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()
  }

現在,我們需要訂閱我們剛建立的可觀察函式。 請將此放在您需要呼叫此函式以執行 PowerShell 指令碼的位置:

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

藉由將節點名稱提供給 createSession 方法,就會建立和使用新的 PowerShell 工作階段,然後此工作階段會在 PowerShell 呼叫完成時立即終結。

索引鍵選項

呼叫 PowerShell API 時,有一些可用選項。 每次建立工作階段時,都可以在使用或不使用索引鍵的情況下建立工作階段。

金鑰:這創造一個可查閱和重用,甚至橫跨組成元件的金鑰工作階段 (代表綒成元件 1 可創造含有 “SME-ROCKS” 的工作階段,而組成元件 2 可使用相同工作階段)。 如果提供金鑰,創造的工作階段必須藉由呼叫 dispose() 處置,如上述範例所示。 工作階段不應保留,而處置的時間不應超過 5 分鐘。

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

無索引鍵:會自動為工作階段建立索引鍵。 會在 3 分鐘後自動處置此工作階段。 使用無金鑰允許您的擴充程式回收使用工作階段創造時,已經可用的任何執行空間。 如果沒有可用的執行空間,會創造一個新的。 這項功能適用於一次性呼叫,但重複使用可能會影響效能。 工作階段的建立需要大約 1 秒的時間,因此持續回收工作階段可能會導致速度變慢。

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

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

在大部分情況下,請在 ngOnInit() 方法中建立索引鍵工作階段,然後在 ngOnDestroy() 中進行處置。 當元件中有多個 PowerShell 指令碼,但未跨元件共用基礎工作階段時,請遵循此模式。 為了獲得最佳結果,請確定工作階段建立是在元件 (而不是服務) 內部管理,這有助於確保可以正確管理存留期和清除。

為了獲得最佳結果,請確定工作階段建立是在元件 (而不是服務) 內部管理,這有助於確保可以正確管理存留期和清除。

PowerShell 資料流

如果您有長時間執行的指令碼且資料是逐步輸出,PowerShell 資料流將可讓您處理資料,而不需要等候指令碼完成。 一收到資料,就會立即呼叫可觀察的 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 -Activity ‘The script is almost done!' -percentComplete 95

WorkItem 選項

函數 說明
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 對陣列中的所有節點執行單一命令
run 對配對的節點執行對應的命令
cancel 取消陣列中所有節點上的命令