Partilhar via


Executar scripts PowerShell do Windows a partir de ficheiros de projeto MSBuild

por Jason Lee

Este tópico descreve como executar um script PowerShell do Windows como parte de um processo de compilação e implementação. Podes executar um script localmente (ou seja, no servidor de compilação) ou remotamente, como num servidor web de destino ou servidor de base de dados.

Existem muitas razões pelas quais pode querer executar um script Windows PowerShell pós-implementação. Por exemplo, você pode querer:

  • Adicione uma fonte de evento personalizada ao registo.
  • Gera um diretório do sistema de ficheiros para os carregamentos.
  • Limpar diretórios de build.
  • Escreve entradas num ficheiro de registo personalizado.
  • Envie emails a convidar os utilizadores para uma aplicação web recém-provisionada.
  • Crie contas de utilizador com as permissões apropriadas.
  • Configurar a replicação entre instâncias do SQL Server.

Este tópico vai mostrar-lhe como executar scripts PowerShell do Windows, tanto localmente como remotamente, a partir de um alvo personalizado num ficheiro de projeto do Microsoft Build Engine (MSBuild).

Este tema faz parte de uma série de tutoriais baseados nos requisitos de implementação empresarial de uma empresa fictícia chamada Fabrikam, Inc. Esta série de tutoriais utiliza uma solução de exemplo — a solução Contact Manager — para representar uma aplicação web com um nível realista de complexidade, incluindo uma aplicação ASP.NET MVC 3, um serviço Windows Communication Foundation (WCF) e um projeto de base de dados.

O método de implementação no centro destes tutoriais baseia-se na abordagem de ficheiros de projeto divididos descrita em Compreender o Ficheiro do Projeto, em que o processo de compilação é controlado por dois ficheiros de projeto — um contendo instruções de compilação que se aplicam a todos os ambientes de destino, e outro contendo definições específicas de compilação e implementação do ambiente. No momento da compilação, o ficheiro de projeto específico do ambiente é fundido no ficheiro de projeto independente do ambiente para formar um conjunto completo de instruções de compilação.

Visão Geral da Tarefa

Para executar um script PowerShell do Windows como parte de um processo automatizado ou de implementação de uma só etapa, terá de completar estas tarefas de alto nível:

  • Adicione o script PowerShell do Windows à sua solução e ao controlo de versão.
  • Crie um comando que invoque o seu script PowerShell do Windows.
  • Escape quaisquer caracteres XML reservados no seu comando.
  • Cria um alvo no teu ficheiro de projeto MSBuild personalizado e usa a tarefa Exec para executar o teu comando.

Este tópico irá mostrar-lhe como realizar estes procedimentos. As tarefas e guias deste tópico assumem que já está familiarizado com os alvos e propriedades do MSBuild, e que sabe como usar um ficheiro de projeto personalizado do MSBuild para gerir um processo de construção e implementação. Para mais informações, consulte Compreender o Ficheiro do Projeto e Compreender o Processo de Construção.

Criação e Adição de Scripts PowerShell para Windows

As tarefas deste tópico utilizam um exemplo de script PowerShell do Windows chamado LogDeploy.ps1 para ilustrar como executar scripts a partir do MSBuild. O scriptLogDeploy.ps1 contém uma função simples que escreve uma entrada de linha única num ficheiro 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 ficheiro de registo ao qual pretende adicionar uma entrada, e o segundo parâmetro representa o destino de implementação que pretende registar no ficheiro de registo. Quando executas o script, ele adiciona uma linha ao ficheiro de registo neste formato:

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

Para disponibilizar o scriptLogDeploy.ps1 à MSBuild, é necessário que:

  • Adiciona o script ao controlo de código fonte.
  • Adicione o script à sua solução no Visual Studio 2010.

Não precisa de implementar o script com o conteúdo da sua solução, independentemente de planear executar o script no servidor de compilação ou num computador remoto. Uma opção é adicionar o script a uma pasta de solução. No exemplo do Gestor de Contactos, porque queres usar o script PowerShell do Windows como parte do processo de implementação, faz sentido adicionar o script à pasta Publicar da solução.

No exemplo do Gestor de Contactos, porque queres usar o script PowerShell do Windows como parte do processo de implementação, faz sentido adicionar o script à pasta Publicar da solução.

O conteúdo das pastas da solução é copiado para construir servidores como material de origem. No entanto, não fazem parte de qualquer produção do projeto.

Executar um script PowerShell para Windows no servidor de compilação

Em alguns cenários, pode querer executar scripts do Windows PowerShell no computador que constrói os seus projetos. Por exemplo, podes usar um script PowerShell do Windows para limpar pastas de construção ou escrever entradas num ficheiro de registo personalizado.

Em termos de sintaxe, executar um script PowerShell do Windows a partir de um ficheiro de projeto MSBuild é o mesmo que executar um script PowerShell do Windows a partir de um prompt de comandos normal. Tens de invocar o executável powershell.exe e usar o comando – para fornecer os comandos que queres que o Windows PowerShell execute. (No Windows PowerShell v2, também pode usar o switch –file ). O comando deve adotar este 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 seu script incluir espaços, precisa de encerrar o caminho do ficheiro em aspas simples precedidas por um ampersand. Não podes usar aspas duplas, porque já as usaste para incluir o comando:

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

Existem algumas considerações adicionais ao invocar este comando do MSBuild. Primeiro, deve incluir a flag –NonInteractive para garantir que o script é executado silenciosamente. De seguida, deve incluir a flag –ExecutionPolicy com um valor de argumento apropriado. Isto especifica a política de execução que o Windows PowerShell irá aplicar ao seu script e permite-lhe sobrepor a política de execução padrão, o que pode impedir a execução do seu script. Pode escolher entre estes valores argumentativos:

  • Um valor de Sem Restrições permitirá que o Windows PowerShell execute o seu script, independentemente de o script estar assinado ou não.
  • Um valor de RemoteSigned permitirá que o Windows PowerShell execute scripts não assinados que foram criados na máquina local. No entanto, os guiões criados noutros locais têm de ser assinados. (Na prática, é muito improvável que tenhas criado um script PowerShell para Windows localmente num servidor de compilação).
  • Um valor de AllSigned permitirá que o Windows PowerShell execute apenas scripts assinados.

A política de execução padrão é Restrita, que impede o PowerShell do Windows de executar quaisquer ficheiros de script.

Finalmente, precisa de escapar de quaisquer caracteres XML reservados que apareçam no seu comando PowerShell do Windows:

  • Substitua as aspas simples por '

  • Substitua aspas duplas por "

  • Substitua os ampersands por &

  • Quando fizer estas alterações, o seu comando irá assemelhar-se a isto:

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

No seu ficheiro de projeto MSBuild personalizado, 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, note-se que:

  • Quaisquer variáveis, como valores de parâmetros e a localização do executável PowerShell do Windows, são declaradas como propriedades do MSBuild.
  • Estão incluídas condições para permitir que os utilizadores sobrescritam estes valores a partir da linha de comandos.
  • A propriedade MSDeployComputerName é declarada noutro local do ficheiro do projeto.

Quando executas este alvo como parte do teu processo de compilação, o Windows PowerShell executa o teu comando e escreve uma entrada de registo no ficheiro que especificaste.

Execução de um Script PowerShell do Windows num Computador Remoto

O Windows PowerShell é capaz de executar scripts em computadores remotos através do Windows Remote Management (WinRM). Para isso, precisas de usar o cmdlet Invoke-Command . Isto permite-lhe executar o seu script em um ou mais computadores remotos sem ter de copiar o script para os computadores remotos. Quaisquer resultados são devolvidos ao computador local a partir do qual executou o script.

Observação

Antes de usar o cmdlet Invoke-Command para executar scripts PowerShell do Windows num computador remoto, precisa de configurar um ouvinte WinRM para aceitar mensagens remotas. Podes fazer isto executando o comando winrm quickconfig no computador remoto. Para obter mais informações, consulte Instalação e configuração para o gerenciamento remoto do Windows.

A partir de uma janela PowerShell do Windows, usarias esta sintaxe para executar o scriptLogDeploy.ps1 num computador remoto:

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

Observação

Existem várias outras formas de usar o Invoke-Command para executar um ficheiro de script, mas esta abordagem é a mais direta quando é necessário fornecer valores de parâmetros e gerir caminhos com espaços.

Quando executa isto a partir de um prompt de comandos, precisa de invocar o executável do Windows PowerShell e usar o parâmetro de comando – para fornecer as 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, precisa de fornecer alguns switches adicionais e escapar de quaisquer 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;

Finalmente, como antes, pode usar a tarefa Exec dentro de um alvo personalizado do MSBuild para executar o 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>

Quando executa este destino como parte do processo de compilação, o PowerShell do Windows executa o seu script no computador que especificou no argumento –computername .

Conclusion

Este tópico descreveu como executar um script PowerShell do Windows a partir de um ficheiro de projeto MSBuild. Pode usar esta abordagem para executar um script PowerShell do Windows, seja localmente ou num computador remoto, como parte de um processo automatizado ou de construção e implementação em etapas únicas.

Leitura adicional

Para orientações sobre como assinar scripts Windows PowerShell e gerir políticas de execução, consulte Running Windows PowerShell Scripts. Para orientações sobre como executar comandos PowerShell do Windows a partir de um computador remoto, consulte Execução de Comandos Remotos.

Para mais informações sobre a utilização de ficheiros de projeto personalizados do MSBuild para controlar o processo de implementação, consulte Compreender o Ficheiro do Projeto e Compreender o Processo de Compilação.