Ausführen von Windows PowerShell-Skripts aus MSBuild-Projektdateien
von Jason Lee
In diesem Thema wird beschrieben, wie Sie ein Windows PowerShell Skript als Teil eines Build- und Bereitstellungsprozesses ausführen. Sie können ein Skript lokal (also auf dem Buildserver) oder remote ausführen, z. B. auf einem Zielwebserver oder Datenbankserver.
Es gibt viele Gründe, warum Sie ein Skript nach der Bereitstellung Windows PowerShell ausführen möchten. Auf diese Weise können Sie z. B. folgende Vorgänge durchführen:
- Fügen Sie der Registrierung eine benutzerdefinierte Ereignisquelle hinzu.
- Generieren Sie ein Dateisystemverzeichnis für Uploads.
- Bereinigen von Buildverzeichnissen.
- Schreiben von Einträgen in eine benutzerdefinierte Protokolldatei.
- Senden von E-Mails, die Benutzer zu einer neu bereitgestellten Webanwendung einladen.
- Erstellen Sie Benutzerkonten mit den entsprechenden Berechtigungen.
- Konfigurieren sie die Replikation zwischen SQL Server Instanzen.
In diesem Thema erfahren Sie, wie Sie Windows PowerShell Skripts sowohl lokal als auch remote von einem benutzerdefinierten Ziel in einer msBuild-Projektdatei (Microsoft-Build-Engine) ausführen.
Dieses Thema ist Teil einer Reihe von Tutorials, die sich auf die Unternehmensbereitstellungsanforderungen eines fiktiven Unternehmens namens Fabrikam, Inc. beziehen. In dieser Tutorialreihe wird eine Beispiellösung – die Contact Manager-Lösung – verwendet, um eine Webanwendung mit einem realistischen Komplexitätsgrad darzustellen, einschließlich einer ASP.NET MVC 3-Anwendung, eines WCF-Diensts (Windows Communication Foundation) und eines Datenbankprojekts.
Die Bereitstellungsmethode im Mittelpunkt dieser Tutorials basiert auf dem unter Grundlegendes zur Projektdatei beschriebenen Ansatz für geteilte Projektdateien, bei dem der Buildprozess von zwei Projektdateien gesteuert wird– eine mit Buildanweisungen, die für jede Zielumgebung gelten, und eine mit umgebungsspezifischen Build- und Bereitstellungseinstellungen. Zur Buildzeit wird die umgebungsspezifische Projektdatei in die umgebungsunabhängige Projektdatei zusammengeführt, um einen vollständigen Satz von Buildanweisungen zu bilden.
Aufgabenübersicht
Um ein Windows PowerShell-Skript als Teil eines automatisierten oder einstufigen Bereitstellungsprozesses auszuführen, müssen Sie die folgenden allgemeinen Aufgaben ausführen:
- Fügen Sie das skript Windows PowerShell ihrer Projektmappe und der Quellcodeverwaltung hinzu.
- Erstellen Sie einen Befehl, der Ihr Windows PowerShell-Skript aufruft.
- Escape aller reservierten XML-Zeichen in Ihrem Befehl.
- Erstellen Sie ein Ziel in Ihrer benutzerdefinierten MSBuild-Projektdatei, und verwenden Sie die Exec-Aufgabe , um den Befehl auszuführen.
In diesem Thema erfahren Sie, wie Sie diese Verfahren ausführen. Bei den Aufgaben und exemplarischen Vorgehensweisen in diesem Thema wird davon ausgegangen, dass Sie bereits mit MSBuild-Zielen und -Eigenschaften vertraut sind und dass Sie wissen, wie Sie eine benutzerdefinierte MSBuild-Projektdatei verwenden, um einen Build- und Bereitstellungsprozess zu steuern. Weitere Informationen finden Sie unter Grundlegendes zur Projektdatei und Grundlegendes zum Buildprozess.
Erstellen und Hinzufügen von Windows PowerShell Skripts
Die Aufgaben in diesem Thema verwenden ein Beispiel Windows PowerShell Skripts mit dem Namen LogDeploy.ps1, um zu veranschaulichen, wie Skripts aus MSBuild ausgeführt werden. Das LogDeploy.ps1 Skript enthält eine einfache Funktion, die einen einzeiligen Eintrag in eine Protokolldatei schreibt:
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]
Das LogDeploy.ps1-Skript akzeptiert zwei Parameter. Der erste Parameter stellt den vollständigen Pfad zu der Protokolldatei dar, der Sie einen Eintrag hinzufügen möchten, und der zweite Parameter stellt das Bereitstellungsziel dar, das Sie in der Protokolldatei aufzeichnen möchten. Wenn Sie das Skript ausführen, wird der Protokolldatei eine Zeile in diesem Format hinzugefügt:
Deployed package to TESTWEB1 on 02/11/2012 09:28:18
Um das LogDeploy.ps1 Skript für MSBuild verfügbar zu machen, müssen Sie:
- Fügen Sie das Skript zur Quellcodeverwaltung hinzu.
- Fügen Sie das Skript ihrer Projektmappe in Visual Studio 2010 hinzu.
Sie müssen das Skript nicht mit Ihrem Lösungsinhalt bereitstellen, unabhängig davon, ob Sie das Skript auf dem Buildserver oder auf einem Remotecomputer ausführen möchten. Eine Möglichkeit besteht darin, das Skript einem Projektmappenordner hinzuzufügen. Da Sie im Contact Manager-Beispiel das Windows PowerShell Skript als Teil des Bereitstellungsprozesses verwenden möchten, ist es sinnvoll, das Skript dem Projektmappenordner veröffentlichen hinzuzufügen.
Der Inhalt von Projektmappenordnern wird als Quellmaterial auf Buildserver kopiert. Sie sind jedoch kein Teil einer Projektausgabe.
Ausführen eines Windows PowerShell-Skripts auf dem Buildserver
In einigen Szenarien können Sie Windows PowerShell Skripts auf dem Computer ausführen, auf dem Ihre Projekte erstellt werden. Sie können beispielsweise ein Windows PowerShell Skript verwenden, um Buildordner zu sauber oder Einträge in eine benutzerdefinierte Protokolldatei zu schreiben.
In Bezug auf die Syntax entspricht das Ausführen eines Windows PowerShell Skripts aus einer MSBuild-Projektdatei dem Ausführen eines Windows PowerShell Skripts über eine reguläre Eingabeaufforderung. Sie müssen die powershell.exe ausführbare Datei aufrufen und den Schalter –command verwenden, um die Befehle bereitzustellen, die Windows PowerShell ausgeführt werden sollen. (In Windows PowerShell v2 können Sie auch den Schalter –file verwenden. Der Befehl sollte das folgende Format annehmen:
powershell.exe –command "& { [Path to script] 'parameter1' 'parameter2' ... }"
Beispiel:
powershell.exe –command
"& { C:\LogDeploy.ps1 'C:\DeployLogs\log.txt' 'TESTWEB1' }"
Wenn der Pfad zu Ihrem Skript Leerzeichen enthält, müssen Sie den Dateipfad in einfache Anführungszeichen einschließen, denen ein Ampersand vorangestellt ist. Sie können keine doppelten Anführungszeichen verwenden, da Sie sie bereits zum Einschließen des Befehls verwendet haben:
powershell.exe –command
"& { &'C:\Path With Spaces\LogDeploy.ps1'
'C:\Path With Spaces\log.txt'
'TESTWEB1' }"
Es gibt einige zusätzliche Überlegungen, wenn Sie diesen Befehl aus MSBuild aufrufen. Zunächst sollten Sie das Flag –NonInteractive einschließen, um sicherzustellen, dass das Skript ruhig ausgeführt wird. Als Nächstes sollten Sie das Flag –ExecutionPolicy mit einem entsprechenden Argumentwert einschließen. Dies gibt die Ausführungsrichtlinie an, die Windows PowerShell auf Ihr Skript anwenden wird, und ermöglicht es Ihnen, die Standardausführungsrichtlinie zu überschreiben, wodurch die Ausführung Ihres Skripts verhindert werden kann. Sie können aus den folgenden Argumentwerten wählen:
- Der Wert Unrestricted ermöglicht es Windows PowerShell, Ihr Skript auszuführen, unabhängig davon, ob das Skript signiert ist.
- Mit dem Wert RemoteSigned können Windows PowerShell Skripts ohne Vorzeichen ausführen, die auf dem lokalen Computer erstellt wurden. Skripts, die an anderer Stelle erstellt wurden, müssen jedoch signiert werden. (In der Praxis ist es sehr unwahrscheinlich, dass Sie lokal auf einem Buildserver ein Windows PowerShell Skript erstellt haben.)
- Mit dem Wert AllSigned können Windows PowerShell nur signierte Skripts ausführen.
Die Standardausführungsrichtlinie ist Eingeschränkt, wodurch verhindert wird, dass Windows PowerShell Skriptdateien ausführen.
Schließlich müssen Sie alle reservierten XML-Zeichen, die in Ihrem Windows PowerShell-Befehl vorkommen, mit Escapezeichen versehen:
Ersetzen Sie einfache Anführungszeichen durch '
Ersetzen Sie doppelte Anführungszeichen durch "
Ersetzen Sie ampersands durch &
Wenn Sie diese Änderungen vornehmen, sieht Ihr Befehl wie folgt aus:
powershell.exe –NonInteractive –ExecutionPolicy Unrestricted
–command "& { &'[Path to script]'
'[parameter1]'
'[parameter2]' } "
In Ihrer benutzerdefinierten MSBuild-Projektdatei können Sie ein neues Ziel erstellen und den Task Exec verwenden, um diesen Befehl auszuführen:
<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>
Beachten Sie in diesem Beispiel Folgendes:
- Alle Variablen, z. B. Parameterwerte und der Speicherort der ausführbaren Windows PowerShell, werden als MSBuild-Eigenschaften deklariert.
- Es sind Bedingungen enthalten, damit Benutzer diese Werte über die Befehlszeile überschreiben können.
- Die MSDeployComputerName-Eigenschaft wird an anderer Stelle in der Projektdatei deklariert.
Wenn Sie dieses Ziel im Rahmen des Buildprozesses ausführen, führen Windows PowerShell Ihren Befehl aus und schreiben einen Protokolleintrag in die von Ihnen angegebene Datei.
Ausführen eines Windows PowerShell-Skripts auf einem Remotecomputer
Windows PowerShell ist in der Lage, Skripts auf Remotecomputern über die Windows-Remoteverwaltung (WinRM) auszuführen. Dazu müssen Sie das Cmdlet Invoke-Command verwenden. Dadurch können Sie Ihr Skript für einen oder mehrere Remotecomputer ausführen, ohne das Skript auf die Remotecomputer zu kopieren. Alle Ergebnisse werden an den lokalen Computer zurückgegeben, auf dem Sie das Skript ausgeführt haben.
Hinweis
Bevor Sie das Cmdlet Invoke-Command verwenden, um Windows PowerShell Skripts auf einem Remotecomputer auszuführen, müssen Sie einen WinRM-Listener konfigurieren, um Remotenachrichten zu akzeptieren. Dazu können Sie den Befehl winrm quickconfig auf dem Remotecomputer ausführen. Weitere Informationen finden Sie unter Installation und Konfiguration für die Windows-Remoteverwaltung.
In einem Windows PowerShell Fenster würden Sie diese Syntax verwenden, um das LogDeploy.ps1-Skript auf einem Remotecomputer auszuführen:
Invoke-Command –ComputerName 'REMOTESERVER1'
–ScriptBlock { &"C:\Path With Spaces\LogDeploy.ps1"
'C:\Path With Spaces\Log.txt'
'TESTWEB1' }
Hinweis
Es gibt verschiedene andere Möglichkeiten, invoke-Command zum Ausführen einer Skriptdatei zu verwenden, aber dieser Ansatz ist am einfachsten, wenn Sie Parameterwerte angeben und Pfade mit Leerzeichen verwalten müssen.
Wenn Sie dies über eine Eingabeaufforderung ausführen, müssen Sie die ausführbare Windows PowerShell aufrufen und den Parameter –command verwenden, um Ihre Anweisungen bereitzustellen:
powershell.exe –command
"& {Invoke-Command –ComputerName 'REMOTESERVER1'
–ScriptBlock { &'C:\Path With Spaces\LogDeploy.ps1'
'C:\Path With Spaces\Log.txt'
'TESTWEB1' } "
Wie zuvor müssen Sie einige zusätzliche Schalter bereitstellen und reservierte XML-Zeichen mit Escapezeichen versehen, wenn Sie den Befehl über MSBuild ausführen:
powershell.exe -NonInteractive -executionpolicy Unrestricted
-command "& Invoke-Command
–ComputerName 'REMOTESERVER1'
-ScriptBlock { &'C:\Path With Spaces\LogDeploy.ps1'
' C:\Path With Spaces\Log.txt '
'TESTWEB1' } "
Schließlich können Sie wie zuvor den Task Exec innerhalb eines benutzerdefinierten MSBuild-Ziels verwenden, um Ihren Befehl auszuführen:
<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>
Wenn Sie dieses Ziel im Rahmen des Buildprozesses ausführen, führen Windows PowerShell Ihr Skript auf dem Computer aus, den Sie im Argument –computername angegeben haben.
Zusammenfassung
In diesem Thema wurde beschrieben, wie Sie ein Windows PowerShell Skript aus einer MSBuild-Projektdatei ausführen. Sie können diesen Ansatz verwenden, um ein Windows PowerShell Skript entweder lokal oder auf einem Remotecomputer als Teil eines automatisierten oder einstufigen Build- und Bereitstellungsprozesses auszuführen.
Weitere Informationen
Eine Anleitung zum Signieren Windows PowerShell Skripts und zum Verwalten von Ausführungsrichtlinien finden Sie unter Ausführen Windows PowerShell Skripts. Eine Anleitung zum Ausführen von Windows PowerShell Befehlen von einem Remotecomputer finden Sie unter Ausführen von Remotebefehlen.
Weitere Informationen zur Verwendung benutzerdefinierter MSBuild-Projektdateien zum Steuern des Bereitstellungsprozesses finden Sie unter Grundlegendes zur Projektdatei und Grundlegendes zum Buildprozess.