Diagnosticar falhas de tarefas do MSBuild

MSB6006 é emitido quando uma classe derivada de ToolTask executa um processo de ferramenta que retorna um código de saída diferente de zero se a tarefa não registrou um erro mais específico.

Identificar a tarefa com falha

Quando você encontra um erro de tarefa, a primeira etapa é identificar a tarefa que está falhando.

O texto do erro especifica o nome da ferramenta (um nome amigável fornecido pela implementação da tarefa de ToolName ou o nome do executável) e o código de saída numérico. Por exemplo, em error MSB6006: "custom tool" exited with code 1., o nome da ferramenta é custom tool e o código de saída é 1.

Para localizar a tarefa de MSBuild com falha:

  • Nos builds de linha de comando: se o build tiver sido configurado para incluir um resumo (o padrão), o resumo terá esta aparência:

    Build FAILED.
    
    "S:\MSB6006_demo\MSB6006_demo.csproj" (default target) (1) ->
    (InvokeToolTask target) ->
      S:\MSB6006_demo\MSB6006_demo.csproj(19,5): error MSB6006: "custom tool" exited with code 1.
    

    Esse resultado indica que o erro ocorreu em uma tarefa definida na linha 19 do arquivo S:\MSB6006_demo\MSB6006_demo.csproj, em um destino chamado InvokeToolTask, no projeto S:\MSB6006_demo\MSB6006_demo.csproj.

  • Na interface do usuário do Visual Studio: as mesmas informações estão disponíveis na lista de erros do Visual Studio nas colunas Project, File e Line.

Encontrar mais informações sobre a falha

O erro MSB6006 é emitido quando a tarefa não registrou um erro específico. A falha ao registrar um erro geralmente ocorre porque a tarefa não está configurada para entender o formato de erro emitido pela ferramenta que ele chama.

Ferramentas bem comportadas geralmente emitem informações contextuais ou de erro para a saída padrão ou o fluxo de erros, e as tarefas capturam e registram essas informações por padrão. Examine as entradas de log antes da ocorrência do erro para obter informações adicionais. Executar novamente o build com um nível de log mais alto pode ser necessário para preservar essas informações. Espera-se que os erros ou o contexto adicional identificados no log revelem a causa raiz do problema. Caso contrário, talvez seja necessário restringir as possíveis causas examinando as propriedades e os itens que são entradas para a tarefa com falha.

Observação

O MSBuild reconhece um formato de saída de diagnóstico específico. Os detalhes desse formato estão documentados em Formato do MSBuild e do Visual Studio para mensagens de diagnóstico.

Depurar uma tarefa

Ao depurar tarefas do MSBuild, aqui estão algumas dicas gerais.

  • Restrinja o escopo do caso de reprodução o máximo possível (por exemplo, definindo /p:BuildProjectReferences=false e iniciando o MSBuild com um projeto específico ou um destino específico) para ter menos código para trabalhar.
  • Use a opção de linha de comando do MSBuild /m:1 para ter um único processo do MSBuild para depurar.
  • Defina a variável de ambiente MSBUILDDEBUGONSTART como 1 para obter um depurador anexado ao MSBuild na inicialização.
  • Defina um ponto de interrupção no método Execute da tarefa a ser executada.

Depurar uma tarefa personalizada

Se você estiver escrevendo código para uma tarefa personalizada, poderá facilitar a depuração adicionando uma chamada para invocar o depurador no método Execute da tarefa. Você pode cercar esse código com uma verificação de variável de ambiente, de modo que, quando um usuário define essa variável de ambiente, a tarefa é interrompida e dá ao usuário a oportunidade de depurar. Você pode usar System.Diagnostics.Debugger.Launch ou System.Diagnostics.Debugger.Break para iniciar ou interromper o depurador.

Adicione o máximo de logs possível em uma tarefa personalizada para tornar a tarefa mais fácil para os usuários depurá-la. Isso é importante quando você finalmente identifica o caso raiz de uma falha; adicione código de log suficiente para detectar e relatar esse modo de falha no futuro.

Considere configurar um ambiente de teste para uma tarefa usando xUnit. Consulte C# de teste de unidade no .NET Core usando o teste dotnet e xUnit. Você pode configurar o teste xUnit para usar a API do MSBuild para invocar o MSBuild programaticamente com um arquivo de projeto fictício que inclui as propriedades, itens e destinos necessários para executar a tarefa em questão. Em alguns casos, pode fazer sentido criar um mecanismo de build fictício. Você pode ver um exemplo em Teste de unidade uma tarefa personalizada do MSBuild com o Visual Studio.

Em projetos do SDK do .NET, você também pode modificar launchSettings.json para adicionar um perfil de depuração especial que executa MSBuild.exe com os argumentos de linha de comando e variáveis de ambiente mencionados anteriormente neste artigo.

"profiles": {
  "Debug Build": {
    "commandName": "Executable",
    "executablePath": "$(MSBuildBinPath)\\MSBuild.exe",
    "commandLineArgs": "/p:Configuration=$(Configuration) $(ProjectFileName) /m:1",
    "workingDirectory": "$(ProjectDir)"
  }
}

Se você quiser ser solicitado a anexar seu próprio depurador em runtime, defina a variável de ambiente MSBUILDDEBUGONSTART como 2. Isso pode ser útil quando você estiver usando um depurador diferente, como no macOS, quando o Visual Studio não estiver disponível.