Exécution de scripts Windows PowerShell à partir de fichiers projet MSBuild
par Jason Lee
Cette rubrique explique comment exécuter un script Windows PowerShell dans le cadre d’un processus de génération et de déploiement. Vous pouvez exécuter un script localement (en d’autres termes, sur le serveur de build) ou à distance, comme sur un serveur web de destination ou un serveur de base de données.
Il existe de nombreuses raisons pour lesquelles vous pouvez exécuter un script de Windows PowerShell post-déploiement. Vous pouvez, par exemple, souhaiter effectuer les opérations suivantes :
- Ajoutez une source d’événement personnalisée au Registre.
- Générez un répertoire de système de fichiers pour les chargements.
- Nettoyer les répertoires de build.
- Écrire des entrées dans un fichier journal personnalisé.
- Envoyer des e-mails invitant des utilisateurs à une application web nouvellement provisionnée.
- Créez des comptes d’utilisateur avec les autorisations appropriées.
- Configurez la réplication entre SQL Server instances.
Cette rubrique vous montre comment exécuter des scripts Windows PowerShell localement et à distance à partir d’une cible personnalisée dans un fichier projet Microsoft Build Engine (MSBuild).
Cette rubrique fait partie d’une série de tutoriels basés sur les exigences de déploiement d’entreprise d’une société fictive nommée Fabrikam, Inc. Cette série de tutoriels utilise un exemple de solution, la solution Gestionnaire de contacts, pour représenter une application web avec un niveau de complexité réaliste, notamment une application ASP.NET MVC 3, un service Windows Communication Foundation (WCF) et un projet de base de données.
La méthode de déploiement au cœur de ces didacticiels est basée sur l’approche de fichier projet fractionné décrite dans Présentation du fichier projet, dans laquelle le processus de génération est contrôlé par deux fichiers projet : l’un contenant des instructions de génération qui s’appliquent à chaque environnement de destination et l’autre contenant des paramètres de build et de déploiement spécifiques à l’environnement. Au moment de la génération, le fichier projet spécifique à l’environnement est fusionné dans le fichier projet indépendant de l’environnement pour former un ensemble complet d’instructions de génération.
Vue d’ensemble de la tâche
Pour exécuter un script Windows PowerShell dans le cadre d’un processus de déploiement automatisé ou en une seule étape, vous devez effectuer ces tâches générales :
- Ajoutez le script Windows PowerShell à votre solution et au contrôle de code source.
- Créez une commande qui appelle votre script Windows PowerShell.
- Échappement des caractères XML réservés dans votre commande.
- Créez une cible dans votre fichier projet MSBuild personnalisé et utilisez la tâche Exec pour exécuter votre commande.
Cette rubrique vous montre comment effectuer ces procédures. Les tâches et procédures pas à pas de cette rubrique supposent que vous êtes déjà familiarisé avec les cibles et les propriétés MSBuild, et que vous comprenez comment utiliser un fichier projet MSBuild personnalisé pour piloter un processus de génération et de déploiement. Pour plus d’informations, consultez Présentation du fichier projet et Présentation du processus de génération.
Création et ajout de scripts Windows PowerShell
Les tâches de cette rubrique utilisent un exemple de script Windows PowerShell nommé LogDeploy.ps1 pour illustrer comment exécuter des scripts à partir de MSBuild. Le script LogDeploy.ps1 contient une fonction simple qui écrit une entrée sur une seule ligne dans un fichier journal :
function LogDeployment
{
param([string]$filepath,[string]$deployDestination)
$datetime = Get-Date
$filetext = "Deployed package to " + $deployDestination + " on " + $datetime
$filetext | Out-File -filepath $filepath -Append
}
LogDeployment $args[0] $args[1]
Le script LogDeploy.ps1 accepte deux paramètres. Le premier paramètre représente le chemin d’accès complet au fichier journal auquel vous souhaitez ajouter une entrée, et le deuxième paramètre représente la destination de déploiement que vous souhaitez enregistrer dans le fichier journal. Lorsque vous exécutez le script, il ajoute une ligne au fichier journal dans ce format :
Deployed package to TESTWEB1 on 02/11/2012 09:28:18
Pour mettre le script LogDeploy.ps1 à la disposition de MSBuild, vous devez :
- Ajoutez le script au contrôle de code source.
- Ajoutez le script à votre solution dans Visual Studio 2010.
Vous n’avez pas besoin de déployer le script avec le contenu de votre solution, que vous prévoyiez d’exécuter le script sur le serveur de build ou sur un ordinateur distant. Une option consiste à ajouter le script à un dossier de solution. Dans l’exemple du Gestionnaire de contacts, étant donné que vous souhaitez utiliser le script Windows PowerShell dans le cadre du processus de déploiement, il est judicieux d’ajouter le script au dossier Publier la solution.
Le contenu des dossiers de solution est copié pour générer des serveurs en tant que matériau source. Toutefois, elles ne font pas partie de la sortie d’un projet.
Exécution d’un script Windows PowerShell sur le serveur de build
Dans certains scénarios, vous pouvez exécuter des scripts Windows PowerShell sur l’ordinateur qui génère vos projets. Par exemple, vous pouvez utiliser un script Windows PowerShell pour propre des dossiers de build ou écrire des entrées dans un fichier journal personnalisé.
En termes de syntaxe, l’exécution d’un script Windows PowerShell à partir d’un fichier projet MSBuild est identique à l’exécution d’un script Windows PowerShell à partir d’une invite de commandes standard. Vous devez appeler l’exécutable powershell.exe et utiliser le commutateur –command pour fournir les commandes que vous souhaitez exécuter Windows PowerShell. (Dans Windows PowerShell v2, vous pouvez également utiliser le commutateur –file). La commande doit prendre le format suivant :
powershell.exe –command "& { [Path to script] 'parameter1' 'parameter2' ... }"
Par exemple :
powershell.exe –command
"& { C:\LogDeploy.ps1 'C:\DeployLogs\log.txt' 'TESTWEB1' }"
Si le chemin d’accès à votre script comprend des espaces, vous devez placer le chemin d’accès du fichier entre guillemets simples précédés d’une esperluette. Vous ne pouvez pas utiliser de guillemets doubles, car vous les avez déjà utilisés pour inclure la commande :
powershell.exe –command
"& { &'C:\Path With Spaces\LogDeploy.ps1'
'C:\Path With Spaces\log.txt'
'TESTWEB1' }"
Il existe quelques considérations supplémentaires lorsque vous appelez cette commande à partir de MSBuild. Tout d’abord, vous devez inclure l’indicateur –NonInteractive pour vous assurer que le script s’exécute en mode silencieux. Ensuite, vous devez inclure l’indicateur –ExecutionPolicy avec une valeur d’argument appropriée. Cela spécifie la stratégie d’exécution que Windows PowerShell appliquez à votre script et vous permet de remplacer la stratégie d’exécution par défaut, ce qui peut empêcher l’exécution de votre script. Vous pouvez choisir parmi ces valeurs d’argument :
- La valeur Non restreint permet Windows PowerShell d’exécuter votre script, que le script soit signé ou non.
- La valeur RemoteSigned permet Windows PowerShell d’exécuter des scripts non signés créés sur l’ordinateur local. Toutefois, les scripts créés ailleurs doivent être signés. (Dans la pratique, il est très peu probable que vous ayez créé un script Windows PowerShell localement sur un serveur de build).
- La valeur AllSigned permet Windows PowerShell d’exécuter des scripts signés uniquement.
La stratégie d’exécution par défaut est Restricted, ce qui empêche Windows PowerShell d’exécuter des fichiers de script.
Enfin, vous devez placer dans une séquence d’échappement tous les caractères XML réservés qui se produisent dans votre commande Windows PowerShell :
Remplacez les guillemets simples par &apos ;
Remplacez les guillemets doubles par&guillemets ;
Remplacez les esperluette par & ;
Lorsque vous apportez ces modifications, votre commande ressemble à ceci :
powershell.exe –NonInteractive –ExecutionPolicy Unrestricted
–command "& { &'[Path to script]'
'[parameter1]'
'[parameter2]' } "
Dans votre fichier projet MSBuild personnalisé, vous pouvez créer une cible et utiliser la tâche Exec pour exécuter cette commande :
<Target Name="WriteLogEntry" Condition=" '$(WriteLogEntry)'!='false' ">
<PropertyGroup>
<PowerShellExe Condition=" '$(PowerShellExe)'=='' ">
%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe
</PowerShellExe>
<ScriptLocation Condition=" '$(ScriptLocation)'=='' ">
C:\Path With Spaces\LogDeploy.ps1
</ScriptLocation>
<LogFileLocation Condition=" '$(LogFileLocation)'=='' ">
C:\Path With Spaces\ContactManagerDeployLog.txt
</LogFileLocation>
</PropertyGroup>
<Exec Command="$(PowerShellExe) -NonInteractive -executionpolicy Unrestricted
-command "& {
&'$(ScriptLocation)'
'$(LogFileLocation)'
'$(MSDeployComputerName)'} "" />
</Target>
Dans cet exemple, notez que :
- Toutes les variables, telles que les valeurs de paramètre et l’emplacement de l’exécutable Windows PowerShell, sont déclarées en tant que propriétés MSBuild.
- Des conditions sont incluses pour permettre aux utilisateurs de remplacer ces valeurs à partir de la ligne de commande.
- La propriété MSDeployComputerName est déclarée ailleurs dans le fichier projet.
Lorsque vous exécutez cette cible dans le cadre de votre processus de génération, Windows PowerShell exécutez votre commande et écrivez une entrée de journal dans le fichier que vous avez spécifié.
Exécution d’un script Windows PowerShell sur un ordinateur distant
Windows PowerShell est capable d’exécuter des scripts sur des ordinateurs distants via Windows Remote Management (WinRM). Pour ce faire, vous devez utiliser l’applet de commande Invoke-Command . Cela vous permet d’exécuter votre script sur un ou plusieurs ordinateurs distants sans copier le script sur les ordinateurs distants. Tous les résultats sont retournés à l’ordinateur local à partir duquel vous avez exécuté le script.
Notes
Avant d’utiliser l’applet de commande Invoke-Command pour exécuter des scripts Windows PowerShell sur un ordinateur distant, vous devez configurer un écouteur WinRM pour accepter les messages distants. Pour ce faire, exécutez la commande winrm quickconfig sur l’ordinateur distant. Pour plus d’informations, consultez Installation et configuration pour Windows Remote Management.
À partir d’une fenêtre Windows PowerShell, vous utiliseriez cette syntaxe pour exécuter le script LogDeploy.ps1 sur un ordinateur distant :
Invoke-Command –ComputerName 'REMOTESERVER1'
–ScriptBlock { &"C:\Path With Spaces\LogDeploy.ps1"
'C:\Path With Spaces\Log.txt'
'TESTWEB1' }
Notes
Il existe d’autres façons d’utiliser Invoke-Command pour exécuter un fichier de script, mais cette approche est la plus simple lorsque vous devez fournir des valeurs de paramètre et gérer les chemins d’accès avec des espaces.
Lorsque vous exécutez cette commande à partir d’une invite de commandes, vous devez appeler l’exécutable Windows PowerShell et utiliser le paramètre –command pour fournir vos instructions :
powershell.exe –command
"& {Invoke-Command –ComputerName 'REMOTESERVER1'
–ScriptBlock { &'C:\Path With Spaces\LogDeploy.ps1'
'C:\Path With Spaces\Log.txt'
'TESTWEB1' } "
Comme précédemment, vous devez fournir des commutateurs supplémentaires et échapper les caractères XML réservés lorsque vous exécutez la commande à partir de MSBuild :
powershell.exe -NonInteractive -executionpolicy Unrestricted
-command "& Invoke-Command
–ComputerName 'REMOTESERVER1'
-ScriptBlock { &'C:\Path With Spaces\LogDeploy.ps1'
' C:\Path With Spaces\Log.txt '
'TESTWEB1' } "
Enfin, comme précédemment, vous pouvez utiliser la tâche Exec dans une cible MSBuild personnalisée pour exécuter votre commande :
<Target Name="WriteLogEntry" Condition=" '$(WriteLogEntry)'!='false' ">
<PropertyGroup>
<PowerShellExe Condition=" '$(PowerShellExe)'=='' ">
%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe
</PowerShellExe>
<ScriptLocation Condition=" '$(ScriptLocation)'=='' ">
C:\Path With Spaces\LogDeploy.ps1
</ScriptLocation>
<LogFileLocation Condition=" '$(LogFileLocation)'=='' ">
C:\Path With Spaces\ContactManagerDeployLog.txt
</LogFileLocation>
</PropertyGroup>
<Exec Command="$(PowerShellExe) -NonInteractive -executionpolicy Unrestricted
-command "& invoke-command -scriptblock {
&'$(ScriptLocation)'
'$(LogFileLocation)'
'$(MSDeployComputerName)'}
""/>
</Target>
Lorsque vous exécutez cette cible dans le cadre de votre processus de génération, Windows PowerShell exécutez votre script sur l’ordinateur que vous avez spécifié dans l’argument –computername.
Conclusion
Cette rubrique explique comment exécuter un script Windows PowerShell à partir d’un fichier projet MSBuild. Vous pouvez utiliser cette approche pour exécuter un script Windows PowerShell, localement ou sur un ordinateur distant, dans le cadre d’un processus de génération et de déploiement automatisé ou en une seule étape.
En savoir plus
Pour obtenir des conseils sur la signature Windows PowerShell scripts et la gestion des stratégies d’exécution, consultez Exécution de scripts Windows PowerShell. Pour obtenir des conseils sur l’exécution de commandes Windows PowerShell à partir d’un ordinateur distant, consultez Exécution de commandes à distance.
Pour plus d’informations sur l’utilisation de fichiers projet MSBuild personnalisés pour contrôler le processus de déploiement, consultez Présentation du fichier projet et Présentation du processus de génération.