Partilhar via


Execução de scripts do Windows PowerShell de arquivos de projeto do MSBuild

por Jason Lee

Este tópico descreve como executar um script de Windows PowerShell como parte de um processo de build e implantação. Você pode executar um script localmente (em outras palavras, no servidor de build) ou remotamente, como em um servidor Web de destino ou servidor de banco de dados.

Há muitos motivos pelos quais talvez você queira executar um script de Windows PowerShell pós-implantação. Por exemplo, você pode querer:

  • Adicione uma origem de evento personalizada ao registro.
  • Gere um diretório do sistema de arquivos para uploads.
  • Limpe os diretórios de build.
  • Gravar entradas em um arquivo de log personalizado.
  • Envie emails convidando usuários para um aplicativo Web recém-provisionado.
  • Crie contas de usuário com as permissões apropriadas.
  • Configurar a replicação entre instâncias de SQL Server.

Este tópico mostrará como executar Windows PowerShell scripts local e remotamente de um destino personalizado em um arquivo de projeto do Microsoft Build Engine (MSBuild).

Este tópico faz parte de uma série de tutoriais baseados nos requisitos de implantação corporativa de uma empresa fictícia chamada Fabrikam, Inc. Esta série de tutoriais usa uma solução de exemplo, a solução do Contact Manager, para representar um aplicativo Web com um nível realista de complexidade, incluindo um aplicativo ASP.NET MVC 3, um serviço WCF (Windows Communication Foundation) e um projeto de banco de dados.

O método de implantação no centro desses tutoriais baseia-se na abordagem de arquivo de projeto dividido descrita em Noções básicas sobre o Arquivo de Projeto, na qual o processo de build é controlado por dois arquivos de projeto, um contendo instruções de build que se aplicam a cada ambiente de destino e outro que contém configurações de build e implantação específicas do ambiente. No momento do build, o arquivo de projeto específico do ambiente é mesclado no arquivo de projeto independente do ambiente para formar um conjunto completo de instruções de build.

Visão geral da tarefa

Para executar um script Windows PowerShell como parte de um processo de implantação automatizado ou de etapa única, você precisará concluir essas tarefas de alto nível:

  • Adicione o script Windows PowerShell à sua solução e ao controle do código-fonte.
  • Crie um comando que invoque seu script de Windows PowerShell.
  • Escape de todos os caracteres XML reservados em seu comando.
  • Crie um destino no arquivo de projeto personalizado do MSBuild e use a tarefa Exec para executar o comando.

Este tópico mostrará como executar esses procedimentos. As tarefas e instruções passo a passo neste tópico pressupõem que você já esteja familiarizado com destinos e propriedades do MSBuild e que você entenda como usar um arquivo de projeto personalizado do MSBuild para conduzir um processo de build e implantação. Para obter mais informações, consulte Noções básicas sobre o arquivo de projeto e Noções básicas sobre o processo de build.

Criando e adicionando scripts de Windows PowerShell

As tarefas neste tópico usam um exemplo Windows PowerShell script chamado LogDeploy.ps1 para ilustrar como executar scripts do MSBuild. O scriptLogDeploy.ps1 contém uma função simples que grava uma entrada de linha única em um arquivo de 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]

O scriptLogDeploy.ps1 aceita dois parâmetros. O primeiro parâmetro representa o caminho completo para o arquivo de log ao qual você deseja adicionar uma entrada e o segundo parâmetro representa o destino de implantação que você deseja registrar no arquivo de log. Quando você executa o script, ele adiciona uma linha ao arquivo de log neste formato:

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

Para disponibilizar o script LogDeploy.ps1 para o MSBuild, você precisa:

  • Adicione o script ao controle do código-fonte.
  • Adicione o script à sua solução no Visual Studio 2010.

Você não precisa implantar o script com o conteúdo da solução, independentemente de planejar executar o script no servidor de build ou em um computador remoto. Uma opção é adicionar o script a uma pasta de solução. No exemplo do Gerenciador de Contatos, como você deseja usar o script Windows PowerShell como parte do processo de implantação, faz sentido adicionar o script à pasta Publicar solução.

No exemplo do Gerenciador de Contatos, como você deseja usar o script Windows PowerShell como parte do processo de implantação, faz sentido adicionar o script à pasta Publicar solução.

O conteúdo das pastas de solução é copiado para criar servidores como material de origem. No entanto, eles não fazem parte de nenhuma saída do projeto.

Executando um script de Windows PowerShell no servidor de build

Em alguns cenários, talvez você queira executar Windows PowerShell scripts no computador que compila seus projetos. Por exemplo, você pode usar um script Windows PowerShell para limpo pastas de build ou gravar entradas em um arquivo de log personalizado.

Em termos de sintaxe, executar um script Windows PowerShell de um arquivo de projeto do MSBuild é o mesmo que executar um script Windows PowerShell de um prompt de comando regular. Você precisa invocar a powershell.exe executável e usar a opção –command para fornecer os comandos que você deseja que Windows PowerShell executar. (No Windows PowerShell v2, você também pode usar a opção –file). O comando deve ter esse formato:

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

Por exemplo:

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

Se o caminho para o script incluir espaços, você precisará colocar o caminho do arquivo entre aspas simples precedidas por um e comercial. Você não pode usar aspas duplas, pois já as usou para colocar o comando entre aspas:

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

Há algumas considerações adicionais quando você invoca esse comando do MSBuild. Primeiro, você deve incluir o sinalizador –NonInteractive para garantir que o script seja executado silenciosamente. Em seguida, você deve incluir o sinalizador –ExecutionPolicy com um valor de argumento apropriado. Isso especifica a política de execução que Windows PowerShell será aplicada ao script e permite que você substitua a política de execução padrão, o que pode impedir a execução do script. Você pode escolher entre estes valores de argumento:

  • Um valor de Irrestrito permitirá que Windows PowerShell execute o script, independentemente de o script ser assinado.
  • Um valor de RemoteSigned permitirá que Windows PowerShell execute scripts não assinados que foram criados no computador local. No entanto, os scripts que foram criados em outro lugar devem ser assinados. (Na prática, é muito improvável que você tenha criado um script Windows PowerShell localmente em um servidor de build).
  • Um valor AllSigned permitirá que Windows PowerShell execute apenas scripts assinados.

A política de execução padrão é Restrita, o que impede que Windows PowerShell executem arquivos de script.

Por fim, você precisa escapar de todos os caracteres XML reservados que ocorrem no comando Windows PowerShell:

  • Substitua as aspas simples por '

  • Substitua aspas duplas por &aspas;

  • Substituir e comercialmente por &

  • Quando você fizer essas alterações, o comando será semelhante a este:

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

No arquivo de projeto personalizado do MSBuild, você pode criar um novo destino e usar a tarefa Exec para executar este 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>

Neste exemplo, observe que:

  • Todas as variáveis, como valores de parâmetro e o local do executável Windows PowerShell, são declaradas como propriedades do MSBuild.
  • As condições são incluídas para permitir que os usuários substituam esses valores da linha de comando.
  • A propriedade MSDeployComputerName é declarada em outro lugar no arquivo de projeto.

Quando você executa esse destino como parte do processo de build, Windows PowerShell executará seu comando e gravará uma entrada de log no arquivo especificado.

Executando um script Windows PowerShell em um computador remoto

Windows PowerShell é capaz de executar scripts em computadores remotos por meio do WinRM (Gerenciamento Remoto do Windows). Para fazer isso, você precisa usar o cmdlet Invoke-Command . Isso permite que você execute seu script em um ou mais computadores remotos sem copiar o script para os computadores remotos. Todos os resultados são retornados para o computador local do qual você executou o script.

Observação

Antes de usar o cmdlet Invoke-Command para executar scripts Windows PowerShell em um computador remoto, você precisa configurar um ouvinte WinRM para aceitar mensagens remotas. Você pode fazer isso executando o comando winrm quickconfig no computador remoto. Para obter mais informações, consulte Instalação e configuração do Gerenciamento Remoto do Windows.

Em uma janela Windows PowerShell, você usaria essa sintaxe para executar o script LogDeploy.ps1 em um computador remoto:

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

Observação

Há várias outras maneiras de usar Invoke-Command para executar um arquivo de script, mas essa abordagem é a mais simples quando você precisa fornecer valores de parâmetro e gerenciar caminhos com espaços.

Ao executar isso em um prompt de comando, você precisa invocar o executável Windows PowerShell e usar o parâmetro –command para fornecer suas instruções:

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

Como antes, você precisa fornecer alguns comutadores adicionais e escapar de todos os caracteres XML reservados ao executar o comando do 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;

Por fim, como antes, você pode usar a tarefa Exec em um destino personalizado do MSBuild para executar seu 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>

Ao executar esse destino como parte do processo de build, Windows PowerShell executará o script no computador especificado no argumento –computername.

Conclusão

Este tópico descreveu como executar um script de Windows PowerShell de um arquivo de projeto do MSBuild. Você pode usar essa abordagem para executar um script de Windows PowerShell, localmente ou em um computador remoto, como parte de um processo de build e implantação automatizado ou de etapa única.

Leitura Adicional

Para obter diretrizes sobre como assinar scripts Windows PowerShell e gerenciar políticas de execução, consulte Executando scripts de Windows PowerShell. Para obter diretrizes sobre como executar comandos Windows PowerShell de um computador remoto, consulte Executando comandos remotos.

Para obter mais informações sobre como usar arquivos de projeto personalizados do MSBuild para controlar o processo de implantação, consulte Noções básicas sobre o arquivo de projeto e Noções básicas sobre o processo de build.