65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 PowerShell 的简单生成脚本

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2012 年 4 月 13 日

CPOL

4分钟阅读

viewsIcon

73561

使用 MSBuild 构建多个项目和解决方案的 PowerShell 生成脚本,并提供在生成过程中修复生成错误并继续的选项,而无需重新启动整个生成。

引言

本文介绍如何使用 PowerShell 和 MSBuild 为多个项目和解决方案编写一个简单的生成脚本,并提供在生成过程中修复生成错误并继续生成而无需重新启动整个生成的选项。

背景

我不得不在非常短的时间内(大约一小时)组装一个生成脚本。我可以编写这个 PowerShell 脚本来执行生成,它很好地满足了我的目的。

关于脚本

生成步骤概述

下图概述了我考虑过的生成步骤。如您所见,这是一个标准流程。您可能会注意到此图表中缺少一些生成步骤,其中一些被省略以使脚本尽可能简单。其中一些是

  • 在生成前自动更新源 
  • 控制程序集版本 
  • 自动增量 版本号 
  • 生成输出路径不可配置。将从项目属性中获取。 
  • 标记源文件。 

提取最新源文件

 

步骤 1:关闭所有 DevEnv

修复并继续功能需要 devevn 进程未运行,因此在脚本开头会要求关闭所有 devenv。但是,这不会阻止脚本运行。

步骤 2:初始化生成配置

以下是生成中使用的生成初始化和配置。

  • 生成的基本目录
  • 处理依赖关系(SolutionConfig.txt 定义了解决方案的生成顺序)
  • MSBuild.exe 的位置 
  • MS Build 日志配置
  • devenv 的位置
  • 如果您在生成的前后操作中使用任何 Windows SDK 工具,请将 Windows SDK 的位置作为路径的一部分。

步骤 3:对于 SolutionConfig.txt 文件中的每个解决方案,执行生成

  • 检查文件是否存在
  • 文件的扩展名为 .sln。如果您想包含更多文件,如 .csproj、vcxproj 等,可以在脚本中进行必要的更改。这是为了避免 SolutionConfig.txt 文件中的错误。

步骤 4:MSBuild

MSBuild 是一个用于构建应用程序的平台。使用 MSBuild 可以在未安装 Visual Studio 的系统上构建项目。要阅读更多关于 MSBuild 的信息,请访问 MSDN MSBuild

步骤 5:解决生成中断

为了能够解决生成中断的问题,您需要在安装了 Visual Studio 的计算机上运行此脚本。脚本将启动 Visual Studio 并打开失败的解决方案。在解决所有错误后,关闭 Visual Studio 以继续构建顺序中的下一个解决方案。

步骤 6:完成生成

如果所有项目都能成功编译而没有错误,生成将成功完成。如果您选择不修复错误,生成将以错误终止。

整合所有内容

Clear-Host

Write-Host "Please make sure you do not have any instances of Visual studio running before running the script..." -ForegroundColor Red -BackgroundColor White
Write-Host "You have 10 seconds" -ForegroundColor Red -BackgroundColor White

Start-Sleep -s 10

$baseDirectory = "D:\Project1\Source"
$solutionFilesPath = "$baseDirectory\SolutionConfig.txt"
$projectFiles = Get-Content $solutionFilesPath 

$msbuild = "C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe"
$MSBuildLogger="/flp1:Append;LogFile=Build.log;Verbosity=Normal; /flp2:LogFile=BuildErrors.log;Verbosity=Normal;errorsonly"

$devenv = "C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe"

$action = "Y"

# $env:Path = $env:Path + ";C:\Program Files\Microsoft SDKs\Windows\v7.0A"

foreach($projectFile in $projectFiles)
{
    if ($projectFile.EndsWith(".sln")) 
    {
        $projectFileAbsPath = "$baseDirectory\$projectFile"
        
        $filename = [System.IO.Path]::GetFileName($projectFile); 
        $action = "Y"  
        while($action -eq "Y") 
        {
            if(Test-Path $projectFileAbsPath) 
            {
                Write-Host "Building $projectFileAbsPath"
                & $msbuild $projectFileAbsPath /t:rebuild /p:PlatformTarget=x86 /fl "/flp1:logfile=$baseDirectory\msbuild.log;Verbosity=Normal;Append;" "/flp2:logfile=$baseDirectory\errors.txt;errorsonly;Append;"
                #& $devenv $projectFileAbsPath /Rebuild
                
                if($LASTEXITCODE -eq 0)
                {
                    Write-Host "Build SUCCESS" -ForegroundColor Green
                    Clear-Host
                    break
                }
                else
                {
                    Write-Host "Build FAILED" -ForegroundColor Red
                    
                    $action = Read-Host "Enter Y to Fix then continue, N to Terminate, I to Ignore and continue the build"
                    
                    if($action -eq "Y")
                    {
                        & $devenv $projectFileAbsPath
                        wait-process -name devenv    
                    }
                    else 
                    {
                        if($action -eq "I")
                        {
                            Write-Host "Ignoring build failure..."
                            break
                        }
                        else
                        {
                            Write-Host "Terminating Build... Please restart the build once the issue is fixed." -ForegroundColor Red
                            break
                        }
                    }
                }
            }
            else
            {
                Write-Host "File does not exist : $projectFileAbsPath"
                Start-Sleep -s 5
                break
            }
        }
        
        if($action -eq "N")
        {
            break;
        }
        
    }
}
 

请记得使用语言下拉菜单设置代码片段的语言。

使用“var”按钮将变量或类名包装在 <code> 标签中,例如 this

关注点

将 MS Build 输出记录到文件

MSBuild 提供了非常全面的机制来记录生成输出和错误。以下脚本创建 2 个日志文件,一个用于成功生成,另一个用于错误。

$msbuild = "C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" 

$MSBuildLogger="/flp1:Append;LogFile=Build.log;Verbosity=Normal; /flp2:LogFile=BuildErrors.log;

& $msbuild $projectFileAbsPath /t:rebuild /p:PlatformTarget=x86 /fl "/flp1:logfile=$baseDirectory\msbuild.log;Verbosity=Normal;Append;" "/flp2:logfile=$baseDirectory\errors.txt;errorsonly;Append;" 

等待进程退出

要在 PowerShell 中等待进程退出,我通过进程名称等待,这也可以相对于进程 ID 来完成。

Wait-Process -name devenv

或者,可以使用以下命令启动一个进程并等待其完成。

Start-Process $devenv -NoNewWindow -Wait

或者

$proc = Start-Process <path to exe> -NoWindow
$proc.WaitForExit()

验证路径是否存在 

要检查目录或文件是否存在,我们可以使用 Test-Path 命令。当与 Windows PowerShell 注册表提供程序一起使用时,Test-Path 也可以用于验证注册表项是否存在。 

SVN 更新 和标记源 

如果您将 SVN 用作源代码控制,您可以在执行上面流程图中的任何步骤之前包含以下命令来更新您的源代码。 需要在 $env.Path 中添加 svn 的路径。 如果您需要签出多个文件夹,您可以在一个命令中指定多个文件夹的 URL,用空格分隔。 

& svn co $repositoryUrl1 $repositoryUrl2 $destinationDir   

在成功生成后标记 SVN 中的源文件,您可以创建标签。 这通常与成功的生成相关联, 成功生成 用于生成程序集的增量版本号。 

Win SDK 工具 

当项目使用 .Net 4.0 作为目标框架进行生成时,Windows SDK 与 Visual Studio 2010 默认引用的 win sdk 文件夹不兼容。需要为 .Net 4.0 dll 引用的额外路径是

C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools

默认情况下,Visual Studio 2010 引用的路径是

C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin

参考文献

MSBuild 参考

Windows PowerShell 参考 

处理依赖关系 

生成过程  

© . All rights reserved.