visual-studio 任何好的 PowerShell MSBuild 任务?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/78069/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 16:30:16  来源:igfitidea点击:

Any good PowerShell MSBuild tasks?

visual-studiopowershellmsbuild

提问by Eric Schoonover

Anyone know of any good MSBuild tasks that will execute a PowerShell script and pass it different parameters?

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

I was able to find B# .NET Blog: Invoking PowerShell scripts from MSBuild, but I'm hoping for something that is a little more polished.

我能够找到B# .NET 博客:从 MSBuild 调用 PowerShell 脚本,但我希望有一些更完善的东西。

If I can't find anything I will of course just go ahead and polish my own using that blog post as a starter.

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

回答by Steven Murawski

You might also want to look at Psake- a PowerShell based build environment.

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

回答by Ruben Bartelink

Duplicate Question and Answer I Posted, here for posterity for when it has been vote to closed. The key difference is that this question was constrained to being OOTBand my self-answer stays within that constraint.

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

Question

Powershell doesn't seem to have an easy way to trigger it with an arbitrary command and then bubble up parse and execution errors in a way that correctly interoperates with callers that are not PowerShell - e.g., cmd.exe, TeamCityetc.

PowerShell的似乎并不有一个简单的方法与任意命令,然后泡了解析和执行错误触发它的方式,正确地与呼叫者互操作是不是PowerShell的-例如cmd.exeTeamCity的等等。

My question is simple. What's the best way for me with OOTB MSBuild v4 and PowerShell v3 (open to suggestions-wouldnt rule out a suitably production ready MSBuild Task, but it would need to be a bit stronger than suggesting "it's easy - taking the PowerShell Task Factory sample and tweak it and/or becoming it's maintainer/parent") to run a command (either a small script segment, or (most commonly) an invocation of a .ps1script.

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

I'm thinking it should be something normal like:

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

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


That sadly doesn't work:-

遗憾的是这不起作用:-

  1. if ThingToDofails to parse, it fails silently
  2. if ThingToDois a script invocation that doesn't exist, it fails
  3. if you want to propagate an ERRORLEVELbased .cmdresult, it gets hairy
  4. if you want to embed "quotes in the ThingToDo, it won't work
  1. 如果ThingToDo解析失败,则静默失败
  2. 如果ThingToDo是不存在的脚本调用,则失败
  3. 如果你想传播一个ERRORLEVEL基于.cmd结果的结果,它会变得毛茸茸的
  4. 如果您想在 中嵌入"引号ThingToDo,它将不起作用

So, what is the bullet proof way of running PowerShell from MSBuild supposed to be? Is there something I can PsGetto make everything OK?

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

Answer

回答

Weeeeelll, you could use something long winded like this until you find a better way:-

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

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

And then 'all' you need to do is:

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

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

The single redeeming feature of this (other than trapping all error types I could think of), is that it works OOTB with any PowerShell version and any MSBuild version.

这个唯一的补偿功能(除了捕获我能想到的所有错误类型)是它可以与任何 PowerShell 版本和任何 MSBuild 版本一起使用。

I'll get my coat.

我去拿我的外套。

回答by Garrett Serack

With a bit of fun, I managed to come up with a fairly clean way of making this work:

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

<?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>

Notes:

笔记:

  • 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)" /> 
    
  • 您仍然可以使用标准的 Exec Task 功能!(参见: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)" /> 
    

See! then you can use those items with another msbuild Task :D

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