Any good PowerShell MSBuild tasks?

后端 未结 4 857
醉话见心
醉话见心 2020-12-03 09:05

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

I was able to find B# .NET Blog: Invoking PowerShell sc

相关标签:
4条回答
  • 2020-12-03 09:37

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

    0 讨论(0)
  • 2020-12-03 09:38

    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)" /> 
      

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

    0 讨论(0)
  • 2020-12-03 09:49

    One could use http://powershellmsbuild.codeplex.com/ for 3.5. It'd be nice if there was a NuGet package for it that one could leverage via NuGet package restore.

    4.0 has a Windows Powershell Task Factory which you can get in the code gallery has been rolled into MSBuild Extension Pack (one of the top task libraries - 400+ Tasks & recommended in Inside MSBuild) has PowerShellTaskFactory (download the help file from the download section of this example release to have a peek).

    0 讨论(0)
  • 2020-12-03 10:00

    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 OOTB and my self-answer stays within that constraint.

    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, TeamCity etc.

    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 .ps1 script.

    I'm thinking it should be something normal like:

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

    That sadly doesn't work:-

    1. if ThingToDo fails to parse, it fails silently
    2. if ThingToDo is a script invocation that doesn't exist, it fails
    3. if you want to propagate an ERRORLEVEL based .cmd result, it gets hairy
    4. if you want to embed " quotes in the ThingToDo, it won't work

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

    Answer

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

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

    I'll get my coat.

    0 讨论(0)
提交回复
热议问题