在擴充功能中使用 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.ts
或 strings.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 | 取消陣列中所有節點上的命令 |