WPF 通过PowerShell脚本,控制项目的版本、生成、发布,附带InstallerSetup的控制

概述

一般情况下,Visual Studio提供了的发布功能能够满足基础的需求。
但在实际开发过程中,对于复杂的项目,多个项目组成的大型项目,或者需要CICD的项目,往往都是需要脚本来控制发布的各个步骤。

例如:

  • 多个子项目的版本统一修改
  • 按序生成发布
  • 辅助文档生成编译
  • 相关文件的拷贝复制
  • 不同格式、平台的安装包。

虽然VS也能够通过生成前后的事件来控制,但还是没有单独的脚本方便管理。

下面,我将以自身项目的某个脚本来详细阐述。

脚本样例 Build.ps1


param (
    [switch]$help, 
    [Parameter(Mandatory = $false)][bool]$publish_Free_Installer = $false,
    [Parameter(Mandatory = $false)][bool]$publish_MSI_Installer = $false,
    [Parameter(Mandatory = $false)][bool]$updateVersion = $false,
    [Parameter(Mandatory = $false)][int]$major_ver,
    [Parameter(Mandatory = $false)][int]$minor_ver,
    [Parameter(Mandatory = $false)][int]$patch_ver

    )
    
[string]$MsBuild = " "
[string]$Proj = "$PSScriptRoot\..\ToolsKit\DeviceToolsKit.csproj"
[string]$TempPackage_Path = "$PSScriptRoot\..\TempPackage"
[string]$Delivery_Path = "$PSScriptRoot\..\Delivery"

[string]$Installer_proj = "$PSScriptRoot\..\ProjectInstaller\ProjectInstaller.vdproj"


function ChangeVersionNumberInFile($file, $major, $minor, $patch)
{
    Write-Host "Changing version in $file to $major.$minor.$patch"
    $sr = new-object System.IO.StreamReader( $file, [System.Text.Encoding]::GetEncoding("utf-8") )
    $content = $sr.ReadToEnd()
    $sr.Close()  

    switch([System.IO.Path]::GetExtension($file))
    {
        ".json"         {$content = [Regex]::Replace($content, 'Hydra (\d+)\.(\d+).(\d+)',"Hydra $major.$minor.$patch"); Break}
        ".csproj"       {$content = [Regex]::Replace($content, "<Version>(\d+).(\d+).(\d+)</Version>", "<Version>$major.$minor.$patch</Version>"); Break}
        ".cs"           {$content = [Regex]::Replace($content, '"(\d+)\.(\d+).(\d+)','"' + "$major.$minor.$patch"); Break}
        ".appxmanifest" {$content = [Regex]::Replace($content, '    Version="(\d+)\.(\d+).(\d+)','    Version="' + "$major.$minor.$patch"); Break}
    }

    $sw = new-object System.IO.StreamWriter( $file, $false, [System.Text.Encoding]::GetEncoding("utf-8") )
    $sw.Write( $content )
    $sw.Close() 
}

function uuid { [guid]::NewGuid().ToString().ToUpper() }

function SetInstallerVersion ($file, $version)
{
   Write-Host  "Changing version in $file to $version"

    $sr = new-object System.IO.StreamReader( $file, [System.Text.Encoding]::GetEncoding("utf-8") )
    $content = $sr.ReadToEnd()
    $sr.Close()  


    $content = [Regex]::Replace($content, '"ProductVersion" = "8:"', '"ProductVersion" = "8:'+$version+'"');
    $content = [Regex]::Replace($content, '"ProductVersion" = "8:(\d+)\.(\d+)"', '"ProductVersion" = "8:'+$version+'"');
    $content = [Regex]::Replace($content, '"ProductVersion" = "8:(\d+)\.(\d+)\.(\d+)"', '"ProductVersion" = "8:'+$version+'"');

    [string] $ProductCode = uuid
    [string] $PackageCode = uuid

    $content = [Regex]::Replace($content, '"ProductCode" = "8:{(\w{8})-(\w{4})-(\w{4})-(\w{4})-(\w{12})}"', '"ProductCode" = "8:{' + $ProductCode + '}"');
    $content = [Regex]::Replace($content, '"PackageCode" = "8:{(\w{8})-(\w{4})-(\w{4})-(\w{4})-(\w{12})}"', '"PackageCode" = "8:{' + $PackageCode + '}"');

    $sw = new-object System.IO.StreamWriter( $file, $false, [System.Text.Encoding]::GetEncoding("utf-8") )
    $sw.Write( $content )
    $sw.Close()
}

function UpdateVersion()
{ 
    
    "--------------------------------------------"
    "-- Update project version --"
    "--------------------------------------------"
    ChangeVersionNumberInFile $Proj $major_ver $minor_ver $patch_ver
      "--------------------------------------------"
    "-- Update installer version --"
    "--------------------------------------------"
    
    $targetVersion ="$major_ver.$minor_ver.$patch_ver"
    SetInstallerVersion $Installer_proj $targetVersion
  
}

function FindMSBuildPath()
{

    if (Test-Path "C:\Program Files\Microsoft Visual Studio\2022\Community\Msbuild\Current\Bin\MSBuild.exe") {
        $msBuild = "C:\Program Files\Microsoft Visual Studio\2022\Community\Msbuild\Current\Bin\MSBuild.exe"
   
    }
    elseif (Test-Path "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe") {
        $msBuild = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe"
    }
    elseif (Test-Path "C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe") {
        $msBuild = "C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe"
    }
    else{
        throw "Unable to find MSBuild.exe path"
    }

    return $msBuild
}

function RestoreNuget($proj)
{
    "-----NuGet Restore: $proj-----"
    & "$PSScriptRoot\..\Tools\nuget.exe" restore "$proj"
}

function PublishFreeInstallPackage()
{
    "---------------------------------------------"
    "-- Publish Free Install Package --"
    "---------------------------------------------"
    RestoreNuget($Proj)
    dotnet clean $Proj -c Release
    dotnet build $Proj -c Release --force
   
    if ($LASTEXITCODE -ne 0) {
        exit $lastexitcode
    }  
     "-----Publish Project-----"  
    dotnet publish $Proj -c Release -p:PublishProfile=FolderProfile      
}

function PublishMSIInstallPackage()
{    
    "---------------------------------------------"
    "-- Publish MSI Install Package --"
    "---------------------------------------------"
    ""
    "-------------------------"
    "-- Build current project --"
    "-------------------------"

    RestoreNuget($Proj)
    dotnet clean $Proj -c Release
    dotnet build $Proj -c Release --force

    if($MsBuild -eq " ")
    {
        $MSBuild = FindMSBuildPath
    }
    & $MsBuild $Proj /p:Configuration=Release /t:Clean,Build

    if ($LASTEXITCODE -ne 0) {
        exit $lastexitcode
    }    
    
    "-----------------------------"
    "-- Build Installer project --"
    "-----------------------------"
    #[string]$Installer_proj = "$PSScriptRoot\..\ProjectInstaller\ProjectInstaller.vdproj"
    #if($Sign -eq $True)
    #{
        #Add pre build event to sign .exe after rebuilding project but before building installer
        #ReplaceLine "$PSScriptRoot\..\src\SPDev\SPDevInstaller\SPDevInstaller.vdproj" '"PreBuildEvent"' '"PreBuildEvent" = "8:call \"$(ProjectDir)/../../../build/certificates/certificate.bat\" \"$(ProjectDir)..\\..\\..\\out\\application_studio_$(Configuration)\\$(Configuration)\\application_studio.exe\"\r\n"'
   # }

    $devenvDir = FindDevenvdPath
    
    Remove-Item -Path "$PSScriptRoot\..\out\Installer\Release\*" -Recurse -Force -ErrorAction SilentlyContinue
    
    & $devenvDir "$PSScriptRoot\..\DeviceToolsKit.sln" /project $Installer_proj /Build Release
    if ($LASTEXITCODE -ne 0) {

        # Remove pre build event from installer proj file if failed to sign
        #ReplaceLine "$PSScriptRoot\..\src\SPDev\SPDevInstaller\SPDevInstaller.vdproj" '"PreBuildEvent"' '"PreBuildEvent" = "8:"'
        exit $lastexitcode
    }

    $fullName = (Get-ItemProperty "$PSScriptRoot\..\ProjectInstaller\Release\*.msi").Name
    $AppName = (Get-ItemProperty "$PSScriptRoot\..\ProjectInstaller\Release\*.msi").Name.Split('.')[0]

    $major_ver, $minor_ver, $patch_ver = GetVersionOfFile $Proj
    $targetVersion ="$major_ver.$minor_ver.$patch_ver"

    $installerName = $AppName + "_v" + $targetVersion + ".msi"
    "Installer Name: $installerName"

    Rename-Item -Path "$PSScriptRoot\..\ProjectInstaller\Release\$fullName" -NewName $installerName

   # if($Sign -eq $True)
   # {
        # Sign Installer
        #& "$PSScriptRoot\certificates\certificate.bat" "$PSScriptRoot\..\out\Installer\Release\*.msi"
        # Remove pre build event from installer proj file after signing
        #ReplaceLine "$PSScriptRoot\..\src\SPDev\SPDevInstaller\SPDevInstaller.vdproj" '"PreBuildEvent"' '"PreBuildEvent" = "8:"'
   # }
}
function FindDevenvdPath()
{
    if (Test-Path "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\devenv.com") {
        $devenvDir = "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\devenv.com"
    }
    elseif (Test-Path "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.com") {
        $devenvDir = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.com"
    }
    elseif (Test-Path "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\devenv.com") {
        $devenvDir = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\devenv.com"
    }
    elseif (Test-Path "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.com") {
        $devenvDir = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.com"
    }
    else {
        Write-Error "devenv.com does not exista, make sure Microsoft Visual Studio Installer Projects is installed"
        exit $lastexitcode
    }

    return $devenvDir
}

function CopyMSIPackagesToDelivery
{
    "----- Copy MSI Packages To Delivery -----"  

    $verStr = GetVersionStr $Proj

    $Delivery_FullPath=$Delivery_Path+"\DeviceToolsKit_v"+$verStr+"_InstallPackage"

      "----- Target path -----"  
    Write-Output $Delivery_FullPath

    $check4 = Test-Path $Delivery_Path
     if ($check4.ToString().Equals("False")) {
        mkdir $Delivery_Path
    }

      $check5 = Test-Path $Delivery_FullPath
     if ($check5.ToString().Equals("False")) {
        mkdir $Delivery_FullPath
    }
    #"$PSScriptRoot\..\ProjectInstaller\Release\$fullName"
    xcopy $PSScriptRoot\..\ProjectInstaller\Release\*.* $Delivery_FullPath /E/H/C/I/y 
}

function CopyFreeInstallPackagesToDelivery
{
    "----- Copy Install Free Packages To Delivery -----"  

    $verStr = GetVersionStr $Proj

    $Delivery_FullPath=$Delivery_Path+"\DeviceToolsKit_v"+$verStr+"_InstallFree"

      "----- Target path -----"  
    Write-Output $Delivery_FullPath

    $check4 = Test-Path $Delivery_Path
     if ($check4.ToString().Equals("False")) {
        mkdir $Delivery_Path
    }

      $check5 = Test-Path $Delivery_FullPath
     if ($check5.ToString().Equals("False")) {
        mkdir $Delivery_FullPath
    }

    xcopy $TempPackage_Path\*.* $Delivery_FullPath /E/H/C/I/y 
}
function GetVersionStr($file)
{
    $content = Get-Content $file
    switch([System.IO.Path]::GetExtension($file))
    {
        ".csproj"       {$versionStr = ($content | Select-String "<Version>(\d+).(\d+).(\d+)</Version>") -replace "[^0-9 | .]",'' ; Break}
        default {Write-Error "Unable to get version from $file"; exit}
    }
    return $versionStr
}

function GetVersionOfFile($file)
{
    $content = Get-Content $file
    switch([System.IO.Path]::GetExtension($file))
    {
        ".csproj"       {$version = ($content | Select-String "<Version>(\d+).(\d+).(\d+)</Version>") -replace "[^0-9 | .]",'' ; Break}
        default {Write-Error "Unable to get version from $file"; exit}
    }
    Write-Host "Version $version in file: $file" 
    return $version.Split(".")
}

##########Start of build script##########

if($help)
{
    Write-Host "
    Arguments: null
    "   
    
    exit    
}
if($updateVersion)
{
        if(!$PSBoundParameters.ContainsKey('major_ver') -and !$PSBoundParameters.ContainsKey('minor_ver') -and !$PSBoundParameters.ContainsKey('patch_ver'))
        {        
            $major_ver, $minor_ver, $patch_ver = GetVersionOfFile $Proj
            $patch_ver = $patch_ver + 1
        }
        elseif(!$PSBoundParameters.ContainsKey('major_ver') -xor !$PSBoundParameters.ContainsKey('minor_ver') -xor !$PSBoundParameters.ContainsKey('patch_ver'))
        {
            Write-Error "All Version Parameters must be set: Major, Minor, Patch"
            exit
        }
        UpdateVersion    
}

if($publish_Free_Installer)
{
    $MSBuild = FindMSBuildPath
    PublishFreeInstallPackage
  
    CopyFreeInstallPackagesToDelivery
}

if($publish_MSI_Installer)
{
 $MSBuild = FindMSBuildPath

 PublishMSIInstallPackage

 CopyMSIPackagesToDelivery
}



解释说明

1.参数部分

param (
    [switch]$help, 
    [Parameter(Mandatory = $false)][bool]$publish_Free_Installer = $false,
    [Parameter(Mandatory = $false)][bool]$publish_MSI_Installer = $false,
    [Parameter(Mandatory = $false)][bool]$updateVersion = $false,
    [Parameter(Mandatory = $false)][int]$major_ver,
    [Parameter(Mandatory = $false)][int]$minor_ver,
    [Parameter(Mandatory = $false)][int]$patch_ver

    )

这个power shell 可以通过脚本来启动对应的功能。
不同的参数,可以达到不同的目的。
这里主要实现了三个功能:

  • 版本修改(针对主项目,以及一个InstallerSetup项目)
  • 发布免安装版本
  • 发布MSI的安装包

2.脚本程序的入口

##########Start of build script##########

if($help)
{
    Write-Host "
    Arguments: null
    "   
    
    exit    
}
if($updateVersion)
{
        if(!$PSBoundParameters.ContainsKey('major_ver') -and !$PSBoundParameters.ContainsKey('minor_ver') -and !$PSBoundParameters.ContainsKey('patch_ver'))
        {        
            $major_ver, $minor_ver, $patch_ver = GetVersionOfFile $Proj
            $patch_ver = $patch_ver + 1
        }
        elseif(!$PSBoundParameters.ContainsKey('major_ver') -xor !$PSBoundParameters.ContainsKey('minor_ver') -xor !$PSBoundParameters.ContainsKey('patch_ver'))
        {
            Write-Error "All Version Parameters must be set: Major, Minor, Patch"
            exit
        }
        UpdateVersion    
}

if($publish_Free_Installer)
{
    $MSBuild = FindMSBuildPath
    PublishFreeInstallPackage
  
    CopyFreeInstallPackagesToDelivery
}

if($publish_MSI_Installer)
{
 $MSBuild = FindMSBuildPath

 PublishMSIInstallPackage

 CopyMSIPackagesToDelivery
}

通过不同的输入参数,执行对应的方法。
主要包括了:

  • 自动版本号增加 1
  • 修改成指定的版本号
  • 发布免安装版本,并将结果文件复制到Delivery文件夹
  • 发布MSI安装包,并将结果文件复制到Delivery文件夹

3. 自定义的路径变量

[string]$MsBuild = " "
[string]$Proj = "$PSScriptRoot\..\ToolsKit\DeviceToolsKit.csproj"
[string]$TempPackage_Path = "$PSScriptRoot\..\TempPackage"
[string]$Delivery_Path = "$PSScriptRoot\..\Delivery"

[string]$Installer_proj = "$PSScriptRoot\..\ProjectInstaller\ProjectInstaller.vdproj"

通过上述代码,定义了项目的主要csproj文件的路径
以及最终发布文件的存放位置。
注意,这都是相对路径,需要根据自己项目需求进行修改。

4.修改项目的版本号

(a)修改主项目的版本号

  • $file 是项目的csproj路径。
  • 如果csproj中没有version字段,将会执行失败,需要先行添加版本信息,然后这个脚本就能正常执行。
function ChangeVersionNumberInFile($file, $major, $minor, $patch)
{
    Write-Host "Changing version in $file to $major.$minor.$patch"
    $sr = new-object System.IO.StreamReader( $file, [System.Text.Encoding]::GetEncoding("utf-8") )
    $content = $sr.ReadToEnd()
    $sr.Close()  

    switch([System.IO.Path]::GetExtension($file))
    {
        ".json"         {$content = [Regex]::Replace($content, 'Hydra (\d+)\.(\d+).(\d+)',"Hydra $major.$minor.$patch"); Break}
        ".csproj"       {$content = [Regex]::Replace($content, "<Version>(\d+).(\d+).(\d+)</Version>", "<Version>$major.$minor.$patch</Version>"); Break}
        ".cs"           {$content = [Regex]::Replace($content, '"(\d+)\.(\d+).(\d+)','"' + "$major.$minor.$patch"); Break}
        ".appxmanifest" {$content = [Regex]::Replace($content, '    Version="(\d+)\.(\d+).(\d+)','    Version="' + "$major.$minor.$patch"); Break}
    }

    $sw = new-object System.IO.StreamWriter( $file, $false, [System.Text.Encoding]::GetEncoding("utf-8") )
    $sw.Write( $content )
    $sw.Close() 
}

(b)修改InstallerSetup的版本号

这个安装程序项目的版本号比较特殊。
修改版本号的同时,需要重新生成产品编号。

function uuid { [guid]::NewGuid().ToString().ToUpper() }

function SetInstallerVersion ($file, $version)
{
   Write-Host  "Changing version in $file to $version"

    $sr = new-object System.IO.StreamReader( $file, [System.Text.Encoding]::GetEncoding("utf-8") )
    $content = $sr.ReadToEnd()
    $sr.Close()  


    $content = [Regex]::Replace($content, '"ProductVersion" = "8:"', '"ProductVersion" = "8:'+$version+'"');
    $content = [Regex]::Replace($content, '"ProductVersion" = "8:(\d+)\.(\d+)"', '"ProductVersion" = "8:'+$version+'"');
    $content = [Regex]::Replace($content, '"ProductVersion" = "8:(\d+)\.(\d+)\.(\d+)"', '"ProductVersion" = "8:'+$version+'"');

    [string] $ProductCode = uuid
    [string] $PackageCode = uuid

    $content = [Regex]::Replace($content, '"ProductCode" = "8:{(\w{8})-(\w{4})-(\w{4})-(\w{4})-(\w{12})}"', '"ProductCode" = "8:{' + $ProductCode + '}"');
    $content = [Regex]::Replace($content, '"PackageCode" = "8:{(\w{8})-(\w{4})-(\w{4})-(\w{4})-(\w{12})}"', '"PackageCode" = "8:{' + $PackageCode + '}"');

    $sw = new-object System.IO.StreamWriter( $file, $false, [System.Text.Encoding]::GetEncoding("utf-8") )
    $sw.Write( $content )
    $sw.Close()
}

5.查找本地的MSBuild、devenv工具

这两个工具将被不同的发布方式调用。

function FindMSBuildPath()
{

    if (Test-Path "C:\Program Files\Microsoft Visual Studio\2022\Community\Msbuild\Current\Bin\MSBuild.exe") {
        $msBuild = "C:\Program Files\Microsoft Visual Studio\2022\Community\Msbuild\Current\Bin\MSBuild.exe"
   
    }
    elseif (Test-Path "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe") {
        $msBuild = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe"
    }
    elseif (Test-Path "C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe") {
        $msBuild = "C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe"
    }
    else{
        throw "Unable to find MSBuild.exe path"
    }

    return $msBuild
}
function FindDevenvdPath()
{
    if (Test-Path "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\devenv.com") {
        $devenvDir = "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\devenv.com"
    }
    elseif (Test-Path "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.com") {
        $devenvDir = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.com"
    }
    elseif (Test-Path "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\devenv.com") {
        $devenvDir = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\devenv.com"
    }
    elseif (Test-Path "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.com") {
        $devenvDir = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.com"
    }
    else {
        Write-Error "devenv.com does not exista, make sure Microsoft Visual Studio Installer Projects is installed"
        exit $lastexitcode
    }

    return $devenvDir
}

6.重置并还原Nuget包

需要在项目中,在…\Tools\路径下,添加一个工具nuget.exe,这样才能正常调用该方法。

function RestoreNuget($proj)
{
    "-----NuGet Restore: $proj-----"
    & "$PSScriptRoot\..\Tools\nuget.exe" restore "$proj"
}

7.发布免安装版本

function PublishFreeInstallPackage()
{
    "---------------------------------------------"
    "-- Publish Free Install Package --"
    "---------------------------------------------"
    RestoreNuget($Proj)
    dotnet clean $Proj -c Release
    dotnet build $Proj -c Release --force
   
    if ($LASTEXITCODE -ne 0) {
        exit $lastexitcode
    }  
     "-----Publish Project-----"  
    dotnet publish $Proj -c Release -p:PublishProfile=FolderProfile      
}

通过

-p:PublishProfile=FolderProfile  

调用了实现在项目中制定的publish配置文件。

8.发布MSI的安装包

function PublishMSIInstallPackage()
{    
    "---------------------------------------------"
    "-- Publish MSI Install Package --"
    "---------------------------------------------"
    ""
    "-------------------------"
    "-- Build current project --"
    "-------------------------"

    RestoreNuget($Proj)
    dotnet clean $Proj -c Release
    dotnet build $Proj -c Release --force

    if($MsBuild -eq " ")
    {
        $MSBuild = FindMSBuildPath
    }
    & $MsBuild $Proj /p:Configuration=Release /t:Clean,Build

    if ($LASTEXITCODE -ne 0) {
        exit $lastexitcode
    }    
    
    "-----------------------------"
    "-- Build Installer project --"
    "-----------------------------"
    #[string]$Installer_proj = "$PSScriptRoot\..\ProjectInstaller\ProjectInstaller.vdproj"
    #if($Sign -eq $True)
    #{
        #Add pre build event to sign .exe after rebuilding project but before building installer
        #ReplaceLine "$PSScriptRoot\..\src\SPDev\SPDevInstaller\SPDevInstaller.vdproj" '"PreBuildEvent"' '"PreBuildEvent" = "8:call \"$(ProjectDir)/../../../build/certificates/certificate.bat\" \"$(ProjectDir)..\\..\\..\\out\\application_studio_$(Configuration)\\$(Configuration)\\application_studio.exe\"\r\n"'
   # }

    $devenvDir = FindDevenvdPath
    

    Remove-Item -Path "$PSScriptRoot\..\out\Installer\Release\*" -Recurse -Force -ErrorAction SilentlyContinue
    
    & $devenvDir "$PSScriptRoot\..\DeviceToolsKit.sln" /project $Installer_proj /Build Release
    if ($LASTEXITCODE -ne 0) {

        # Remove pre build event from installer proj file if failed to sign
        #ReplaceLine "$PSScriptRoot\..\src\SPDev\SPDevInstaller\SPDevInstaller.vdproj" '"PreBuildEvent"' '"PreBuildEvent" = "8:"'
        exit $lastexitcode
    }

    $fullName = (Get-ItemProperty "$PSScriptRoot\..\ProjectInstaller\Release\*.msi").Name
    $AppName = (Get-ItemProperty "$PSScriptRoot\..\ProjectInstaller\Release\*.msi").Name.Split('.')[0]

    $major_ver, $minor_ver, $patch_ver = GetVersionOfFile $Proj
    $targetVersion ="$major_ver.$minor_ver.$patch_ver"

    $installerName = $AppName + "_v" + $targetVersion + ".msi"
    "Installer Name: $installerName"

    Rename-Item -Path "$PSScriptRoot\..\ProjectInstaller\Release\$fullName" -NewName $installerName

   # if($Sign -eq $True)
   # {
        # Sign Installer
        #& "$PSScriptRoot\certificates\certificate.bat" "$PSScriptRoot\..\out\Installer\Release\*.msi"
        # Remove pre build event from installer proj file after signing
        #ReplaceLine "$PSScriptRoot\..\src\SPDev\SPDevInstaller\SPDevInstaller.vdproj" '"PreBuildEvent"' '"PreBuildEvent" = "8:"'
   # }
}

主要步骤:
先清理,再生成,最后发布安装包。
重点说明

& $devenvDir "$PSScriptRoot\..\DeviceToolsKit.sln" /project $Installer_proj /Build Release

上述代码,控制Installer项目的采用release模式生成安装包。

 $fullName = (Get-ItemProperty "$PSScriptRoot\..\ProjectInstaller\Release\*.msi").Name
    $AppName = (Get-ItemProperty "$PSScriptRoot\..\ProjectInstaller\Release\*.msi").Name.Split('.')[0]

    $major_ver, $minor_ver, $patch_ver = GetVersionOfFile $Proj
    $targetVersion ="$major_ver.$minor_ver.$patch_ver"

    $installerName = $AppName + "_v" + $targetVersion + ".msi"
    "Installer Name: $installerName"

    Rename-Item -Path "$PSScriptRoot\..\ProjectInstaller\Release\$fullName" -NewName $installerName

上述代码,作用是用命名MSI的安装包,增加版本号尾缀。
但是需要注意,如果你采用了依赖框架的生成方式,那么生成完成后的Setup程序,将无法找到MSI文件。
原因是MSI文件已经被重命名,而负责检查安装环境,并调用MSI的Setup程序,就会找不到原先名字的MSI。
这个重命名的方法,仅适用于不生成Setup程序的发布方式。
有关Installer Setup 的使用,请参考我的其他博客。
里面有详细使用方法和步骤。
注释掉的部分

 #[string]$Installer_proj = "$PSScriptRoot\..\ProjectInstaller\ProjectInstaller.vdproj"
    #if($Sign -eq $True)
    #{
        #Add pre build event to sign .exe after rebuilding project but before building installer
        #ReplaceLine "$PSScriptRoot\..\src\SPDev\SPDevInstaller\SPDevInstaller.vdproj" '"PreBuildEvent"' '"PreBuildEvent" = "8:call \"$(ProjectDir)/../../../build/certificates/certificate.bat\" \"$(ProjectDir)..\\..\\..\\out\\application_studio_$(Configuration)\\$(Configuration)\\application_studio.exe\"\r\n"'
   # }

这个是给安装程序添加证书和签名,没有这两个东西的,就不用这个方法。

通过脚本调用

自动版本号+1

@ECHO OFF
SET ThisScriptsDirectory=%~dp0

PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '%~dp0Build.ps1'  -publish_Free_Installer 0 -publish_MSI_Installer 0 -updateVersion 1

pause

修改指定版本号

@ECHO OFF
SET ThisScriptsDirectory=%~dp0

PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '%~dp0Build.ps1' -publish_Free_Installer 0 -publish_MSI_Installer 0 -updateVersion 1 -major_ver 1 -minor_ver 4 -patch_ver 0

pause

发布免安装版本

@ECHO OFF
SET ThisScriptsDirectory=%~dp0

PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '%~dp0Build.ps1' -updateVersion 0 -publish_Free_Installer 1 -publish_MSI_Installer 0
pause

发布MSI安装版本

@ECHO OFF
SET ThisScriptsDirectory=%~dp0

PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '%~dp0Build.ps1' -updateVersion 0 -publish_Free_Installer 0 -publish_MSI_Installer 1
pause
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值