有哪些好用的PowerShell MSBuild任务?

5

有人知道任何好的MSBuild任务,可以执行PowerShell脚本并传递不同的参数吗?

我能找到B#.NET博客:从MSBuild调用PowerShell脚本,但我希望有一些更加精细的内容。

如果我找不到任何东西,当然会按照该博客文章作为起点制作自己的内容。


我会以博客文章作为起点。我们正在与微软的一位顾问合作,这是他向我们推荐的帖子。我尝试在codeplex上使用PowerShell MSBuild任务,但它在我的Powershell脚本上出现错误,而此脚本在Bart De Smet编写的任务中可以正常运行。 - Scott Lawrence
4个回答

9

更好的选择是微软提供一个 PowerShell 的功能子集(不希望无限制的副作用干扰项目文件和 msbuild 的变更检测的大部分声明性质)。现有的属性函数似乎已经开始实现了这一点(至少它们具有 PowerShell 语法)。 - unbob

7

你可能也想看看Psake - 一个基于PowerShell的构建环境。


5

我发布的重复问题和答案,因为将来可能会被关闭而在此留存。关键区别在于,这个问题受到了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. 如果您想要传播基于.cmd结果的ERRORLEVEL,则会变得混乱
  4. 如果您想在ThingToDo中嵌入引号",则不能正常工作

那么,在MSBuild中运行PowerShell的防弹方式是什么? 有没有什么我可以PsGet来使一切都OK?

答案

好吧,你可以使用以下繁琐的方法,直到找到更好的方法为止:

<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版本中直接使用。
我马上离开。

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>

注意:

  • You can still use the standard Exec Task features! (see: https://msdn.microsoft.com/en-us/library/x8zx72cd.aspx)
  • if your powershell script needs to use < > or & characters, just place the contents in a CDATA wrapper:

    <script2><![CDATA[  $(PowerShell)
      # your powershell code goes here!
      write-host "<<Hi mom!>>"
    ]]></script2>
    
  • if you want return items to the msbuild script you can get them:

    <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

我喜欢它。我看到Walid Toumi在msbuild之外完成了类似的事情,并且将它们用于很好的效果。感谢您抽出时间来调试琐碎的问题。这个概念很简单,我猜想让它真正起作用可能不是那么容易(或者你可能很幸运或是天才:-)在我的环境中,我需要添加-executionpolicy remotesigned。 - unbob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接