Freigeben über


Verwenden von PowerShell in Erweiterungen

Gilt für: Windows Admin Center, Windows Admin Center-Vorschau

In diesem Artikel erhalten Sie ausführlichere Informationen zum SDK der Windows Admin Center-Erweiterung und erfahren, wie Sie Ihrer Erweiterung PowerShell-Befehle hinzufügen.

PowerShell in TypeScript

Der Gulp-Buildprozess verfügt über einen Generierungsschritt, der alle {!ScriptName}.ps1 aus dem Ordner \src\resources\scripts in der Klasse powershell-scripts im Ordner \src\generated erstellt.

Hinweis

Führen Sie kein manuelles Update für die Dateien powershell-scripts.ts oder strings.ts aus. Alle vorgenommenen Änderungen werden bei der nächsten Generierung überschrieben.

Ausführen eines PowerShell-Skripts

Alle Skripts, die Sie auf einem Knoten ausführen möchten, können unter \src\resources\scripts\{!ScriptName}.ps1 abgelegt werden.

Wichtig

Änderungen, die Sie in einer {!ScriptName}.ps1-Datei vornehmen, werden erst nach Ausführen von gulp generate im Projekt berücksichtigt.

Die API erstellt zunächst eine PowerShell-Sitzung auf den entsprechenden Knoten, erstellt dann das PowerShell-Skript mit allen Parametern, die übergeben werden müssen, und führt das Skript anschließend für die erstellten Sitzungen aus.

Das folgende Beispiel zeigt das Skript \src\resources\scripts\Get-NodeName.ps1:

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

Sie erstellen nun eine PowerShell-Sitzung für den Zielknoten:

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

Anschließend erstellen Sie das PowerShell-Skript mit einem Eingabeparameter:

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

Und zuletzt führen Sie das Skript für die erstellte Sitzung aus:

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

Abonnieren Sie nun die Observable-Funktion, die Sie eben erstellt haben. Platzieren Sie diese an die Stelle, an der Sie die Funktion zum Ausführen des PowerShell-Skripts aufrufen müssen:

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

Durch Bereitstellen des Knotennamens für die createSession-Methode wird eine neue PowerShell-Sitzung erstellt, genutzt und nach Abschluss des PowerShell-Aufrufs sofort zerstört.

Schlüsseloptionen

Beim Aufrufen der PowerShell-API sind einige Optionen verfügbar. Jede neue Sitzung kann mit oder ohne Schlüssel erstellt werden.

Schlüssel: Es wird eine schlüsselgebundene Sitzung erstellt, die auch komponentenübergreifend gesucht und wiederverwendet werden kann. Das bedeutet, dass Komponente 1 eine Sitzung mit dem Schlüssel „SME-ROCKS“ erstellen kann, die auch von Komponente 2 verwendet werden kann. Wenn ein Schlüssel bereitgestellt wird, muss die erstellte Sitzung durch Aufrufen von dispose() wie im obigen Beispiel gelöscht werden. Eine Sitzung sollte nach spätestens 5 Minuten verworfen werden.

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

Ohne Schlüssel: Für die Sitzung wird automatisch ein Schlüssel erstellt. Diese Sitzung wird nach 3 Minuten automatisch verworfen. Bei einer Sitzung ohne Schlüssel kann die Erweiterung alle Runspaces wiederverwenden, die bereits zum Zeitpunkt der Erstellung einer Sitzung verfügbar sind. Ist kein Runspace verfügbar, wird ein neuer erstellt. Diese Funktion ist für einmalige Anrufe geeignet, da bei wiederholter Verwendung die Leistung beeinträchtigt werden kann. Das Erstellen einer Sitzung dauert etwa 1 Sekunde, weshalb die fortlaufende Wiederverwendung von Sitzungen zu Verlangsamungen führen kann.

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

oder

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

In den meisten Fällen ist die beste Option, eine schlüsselgebundene Sitzung mit der Methode ngOnInit() zu erstellen und diese dann mit ngOnDestroy() zu verwerfen. Verwenden Sie dieses Muster, wenn sich mehrere PowerShell-Skripts in einer Komponente befinden, die zugrunde liegende Sitzung jedoch NICHT komponentenübergreifend freigegeben wird. Vergewissern Sie sich, dass die Sitzungserstellung in den Komponenten und nicht in den Diensten verwaltet wird. Dies ermöglicht eine ordnungsgemäße Verwaltung von Lebensdauer und Bereinigung.

Vergewissern Sie sich, dass die Sitzungserstellung in den Komponenten und nicht in den Diensten verwaltet wird. Dies ermöglicht eine ordnungsgemäße Verwaltung von Lebensdauer und Bereinigung.

PowerShell-Stream

Bei einem Skript mit langer Ausführungsdauer und progressiver Datenausgabe können Sie mithilfe eines PowerShell-Streams die Daten bereits bearbeiten, bevor die Ausführung des Skripts abgeschlossen ist. Die Observable-Funktion „next()“ wird aufgerufen, sobald Daten empfangen werden.

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

Skripts mit langer Ausführungsdauer

Wenn Sie ein Skript mit langer Ausführungsdauer im Hintergrund ausführen möchten, können Sie ein Arbeitselement übermitteln. Der Status des Skripts wird vom Gateway nachverfolgt, und Sie werden über eine Aktualisierung des Status per Benachrichtigung informiert.

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);

Hinweis

Wenn Sie den Fortschritt anzeigen möchten, muss das Skript den Befehl „Write-Progress“ enthalten. Zum Beispiel:

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

WorkItem-Optionen

Funktion Erklärung
submit() Übermittelt das Arbeitselement.
submitAndWait() Übermittelt das Arbeitselement und wartet bis zum Abschluss der Ausführung.
wait() Wartet bis zum Abschluss des vorhandenen Arbeitselements.
query() Fragt ein vorhandenes Arbeitselement nach der ID ab
find() Sucht ein vorhandenes Arbeitselement nach „TargetNodeName“, „ModuleName“ oder „typeId“.

PowerShell-Batch-APIs

Wenn Sie ein Skript für mehrere Knoten ausführen müssen, können Sie eine PowerShell-Batchsitzung verwenden. Zum Beispiel:

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 */ });

PowerShell-Batch-Optionen

Option Erklärung
runSingleCommand Führt einen einzelnen Befehl für alle Knoten im Array aus.
Run Führt einen entsprechenden Befehl für ein Knotenpaar aus.
cancel Bricht den Befehl für alle Knoten im Array ab.