5

任何人都知道将执行 PowerShell 脚本并传递不同参数的任何好的 MSBuild 任务吗?

我能够找到B# .NET 博客:Invoking PowerShell scripts from MSBuild,但我希望得到一些更精致的东西。

如果我找不到任何东西,我当然会继续使用该博客文章作为入门来完善我自己的内容。

4

4 回答 4

9

对于 3.5,可以使用http://powershellmsbuild.codeplex.com/ 。如果有一个可以通过 NuGet package restore 使用的 NuGet 包,那就太好了

4.0 有一个Windows Powershell 任务工厂您可以在代码库中获得它已被纳入 MSBuild 扩展包(顶级任务库之一 - 400 多个任务并在 MSBuild 内部推荐)有(从下载部分PowerShellTaskFactory下载帮助文件这个示例发布有一个偷看)。

于 2010-08-12T05:45:30.323 回答
7

您可能还想查看Psake - 基于 PowerShell 的构建环境。

于 2008-09-17T05:24:58.203 回答
4

我发布了重复的问题和答案,在这里为后代投票关闭。关键区别在于,这个问题被限制为OOTB,而我的自我回答保持在该限制范围内。

问题

Powershell 似乎没有一种简单的方法来使用任意命令触发它,然后以与非 PowerShell 的调用者正确互操作的方式冒泡解析和执行错误 - 例如cmd.exeTeamCity等。

我的问题很简单。使用 OOTB MSBuild v4 和 PowerShell v3 对我来说最好的方法是什么(接受建议 - 不会排除适合生产的 MSBuild 任务,但它需要比建议“这很容易 - 使用 PowerShell 任务工厂示例和调整它和/或成为它的维护者/父”)来运行一个命令(一个小的脚本段,或者(最常见的)一个.ps1脚本的调用。

我认为它应该是正常的,例如:

<Exec 
  IgnoreStandardErrorWarningFormat="true"
  Command="PowerShell &quot;$(ThingToDo)&quot;" />

可悲的是,这不起作用:-

  1. 如果ThingToDo解析失败,则静默失败
  2. 如果ThingToDo是不存在的脚本调用,则失败
  3. 如果你想传播一个ERRORLEVEL基于.cmd结果的结果,它会变得毛茸茸的
  4. 如果你想在 中嵌入"引号ThingToDo,它将不起作用

那么,从 MSBuild 运行 PowerShell 的防弹方法应该是什么?有什么我可以PsGet让一切正常的吗?

回答

Weeeeelll,您可以使用像这样冗长的东西,直到找到更好的方法:-

<PropertyGroup>
  <__PsInvokeCommand>powershell "Invoke-Command</__PsInvokeCommand>
  <__BlockBegin>-ScriptBlock { $errorActionPreference='Stop';</__BlockBegin>
  <__BlockEnd>; exit $LASTEXITCODE }</__BlockEnd>
  <_PsCmdStart>$(__PsInvokeCommand) $(__BlockBegin)</_PsCmdStart>
  <_PsCmdEnd>$(__BlockEnd)"</_PsCmdEnd>
</PropertyGroup>

然后你需要做的“所有”就是:

<Exec 
  IgnoreStandardErrorWarningFormat="true"
  Command="$(_PsCmdStart)$(ThingToDo)$(_PsCmdEnd)" />

这个唯一的赎回功能(除了捕获我能想到的所有错误类型)是它适用于任何 PowerShell 版本和任何 MSBuild 版本的 OOTB。

我去拿我的外套。

于 2012-10-10T10:48:17.090 回答
3

带着一点乐趣,我设法想出了一个相当干净的方法来完成这项工作:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- #1 Place this line at the top of any msbuild script (ie, csproj, etc) -->
  <PropertyGroup><PowerShell># 2>nul || type %~df0|find /v "setlocal"|find /v "errorlevel"|powershell.exe -noninteractive -&amp; exit %errorlevel% || #</PowerShell></PropertyGroup>

  <!-- #2 in any target you want to run a script -->
  <Target Name="default" >

    <PropertyGroup> <!-- #3 prefix your powershell script with the $(PowerShell) variable, then code as normal! -->
      <myscript>$(PowerShell)
      #
      # powershell script can do whatever you need.
      #
      dir ".\*.cs" -recurse |% {
        write-host Examining file named:  $_.FullName
        # do other stuff here...
      } 
      $answer = 2+5
      write-host Answer is $answer !
      </myscript>
    </PropertyGroup>

    <!-- #4 and execute the script like this -->
    <Exec Command="$(myscript)" EchoOff="true" /> 
  </Target>
</Project>

笔记:

  • 您仍然可以使用标准的执行任务功能!(见:https ://msdn.microsoft.com/en-us/library/x8zx72cd.aspx )
  • 如果您的 powershell 脚本需要使用 < > 或 & 字符,只需将内容放在 CDATA 包装器中:

    <script2><![CDATA[  $(PowerShell)
      # your powershell code goes here!
      write-host "<<Hi mom!>>"
    ]]></script2>
    
  • 如果您想将项目返回到 msbuild 脚本,您可以获取它们:

    <script3>$(PowerShell)
      # your powershell code goes here!
      (dir "*.cs" -recurse).FullName
    </script3>
    
    <Exec Command="$(script3)" EchoOff="true" ConsoleToMSBuild="true"> 
        <Output TaskParameter="ConsoleOutput" PropertyName="items" />
    </Exec>
    <Touch Files="$(items)" /> 
    

看!然后您可以将这些项目与另一个 msbuild 任务一起使用:D

于 2016-12-09T01:36:37.073 回答