我刚刚在powershell中完成了我的第一个夜间构建脚本(第一个重要的任何脚本,真的).我似乎有一些工作得很好,如果还不是很健壮(我还没有处理过大量的错误检查),但我发现自己陷入了Invoke-Expression
cmdlet 周围的成语,我想知道我是否正确使用它.
具体来说,我使用一系列变量来构建命令行,我将用它来构建解决方案,然后运行解决方案的单元测试.例如,像:
$tmpDir = "C:\Users\\Development\Autobuild" $solutionPath=$tmpDir+"\MyProj\MyProj.sln" $devenv="C:\Program Files (x86)\Microsoft Visual Studio 10.0\common7\ide\devenv" $releaseProfile="Release" $releaseCommandLine="`"$devenv`" `"$solutionPath`" /build `"$releaseProfile`""
这个工作得很好,$releaseCommandLine
包含我想要在我完成时执行的命令行.然后我通过这一行执行它:
$output = Invoke-Expression "& $releaseCommandLine"
这是从powershell脚本执行手动构建的命令行的正确方法吗?我最初认为Invoke-Command
会做到这一点,但我一定是做错了,因为我根本无法让它工作半小时,而且我几乎立刻就能做到这一点.
我在同一个脚本中已经按照相同的模式进行了几次.这是最好的做法吗?
看起来很好.我唯一要改变的是使用更多的Powershell功能代替脆弱的假设.例如:
使用Join-Path而不是字符串连接
使用Env:\
提供程序查找%programfiles(x86)%
目录(或者更好的是,使用HKML:\
提供程序查找路径 - 它位于SOFTWARE\Microsoft\VisualStudio \\ InstallDir中)
当我必须编写包含文字双引号和变量扩展的字符串时,我通常会回到下面的语法.个人偏好,显然.
'"{0}" "{1}" /build "{2}"' -f $devenv, $solutionPath, $releaseProfile
在某些情况下,我倾向于使用Process.Start(),这样我就可以独立地捕获stdout和stderr流(甚至可以交互式地控制stdin,具体取决于应用程序).
PS - '&'不是绝对必要的.
我认为没有必要在这里使用Invoke-Expression.我用很多构建脚本完成了这个,它通常看起来像这样:
$vsroot = "$env:ProgramFiles(x86)\Microsoft Visual Studio 9.0" $devenv = "$vsroot\Common7\IDE\devenv.exe" $sln = Join-PathSource\MyProj\MyProj.sln & $devenv $sln /build Release
要么
& $devenv $sln /build "Release|Any CPU"
虽然最近我使用devenv.exe(行为错误的加载项等)遇到了一些麻烦,所以现在我使用msbuild.exe:
$msbuild = 'C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe' & $msbuild $sln /p:Configuration=Release
目前,MSBuild可以处理C#,VB和C++(调用vcbuild),但它无法处理其中包含设置和部署项目的解决方案.但是,我发现它比使用devenv.exe更可靠.
顺便说一句,您通常需要在构建脚本中调用其他工具(sn.exe,signtool.exe,mt.exe等),这些工具特定于您要构建的Visual Studio/.NET版本.因此,通常最好以与VS 2008命令提示符相同的方式配置环境变量.随着PowerShell的社区扩展安装,您可以启用PSCX文件头一行启用此为.NET 3.5/VS 2008点的设置:
$Pscx:Preferences["ImportVisualStudioVars"] = $true