Esecuzione di script di Windows PowerShell dai file di progetto di MSBuild

di Jason Lee

Questo argomento descrive come eseguire uno script Windows PowerShell come parte di un processo di compilazione e distribuzione. È possibile eseguire uno script in locale (in altre parole, nel server di compilazione) o in remoto, ad esempio in un server Web di destinazione o in un server di database.

Esistono molti motivi per cui si potrebbe voler eseguire uno script di post-distribuzione Windows PowerShell. Può, ad esempio, essere necessario:

  • Aggiungere un'origine evento personalizzata al Registro di sistema.
  • Generare una directory del file system per i caricamenti.
  • Pulire le directory di compilazione.
  • Scrivere voci in un file di log personalizzato.
  • Inviare messaggi di posta elettronica che invitano gli utenti a un'applicazione Web appena sottoposto a provisioning.
  • Creare account utente con le autorizzazioni appropriate.
  • Configurare la replica tra istanze di SQL Server.

Questo argomento illustra come eseguire script Windows PowerShell sia in locale che in remoto da una destinazione personalizzata in un file di progetto Microsoft Build Engine (MSBuild).

Questo argomento fa parte di una serie di esercitazioni basate sui requisiti di distribuzione aziendali di una società fittizia denominata Fabrikam, Inc. Questa serie di esercitazioni usa una soluzione di esempio, la soluzione Contact Manager, per rappresentare un'applicazione Web con un livello realistico di complessità, tra cui un'applicazione MVC 3 ASP.NET, un servizio Windows Communication Foundation (WCF) e un progetto di database.

Il metodo di distribuzione al centro di queste esercitazioni si basa sull'approccio di suddivisione del file di progetto descritto in Informazioni sul file di progetto, in cui il processo di compilazione è controllato da due file di progetto, uno contenente istruzioni di compilazione che si applicano a ogni ambiente di destinazione e uno contenente le impostazioni di compilazione e distribuzione specifiche dell'ambiente. In fase di compilazione, il file di progetto specifico dell'ambiente viene unito al file di progetto agnostico dell'ambiente per formare un set completo di istruzioni di compilazione.

Panoramica delle attività

Per eseguire uno script Windows PowerShell come parte di un processo di distribuzione automatizzato o in un singolo passaggio, è necessario completare queste attività di alto livello:

  • Aggiungere lo script Windows PowerShell alla soluzione e al controllo del codice sorgente.
  • Creare un comando che richiama lo script di Windows PowerShell.
  • Eseguire l'escape di tutti i caratteri XML riservati nel comando.
  • Creare una destinazione nel file di progetto MSBuild personalizzato e usare l'attività Exec per eseguire il comando.

Questo argomento illustra come eseguire queste procedure. Le attività e le procedure dettagliate in questo argomento presuppongono che si abbia già familiarità con le destinazioni e le proprietà di MSBuild e che si capisce come usare un file di progetto MSBuild personalizzato per guidare un processo di compilazione e distribuzione. Per altre informazioni, vedere Informazioni sul file di progetto e informazioni sul processo di compilazione.

Creazione e aggiunta di script di Windows PowerShell

Le attività di questo argomento usano uno script di esempio Windows PowerShell denominato LogDeploy.ps1 per illustrare come eseguire script da MSBuild. Lo script LogDeploy.ps1 contiene una semplice funzione che scrive una voce a riga singola in un file di log:

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]

Lo script LogDeploy.ps1 accetta due parametri. Il primo parametro rappresenta il percorso completo del file di log a cui si vuole aggiungere una voce e il secondo parametro rappresenta la destinazione di distribuzione da registrare nel file di log. Quando si esegue lo script, aggiunge una riga al file di log in questo formato:

Deployed package to TESTWEB1 on 02/11/2012 09:28:18

Per rendere disponibile lo script diLogDeploy.ps1 per MSBuild, è necessario:

  • Aggiungere lo script al controllo del codice sorgente.
  • Aggiungere lo script alla soluzione in Visual Studio 2010.

Non è necessario distribuire lo script con il contenuto della soluzione, indipendentemente dal fatto che si prevede di eseguire lo script nel server di compilazione o in un computer remoto. Un'opzione consiste nell'aggiungere lo script a una cartella della soluzione. Nell'esempio di Contact Manager, poiché si vuole usare lo script di Windows PowerShell come parte del processo di distribuzione, è consigliabile aggiungere lo script alla cartella Pubblica soluzione.

Nell'esempio di Contact Manager, poiché si vuole usare lo script di Windows PowerShell come parte del processo di distribuzione, è consigliabile aggiungere lo script alla cartella Pubblica soluzione.

Il contenuto delle cartelle della soluzione viene copiato nei server di compilazione come materiale di origine. Tuttavia, non fanno parte di alcun output del progetto.

Esecuzione di uno script di Windows PowerShell nel server di compilazione

In alcuni scenari, è possibile eseguire script Windows PowerShell nel computer che compila i progetti. Ad esempio, è possibile usare uno script di Windows PowerShell per pulire le cartelle di compilazione o scrivere voci in un file di log personalizzato.

In termini di sintassi, l'esecuzione di uno script Windows PowerShell da un file di progetto MSBuild è identica all'esecuzione di uno script Windows PowerShell da un normale prompt dei comandi. È necessario richiamare l'eseguibile powershell.exe e usare l'opzione –command per fornire i comandi da eseguire Windows PowerShell. In Windows PowerShell v2 è anche possibile usare l'opzione –file. Il comando deve accettare questo formato:

powershell.exe –command "& { [Path to script] 'parameter1' 'parameter2' ... }"

Ad esempio:

powershell.exe –command 
  "& { C:\LogDeploy.ps1 'C:\DeployLogs\log.txt' 'TESTWEB1' }"

Se il percorso dello script include spazi, è necessario racchiudere il percorso del file in virgolette singole precedute da un amperand. Non è possibile usare virgolette doppie, perché sono già state usate per racchiudere il comando:

powershell.exe –command 
  "& { &'C:\Path With Spaces\LogDeploy.ps1' 
        'C:\Path With Spaces\log.txt' 
        'TESTWEB1' }"

Esistono alcune considerazioni aggiuntive quando si richiama questo comando da MSBuild. Prima di tutto, è necessario includere il flag –NonInteractive per assicurarsi che lo script venga eseguito in modo tranquillo. È quindi necessario includere il flag –ExecutionPolicy con un valore di argomento appropriato. In questo modo viene specificato il criterio di esecuzione che Windows PowerShell verrà applicato allo script e consente di eseguire l'override dei criteri di esecuzione predefiniti, che potrebbero impedire l'esecuzione dello script. È possibile scegliere tra questi valori di argomento:

  • Un valore senza restrizioni consentirà Windows PowerShell di eseguire lo script, indipendentemente dal fatto che lo script sia firmato.
  • Un valore di RemoteSigned consentirà Windows PowerShell di eseguire script non firmati creati nel computer locale. Tuttavia, gli script creati altrove devono essere firmati. In pratica, è molto probabile che sia stato creato uno script Windows PowerShell localmente in un server di compilazione.
  • Un valore di AllSigned consente Windows PowerShell di eseguire solo script firmati.

Il criterio di esecuzione predefinito è limitato, che impedisce Windows PowerShell di eseguire tutti i file di script.

Infine, è necessario eseguire l'escape di tutti i caratteri XML riservati che si verificano nel comando Windows PowerShell:

  • Sostituire virgolette singole con '

  • Sostituire virgolette doppie con&virgolette;

  • Sostituire gli amperandi con &

  • Quando si apportano queste modifiche, il comando sarà simile al seguente:

powershell.exe –NonInteractive –ExecutionPolicy Unrestricted 
               –command "& { &'[Path to script]' 
                        '[parameter1]' 
                        '[parameter2]' } "

All'interno del file di progetto MSBuild personalizzato, è possibile creare una nuova destinazione e usare l'attività Exec per eseguire questo comando:

<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 &quot;&amp; { 
                          &amp;&apos;$(ScriptLocation)&apos; 
                          &apos;$(LogFileLocation)&apos; 
                          &apos;$(MSDeployComputerName)&apos;} &quot;" />
</Target>

In questo esempio si noti che:

  • Tutte le variabili, ad esempio i valori dei parametri e il percorso dell'eseguibile Windows PowerShell, vengono dichiarate come proprietà DI MSBuild.
  • Le condizioni sono incluse per consentire agli utenti di eseguire l'override di questi valori dalla riga di comando.
  • La proprietà MSDeployComputerName viene dichiarata altrove nel file di progetto.

Quando si esegue questa destinazione come parte del processo di compilazione, Windows PowerShell eseguirà il comando e scriverà una voce di log nel file specificato.

Esecuzione di uno script di Windows PowerShell in un computer remoto

Windows PowerShell è in grado di eseguire script nei computer remoti tramite Gestione remota Windows (WinRM). A tale scopo, è necessario usare il cmdlet Invoke-Command . In questo modo è possibile eseguire lo script su uno o più computer remoti senza copiare lo script nei computer remoti. Tutti i risultati vengono restituiti al computer locale da cui è stato eseguito lo script.

Nota

Prima di usare il cmdlet Invoke-Command per eseguire script Windows PowerShell in un computer remoto, è necessario configurare un listener WinRM per accettare messaggi remoti. È possibile eseguire questa operazione eseguendo il comando winrm quickconfig nel computer remoto. Per altre informazioni, vedere Installazione e configurazione per Gestione remota Windows.

Da una finestra Windows PowerShell si userà questa sintassi per eseguire lo script diLogDeploy.ps1 in un computer remoto:

Invoke-Command –ComputerName 'REMOTESERVER1' 
               –ScriptBlock { &"C:\Path With Spaces\LogDeploy.ps1"
                               'C:\Path With Spaces\Log.txt'
                               'TESTWEB1' }

Nota

Esistono diversi modi per usare Invoke-Command per eseguire un file di script, ma questo approccio è più semplice quando è necessario fornire i valori dei parametri e gestire i percorsi con gli spazi.

Quando si esegue questa operazione da un prompt dei comandi, è necessario richiamare il file eseguibile Windows PowerShell e usare il parametro –command per fornire le istruzioni seguenti:

powershell.exe –command 
  "& {Invoke-Command –ComputerName 'REMOTESERVER1' 
                     –ScriptBlock { &'C:\Path With Spaces\LogDeploy.ps1'
                                     'C:\Path With Spaces\Log.txt'
                                     'TESTWEB1' } "

Come prima, è necessario fornire alcune opzioni aggiuntive ed eseguire l'escape di tutti i caratteri XML riservati quando si esegue il comando da MSBuild:

powershell.exe -NonInteractive -executionpolicy Unrestricted 
               -command &quot;&amp; Invoke-Command 
                 –ComputerName &apos;REMOTESERVER1&apos;
                 -ScriptBlock { &amp;&apos;C:\Path With Spaces\LogDeploy.ps1&apos; 
                                &apos; C:\Path With Spaces\Log.txt &apos;  
                                &apos;TESTWEB1&apos; } &quot;

Infine, come prima, è possibile usare l'attività Exec all'interno di una destinazione MSBuild personalizzata per eseguire il comando:

<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 &quot;&amp; invoke-command -scriptblock { 
                          &amp;&apos;$(ScriptLocation)&apos; 
                          &apos;$(LogFileLocation)&apos;  
                          &apos;$(MSDeployComputerName)&apos;}
                          &quot;"/>  
</Target>

Quando si esegue questa destinazione come parte del processo di compilazione, Windows PowerShell eseguirà lo script nel computer specificato nell'argomento -computername.

Conclusione

Questo argomento descrive come eseguire uno script Windows PowerShell da un file di progetto MSBuild. È possibile usare questo approccio per eseguire uno script di Windows PowerShell, in locale o in un computer remoto, come parte di un processo di compilazione e distribuzione automatizzato o single-step.

Altre informazioni

Per indicazioni sulla firma di script Windows PowerShell e sulla gestione dei criteri di esecuzione, vedere Esecuzione di script Windows PowerShell. Per indicazioni sull'esecuzione di comandi Windows PowerShell da un computer remoto, vedere Esecuzione di comandi remoti.

Per altre informazioni sull'uso di file di progetto MSBuild personalizzati per controllare il processo di distribuzione, vedere Informazioni sul file di progetto e informazioni sul processo di compilazione.