Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
J’ai récemment eu une idée du module que je voulais implémenter en tant que module binaire. Je dois encore en créer une en utilisant la bibliothèque standard PowerShell, donc cela semblait être une bonne opportunité. J’ai utilisé le Création d’un module binaire multiplateforme guide pour créer ce module sans aucun obstacle. Nous allons suivre ce même processus et je vais ajouter quelques commentaires supplémentaires en cours de route.
Remarque
La version originale de cet article est apparue sur le blog écrit par @KevinMarquette. L’équipe PowerShell remercie Kevin de partager ce contenu avec nous. Consultez son blog à PowerShellExplained.com.
Qu’est-ce que la bibliothèque PowerShell Standard ?
La bibliothèque Standard PowerShell nous permet de créer des modules multiplateformes qui fonctionnent à la fois dans PowerShell et Windows PowerShell 5.1.
Pourquoi les modules binaires ?
Lorsque vous écrivez un module en C#, vous abandonnez l’accès facile aux applets de commande et aux fonctions PowerShell. Toutefois, si vous créez un module qui ne dépend pas d’un grand nombre d’autres commandes PowerShell, l’avantage de performances peut être significatif. PowerShell a été optimisé pour l’administrateur, et non pour l’ordinateur. En passant à C#, vous vous libérez des surcharges ajoutées par PowerShell.
Par exemple, nous avons un processus critique qui effectue beaucoup de travail avec JSON et des tables de hachage. Nous avons optimisé PowerShell autant que possible, mais le processus prend toujours 12 minutes. Le module contenait déjà beaucoup de powerShell de style C#. Cela rend la conversion en module binaire propre et simple. En convertissant en module binaire, nous avons réduit le temps de traitement de plus de 12 minutes à moins de quatre minutes.
Modules hybrides
Vous pouvez combiner des applets de commande binaires avec des fonctions avancées PowerShell. Tout ce que vous savez sur les modules de script s’applique de la même façon. Le fichier psm1 vide est inclus afin de pouvoir ajouter d’autres fonctions PowerShell ultérieurement.
Presque toutes les applets de commande compilées que j’ai créées ont commencé en tant que fonctions PowerShell en premier. Tous nos modules binaires sont des modules vraiment hybrides.
Générer des scripts
J’ai gardé le script de build simple ici. J’utilise généralement un long script Invoke-Build dans le cadre de mon pipeline CI/CD. Il en fait beaucoup plus, comme exécuter des tests Pester, exécuter PSScriptAnalyzer, gérer les versions et publier sur PSGallery. Une fois que j’ai commencé à utiliser un script de build pour mes modules, j’ai pu trouver beaucoup d’éléments à ajouter à celui-ci.
Planification du module
Le plan de ce module consiste à créer un dossier src pour le code C# et à structurer le reste comme je le voudrais pour un module de script. Cela inclut l’utilisation d’un script de build pour compiler tout dans un dossier Output. La structure de dossiers ressemble à ceci :
MyModule
├───src
├───Output
│ └───MyModule
├───MyModule
│ ├───Data
│ ├───Private
│ └───Public
└───Tests
Mise en route
Tout d’abord, j’ai besoin de créer le dossier et de créer le dépôt git. J’utilise $module comme espace réservé pour le nom du module. Cela devrait faciliter la réutilisation de ces exemples si nécessaire.
$module = 'MyModule'
New-Item -Path $module -Type Directory
Set-Location $module
git init
Créez ensuite les dossiers de niveau racine.
New-Item -Path 'src' -Type Directory
New-Item -Path 'Output' -Type Directory
New-Item -Path 'Tests' -Type Directory
New-Item -Path $module -Type Directory
Configuration du module binaire
Cet article est concentré sur le module binaire, c'est par là que nous allons commencer. Cette section extrait des exemples du guide Création d’un module binaire multiplateforme. Passez en revue ce guide si vous avez besoin de détails supplémentaires ou si vous rencontrez des problèmes.
Tout d’abord, nous voulons vérifier la version du kit de développement logiciel (SDK) dotnet core que nous avons installée. J’utilise 2.1.4, mais vous devriez avoir 2.0.0 ou une version ultérieure avant de continuer.
PS> dotnet --version
2.1.4
Je travaille dans le dossier src pour cette section.
Set-Location 'src'
À l’aide de la commande dotnet, créez une bibliothèque de classes.
dotnet new classlib --name $module
Ceci a créé le projet de bibliothèque dans un sous-dossier, mais je ne veux pas ce niveau supplémentaire d’imbrication. Je vais déplacer ces fichiers vers le haut.
Move-Item -Path .\$module\* -Destination .\
Remove-Item $module -Recurse
Définissez la version du Kit de développement logiciel (SDK) .NET Core pour le projet. J’ai le SDK 2.1, donc je vais spécifier 2.1.0.
Utilisez 2.0.0 si vous utilisez le Kit de développement logiciel (SDK) 2.0.
dotnet new globaljson --sdk-version 2.1.0
Ajoutez le package NuGet de la bibliothèque standard PowerShell au projet. Veillez à utiliser la version la plus récente disponible pour le niveau de compatibilité dont vous avez besoin. J’utiliserais par défaut la dernière version, mais je ne pense pas que ce module tire parti des fonctionnalités plus récentes que PowerShell 3.0.
dotnet add package PowerShellStandard.Library --version 7.0.0-preview.1
Nous devrions avoir un dossier src qui ressemble à ceci :
PS> Get-ChildItem
Directory: \MyModule\src
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 7/14/2018 9:51 PM obj
-a---- 7/14/2018 9:51 PM 86 Class1.cs
-a---- 7/14/2018 10:03 PM 259 MyModule.csproj
-a---- 7/14/2018 10:05 PM 45 global.json
Nous sommes maintenant prêts à ajouter notre propre code au projet.
Génération d’une applet de commande binaire
Nous devons mettre à jour le src\Class1.cs pour contenir cette applet de commande de démarrage :
using System;
using System.Management.Automation;
namespace MyModule
{
[Cmdlet( VerbsDiagnostic.Resolve , "MyCmdlet")]
public class ResolveMyCmdletCommand : PSCmdlet
{
[Parameter(Position=0)]
public Object InputObject { get; set; }
protected override void EndProcessing()
{
this.WriteObject(this.InputObject);
base.EndProcessing();
}
}
}
Renommez le fichier pour qu’il corresponde au nom de la classe.
Rename-Item .\Class1.cs .\ResolveMyCmdletCommand.cs
Nous pouvons ensuite créer notre module.
PS> dotnet build
Microsoft (R) Build Engine version 15.5.180.51428 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restore completed in 18.19 ms for C:\workspace\MyModule\src\MyModule.csproj.
MyModule -> C:\workspace\MyModule\src\bin\Debug\netstandard2.0\MyModule.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:02.19
Nous pouvons appeler Import-Module sur la nouvelle dll pour charger notre nouvelle applet de commande.
PS> Import-Module .\bin\Debug\netstandard2.0\$module.dll
PS> Get-Command -Module $module
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Resolve-MyCmdlet 1.0.0.0 MyModule
Si l’importation échoue sur votre système, essayez de mettre à jour .NET vers la version 4.7.1 ou ultérieure. Le guide sur la création d’un module binaire multiplateforme explore en détail la prise en charge de .NET et la compatibilité avec les versions antérieures de .NET.
Manifeste du module
Il est cool que nous puissions importer la dll et avoir un module de travail. J’aime continuer à l’utiliser et créer un manifeste de module. Nous avons besoin du manifeste si nous voulons publier sur PSGallery ultérieurement.
À partir de la racine de notre projet, nous pouvons exécuter cette commande pour créer le manifeste du module dont nous avons besoin.
$manifestSplat = @{
Path = ".\$module\$module.psd1"
Author = 'Kevin Marquette'
NestedModules = @('bin\MyModule.dll')
RootModule = "$module.psm1"
FunctionsToExport = @('Resolve-MyCmdlet')
}
New-ModuleManifest @manifestSplat
Je vais également créer un module racine vide pour les futures fonctions PowerShell.
Set-Content -Value '' -Path ".\$module\$module.psm1"
Cela me permet de combiner les fonctions PowerShell normales et les applets de commande binaires dans le même projet.
Génération du module complet
Je compile tout ensemble dans un dossier de sortie. Nous devons créer un script de build pour ce faire. Je l’ajouterais normalement à un script Invoke-Build, mais nous pouvons le garder simple pour cet exemple. Ajoutez ceci à un fichier build.ps1 à la racine du projet.
$module = 'MyModule'
Push-Location $PSScriptRoot
dotnet build $PSScriptRoot\src -o $PSScriptRoot\output\$module\bin
Copy-Item "$PSScriptRoot\$module\*" "$PSScriptRoot\output\$module" -Recurse -Force
Import-Module "$PSScriptRoot\Output\$module\$module.psd1"
Invoke-Pester "$PSScriptRoot\Tests"
Ces commandes créent notre DLL et placent-la dans notre dossier output\$module\bin. Elles copient ensuite les autres fichiers du module à leur emplacement de destination.
Output
└───MyModule
├───MyModule.psd1
├───MyModule.psm1
└───bin
├───MyModule.deps.json
├───MyModule.dll
└───MyModule.pdb
À ce stade, nous pouvons importer notre module avec le fichier psd1.
Import-Module ".\Output\$module\$module.psd1"
À partir de là, nous pouvons déplacer le dossier .\Output\$module dans notre répertoire $Env:PSModulePath, et il charge automatiquement notre commande chaque fois que nécessaire.
Mise à jour : Nouveau PSModule pour dotnet
J’ai appris que l’outil dotnet a un modèle PSModule.
Toutes les étapes que j’ai décrites ci-dessus sont toujours valides, mais ce modèle en supprime beaucoup. Il s’agit toujours d’un modèle assez nouveau qui est encore en cours de perfectionnement. Attendez-vous à ce que cela continue de s'améliorer à partir de maintenant.
Il s’agit de la façon dont vous utilisez l’installation et l’utilisation du modèle PSModule.
dotnet new -i Microsoft.PowerShell.Standard.Module.Template
dotnet new psmodule
dotnet build
Import-Module "bin\Debug\netstandard2.0\$module.dll"
Get-Module $module
Ce modèle minimalement viable s’occupe de l’ajout du Kit de développement logiciel (SDK) .NET, de powerShell Standard Library et crée un exemple de classe dans le projet. Vous pouvez le générer et l’exécuter immédiatement.
Détails importants
Avant de terminer cet article, voici quelques autres détails qui méritent d’être mentionnés.
Déchargement des DLL
Une fois qu’un module binaire est chargé, vous ne pouvez pas vraiment le décharger. Le fichier DLL est verrouillé jusqu’à ce que vous le déchargez. Cela peut être ennuyeux lors du développement, car chaque fois que vous apportez une modification et que vous souhaitez le générer, le fichier est souvent verrouillé. La seule façon fiable de résoudre ce problème consiste à fermer la session PowerShell qui a chargé la DLL.
Action de rechargement de la fenêtre VS Code
Je fais la plupart de mon travail de développement PowerShell dans VS Code. Lorsque je travaille sur un module binaire (ou un module avec des classes), j’ai pris l’habitude de recharger VS Code chaque fois que je génère.
Ctrl+Maj+P fait apparaître la fenêtre de commande et Reload Window est toujours en haut de ma liste.
Sessions PowerShell imbriquées
Une autre option consiste à avoir une bonne couverture des tests avec Pester. Vous pouvez ensuite ajuster le script build.ps1 pour démarrer une nouvelle session PowerShell, exécuter la build, exécuter les tests et fermer la session.
Mise à jour des modules installés
Ce verrouillage peut être ennuyeux lors de la tentative de mise à jour de votre module installé localement. Si une session l’a chargé, vous devez la trouver et la fermer. Ce n’est pas vraiment un problème lors de l’installation à partir de PSGallery, car la gestion de versions du module place le nouveau dans un dossier différent.
Vous pouvez configurer un PSGallery local et le publier dans le cadre de votre build. Effectuez ensuite votre installation locale à partir de ce PSGallery. Cela ressemble à beaucoup de travail, mais cela peut être aussi simple que de démarrer un conteneur Docker. Dans mon article intitulé , j'explique comment utiliser un serveur NuGet pour un PSRepository.
Pensées finales
Je n’ai pas touché à la syntaxe C# pour créer une applet de commande, mais il y a beaucoup de documentation sur celle-ci dans le kit de développement logiciel (SDK) Windows PowerShell . C’est certainement quelque chose qui vaut la peine d'être expérimenté comme un tremplin vers le C# plus sérieux.