有人知道任何好的MSBuild任务,可以执行PowerShell脚本并传递不同的参数吗?
我能找到B#.NET博客:从MSBuild调用PowerShell脚本,但我希望有一些更加精细的内容。
如果我找不到任何东西,当然会按照该博客文章作为起点制作自己的内容。
有人知道任何好的MSBuild任务,可以执行PowerShell脚本并传递不同的参数吗?
我能找到B#.NET博客:从MSBuild调用PowerShell脚本,但我希望有一些更加精细的内容。
如果我找不到任何东西,当然会按照该博客文章作为起点制作自己的内容。
可以使用http://powershellmsbuild.codeplex.com/来进行3.5版本的编程。如果有一个NuGet包,可以通过NuGet包还原来利用它会更好。
4.0版本有一个Windows Powershell Task Factory,已整合到MSBuild Extension Pack(顶级任务库之一-400+个任务并在Inside MSBuild中推荐)中,其中包含PowerShellTaskFactory
(从此示例发布的下载部分下载帮助文件以查看)。请注意,您可以在代码库中获取它。
我发布的重复问题和答案,因为将来可能会被关闭而在此留存。关键区别在于,这个问题受到了OOTB的限制,而我的自问自答保持了这种限制。
Powershell似乎没有一种简单的方法来使用任意命令触发它,然后以一种能够正确地与非PowerShell调用者(例如cmd.exe
、TeamCity等)进行交互的方式上报解析和执行错误。
我的问题很简单。在使用OOTB MSBuild v4和PowerShell v3(欢迎提供建议-不排除一个适合生产环境的MSBuild任务,但它需要更加强大,不能只是建议“很容易-采用PowerShell任务工厂示例并进行微调和/或成为其维护者/父级”)时,运行命令的最佳方法是什么(可以是小脚本段,也可以是(最常见的)调用.ps1
脚本)。
我认为应该像正常情况一样:
<Exec
IgnoreStandardErrorWarningFormat="true"
Command="PowerShell "$(ThingToDo)"" />
很遗憾,以下方法无法正常工作:
ThingToDo
无法解析,则会默默失败ThingToDo
是一个不存在的脚本调用,则会失败.cmd
结果的ERRORLEVEL
,则会变得混乱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)" />
经过一些有趣的尝试,我设法想出了一个相当简洁的方法使其可行:
<?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 -& 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>
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)" />