Utilisation de PowerShell dans votre extension
Examinons plus en détail le kit SDK Windows Admin Center. Nous allons évoquer l’ajout de commandes PowerShell à votre extension.
PowerShell dans TypeScript
Le processus de génération gulp comporte une étape de génération qui accepte les {!ScriptName}.ps1
placés dans le dossier \src\resources\scripts
, et les génère dans la classe powershell-scripts
sous le dossier \src\generated
.
Notes
Ne mettez pas à jour manuellement les fichiers powershell-scripts.ts
ni les fichiers strings.ts
. Tout changement que vous apportez est remplacé à la prochaine génération.
Exécution d’un script PowerShell
Tous les scripts à exécuter sur un nœud peuvent être placés dans \src\resources\scripts\{!ScriptName}.ps1
.
Important
Les changements apportés à un fichier {!ScriptName}.ps1
ne sont pas répercutés dans votre projet tant que gulp generate
n’a pas été exécuté.
L’API fonctionne en créant d’abord une session PowerShell sur les nœuds que vous ciblez, en créant le script PowerShell avec tous les paramètres à passer, puis en exécutant le script sur les sessions créées.
Par exemple, nous avons ce script \src\resources\scripts\Get-NodeName.ps1
:
Param
(
[String] $stringFormat
)
$nodeName = [string]::Format($stringFormat,$env:COMPUTERNAME)
Write-Output $nodeName
Nous allons créer une session PowerShell pour notre nœud cible :
const session = this.appContextService.powerShell.createSession('{!TargetNode}');
Nous allons ensuite créer le script PowerShell avec un paramètre d’entrée :
const command = PowerShell.createCommand(PowerShellScripts.Get_NodeName, {stringFormat: 'The name of the node is {0}!'});
Pour finir, nous devons exécuter ce script dans la session que nous avons créée :
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()
}
Nous devons à présent nous abonner à la fonction observable que nous venons de créer. Placez ce qui suit à l’emplacement où vous devez appeler la fonction pour exécuter le script PowerShell :
this.getNodeName().subscribe(
response => {
console.log(response)
}
);
En fournissant le nom du nœud à la méthode createSession, une nouvelle session PowerShell est créée, utilisée, puis immédiatement détruite à l’issue de l’appel PowerShell.
Options des clés
Quelques options sont disponibles au moment de l’appel de l’API PowerShell. Chaque fois qu’une session est créée, elle peut l’être avec ou sans clé.
Key : une session avec clé est créée. Elle peut être recherchée et réutilisée, même entre les composants (ce qui signifie que Composant 1 peut créer une session avec la clé « SME-ROCKS », et que Composant 2 peut utiliser cette même session). Si une clé est fournie, la session créée doit être supprimée via l’appel de dispose(), comme cela a été effectué dans l’exemple ci-dessus. Une session ne doit pas être conservée plus de 5 minutes sans être supprimée.
const session = this.appContextService.powerShell.createSession('{!TargetNode}', '{!Key}');
Keyless : Une clé est automatiquement créée pour la session. Cette session est supprimée automatiquement au bout de 3 minutes. L’utilisation de keyless permet à votre extension de recycler l’utilisation de n’importe quelle instance d’exécution déjà disponible au moment de la création d’une session. Si aucune instance d’exécution n’est disponible, une autre instance est créée. Cette fonctionnalité convient bien pour les appels ponctuels, mais son utilisation répétée peut affecter les performances. La création d’une session dure environ 1 seconde. Le recyclage continu des sessions peut donc entraîner des ralentissements.
const session = this.appContextService.powerShell.createSession('{!TargetNodeName}');
ou
const session = this.appContextService.powerShell.createAutomaticSession('{!TargetNodeName}');
Dans la plupart des situations, créez une session à clé dans la méthode ngOnInit()
, puis supprimez-la dans ngOnDestroy()
. Suivez ce modèle quand il existe plusieurs scripts PowerShell dans un composant, mais que la session sous-jacente N’EST PAS partagée entre les composants.
Pour de meilleurs résultats, vérifiez que la création de session est gérée à l’intérieur des composants plutôt que des services. Cela permet de garantir la gestion appropriée de la durée de vie et du nettoyage.
Pour de meilleurs résultats, vérifiez que la création de session est gérée à l’intérieur des composants plutôt que des services. Cela permet de garantir la gestion appropriée de la durée de vie et du nettoyage.
Flux PowerShell
Si vous avez un script durable et si les données sont générées progressivement, un flux PowerShell vous permet de traiter les données sans avoir à attendre la fin du script. Le next() observable est appelé dès la réception des données.
this.appContextService.powerShellStream.run(session, script);
Scripts durables
Si vous disposez d’un script durable à exécuter en arrière-plan, vous pouvez envoyer un élément de travail. L’état du script fait l’objet d’un suivi par la passerelle, et des mises à jour de l’état peuvent être envoyées à une notification.
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);
Notes
Pour que la progression soit affichée, Write-Progress doit être inclus dans le script que vous avez écrit. Par exemple :
Write-Progress -Activity ‘The script is almost done!' -percentComplete 95
Options de WorkItem
function | Explication |
---|---|
submit() | Envoie l’élément de travail |
submitAndWait() | Envoyer l’élément de travail, et attendre la fin de son exécution |
wait() | Attendre la fin de l’exécution de l’élément de travail existant |
query() | Interroger un élément de travail existant en fonction de son ID |
find() | Rechercher un élément de travail existant en fonction de TargetNodeName, ModuleName ou typeId. |
API de traitement par lots PowerShell
Si vous devez exécuter le même script sur plusieurs nœuds, vous pouvez utiliser une session PowerShell de traitement par lots. Par exemple :
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 */ });
Options de PowerShellBatch
Option | Explication |
---|---|
runSingleCommand | Exécuter une seule commande sur tous les nœuds du tableau |
Exécuter | Exécuter la commande correspondante sur le nœud appairé |
annuler | Annuler la commande sur tous les nœuds du tableau |