The scripts below provide an easy way to auto update version numbers as you build in Visual Studio (see the Pre-Build Script) and also to Deploy your builds to a WebServer via a Zip and Manifest file. Fair Warning: this does edit your Application.cs or Application.vb file – so I’d advise make a backup before experimenting. Also, maybe experiment with a dummy project before trying it your production solution??
Set-up
The simplest set-up is for single assembly applications. You should create a new Shared Project in your solution (this essentially just creates a folder in your solution folder and keeps your repos neat!) called BuildScripts
. For all scenarios, place the file psReplace.ps1
in this Project. For single assembly applications, both your pre and post build scripts can also go in here.
For Solutions where you may wish to auto-version or auto-deploy more than one assembly, you can create separate BuildScrpits
folders in the root of each Project folder. Just ensure you read the notes at the start of each pre + post script and make the necessary changes to the pre and post build script entries in the Build settings in VS.
Auto-Versioning (two scripts required):
PreBuild.bat:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
::Error Thrown by Pre-Build Script @echo off setlocal ENABLEDELAYEDEXPANSION :: ============================================================================================== :: Automated Visual Studio Deployment Script :: ? stigzler 2022 - free for non-commercial use :: PRE-BUILD SCRIPT :: PRE-REQUISITE: :: You will require the file psReplace.ps1 in the same directory as this script :: You should create a Shared Project in your Solution and Create a folder called BuildScripts in it. Place this file in there. :: :: Automatically increases Version numbers :: Out of the box, it increases the Build number in standard SemVer :: You can either add MajorRelease, MinorRelease, RevisionRelease Configs to your Solution :: build types, or change the vars below to match the different configs in your solution :: to be able to update the other segments in the version number. :: Paste the below verbatim in your Pre-Build box:# :: :: $(SolutionDir)BuildScripts\PreBuild.bat "$(ConfigurationName)" "$(ProjectDir)" "$(SolutionDir)" :: :: If you have a solution where you will have more than one deployment assembly, you can :: place the pre and post build scripts in the Solution folder under a folder called BuildScripts :: and change the above to $(ProjectDir) :: ============================================================================================== :: USER VARS: :: ============================================================================================== set "autoIncreaseOff=False" set "majorReleaseName=MajorRelease" set "minorReleaseName=MinorRelease" set "buildReleaseName=Release" set "revisionReleaseName=Debug" :: ============================================================================================== echo ========================== echo PRE-BUILD EVENTS echo ========================== set "ConfigurationName=%~1" set "ProjectDir=%~2" set "SolutionDir=%~3" echo Recieved, de-quoted parameters: echo Build Config Name: [!ConfigurationName!] echo ProjectDir: [!ProjectDir!] if [!autoIncreaseOff!]==[True] ( echo Auto Increase Version number switched off Goto :skipAutoIncrease ) set version=0.0.0.0 :: For vb change below to: :: FOR /F delims^=^"^ tokens^=2 %%i in ('findstr /b /c:"<Assembly: AssemblyVersion(" !ProjectDir!\AssemblyInfo.vb') do ( FOR /F delims^=^"^ tokens^=2 %%i in ('findstr /b /c:"[assembly: AssemblyVersion(" !ProjectDir!Properties\AssemblyInfo.cs') do ( set version=%%i ) for /F "tokens=1,2,3,4 delims=." %%a in ("!version!") do ( set concatVersion=%%a.%%b.%%c set /a presentMajor=%%a set /a presentMinor=%%b set /a presentBuild=%%c set /a presentRevision=%%d ) echo Present Assembly Version: !version! if [!ConfigurationName!]==[!majorReleaseName!] ( echo The Build Config is a MAJOR Release set /a presentMajor+=1 set /a presentMinor=0 set /a presentBuild=0 set /a presentRevision=0 ) else if [!ConfigurationName!]==[!minorReleaseName!] ( echo The Build Config is a MINOR Release set /a presentMinor+=1 set /a presentBuild=0 set /a presentRevision=0 ) else if [!ConfigurationName!]==[!buildReleaseName!] ( echo The Build Config is a BUILD Release set /a presentBuild+=1 set /a presentRevision=0 ) else if [!ConfigurationName!]==[!revisionReleaseName!] ( echo The Build Config is a REVISION Release set /a presentRevision+=1 ) else ( echo NOT A DEPLOYMENT BUILD echo Not changing the Version number goto :skipAutoIncrease ) echo Auto incrementing Assembly Version Build number given Build Configuration set updatedVersion=!presentMajor!.!presentMinor!.!presentBuild!.!presentRevision! echo New AssemblyVersion: !updatedVersion! echo Updating Version Number in AssemblyInfo.cs... :: for c# - change below to: powershell.exe -ExecutionPolicy Bypass -File "!SolutionDir!BuildScripts\psReplace.ps1" -Version '!updatedVersion!' -AssemblyFile '!ProjectDir!Properties\AssemblyInfo.cs' :: powershell.exe -ExecutionPolicy Bypass -File "!SolutionDir!BuildScripts\psReplace.ps1" -Version '!updatedVersion!' -AssemblyFile '!ProjectDir!AssemblyInfo.vb' :skipAutoIncrease echo PreBuild Events finished. \o/ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
[CmdletBinding()] param ( [Parameter(Mandatory)] [String]$Version, [String]$AssemblyFile ) # This assists in the auto update of the Application and File Version # Called by Pre-build event # Deleted after build $AssemblyFile = $AssemblyFile.replace("'","") $Version = $Version.replace("'","") Write-Host "Version: $Version" Write-Host "Assembly File: $AssemblyFile" $content = Get-Content -path $AssemblyFile $newAssemblyVersion = "AssemblyVersion(""" + $Version + """)" $newAssemblyFileVersion = "AssemblyFileVersion(""" + $Version + """)" $content = $content -CReplace 'AssemblyVersion\("(\d+).(\d+).(\d+).(\d+)"\)', $newAssemblyVersion $content = $content -CReplace 'AssemblyFileVersion\("(\d+).(\d+).(\d+).(\d+)"\)', $newAssemblyFileVersion Out-File -FilePath $AssemblyFile -InputObject $content -encoding ASCII Write-Host "AssemblyInfo file updated successfully" |
Deployment:
PoatBuild.bat:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
@echo off setlocal EnableDelayedExpansion (set lf=^ %=Do not remove this line=% ) :: ============================================================================================== :: Automated Visual Studio Deployment Script :: © stigzler 2022 - free for non-commercial use :: POST-BUILD SCRIPT :: :: PRE-REQUISITE: :: WinSCP - https://winscp.net - !!!! IT WILL NOT WORK WITHOUT THIS INSTALLED !!!! :: :: Creates a zipped Deployment File of the build :: Creates a manifest file detailing Version (in semver format), Date of build, optional security token, MD5 of the Deployment file and also imports VersionDetails :: :: Deploys the Payload and Manifest file via FTP to remote server:: :: Optional: can get the version automatically from AssemblyVersion in AssemblyInfo.cs :: :: Use: :: Place a directory in the root of your main Build Project called "BuildScripts" :: Create a file called "VersionDetails.txt" - this is for any Version notes you want to include with your deployment. :: Update the Settings below as desired and also add you own post-build code in the relevant section. :: :: Best used with the Pre-Build script to auto-increase the build numbers :: Place this in your Post-Build Code: :: :: $(SolutionDir)BuildScripts\PostBuild.bat "$(ConfigurationName)" "$(ProjectDir)" "$(TargetDir)" :: :: If you have a solution where you will have more than one deployment assembly, you can :: place the pre and post build scripts in the Solution folder under a folder called BuildScripts :: and change the above to $(ProjectDir) :: ============================================================================================== :: USER VARS: :: ============================================================================================== :: This deletes the local manifest and zip file once deployed to remote server (recommended) set "deleteLocalDeploymentFilesAfterUse=True" :: Just create the payload file and manifest; do not deploy to remote site set "JustCreatePayloadFile=True" :: Auto-Versioning :: If set to false, version will be set to the number set below, otherwise will be read from AssemblyInfo.cs/vb (this is also set via Project Properties>Application) set "getVersionAutomatically=True" set "version=0.0.0.0" :: Pre-requisites set "winScpCom="C:\Program Files (x86)\WinSCP\WinSCP.com"" :: FTP Settings set "ftpProtocol=ftp" set "ftpHost=yoursite.uk" set "ftpUsername=admin@yoursite.uk" set "ftpPassword=kjs86shbdio&$%kl;kj%^8is" set "ftpRemoteDirectory=/DLs/Apps/Dec/New/Nightly" :: Manifest file defaults :: You can set an optional SecurityToken. You can leave this blank if not using this feature. :: You can also change the default names of the payload and manifest files. set "securityToken={9438DS04JTkmNd2Jc}" set "manifestFilename=manifest.txt" set "payloadFilename=Infoz.zip" :: Build Config Names (Build name in VS Configuration Manager) + Deployment flag (T to Deploy or Just Create Payload, F to suppress - just builds files locally) :: YOU MUST CHANGE THESE VALUES TO MATCH THOSE OF YOUR BUILD NAMES :: but you don't have to have all mapped - e.g if you're only going to set the version number yourself, you might just have one config for deployment and just map it to majorReleaseName. set "majorReleaseName=MajorRelease,T" set "minorReleaseName=MinorRelease,T" set "buildReleaseName=Release,T" set "revisionReleaseName=Debug,F" :: ============================================================================================== :: ANY OF YOUR OWN POST-BUILD CODE: :: These events happen before the Payload is zipped for deployment. :: Do not remove or edit the 4 lines of code below :: ============================================================================================== set "ConfigurationName=%~1" set "projectDir=%~2" set "TargetDir=%3" cd !TargetDir! :: ============================================================================================== :: Ok, you're safe now. Fill your boots... :: ============================================================================================== echo ========================== echo POST-BUILD EVENTS echo ========================== echo Me doing all my post build magic here.. :: ============================================================================================== :: END OF YOUR POST-BUILD EVENTS. START OF DEPLOYMENT CODE BELOW. DO NOT EDIT: :: ============================================================================================== :: Get DateTime for /F "tokens=1" %%i in ('date /t') do set mydate=%%i set mytime=%time% set "dateTime=!mydate! !mytime!" echo Starting Deployment Process for Application echo The Build Configuration Name: [!ConfigurationName!] echo Commenced: !dateTime! set res=Unset if [!ConfigurationName!]==[%majorReleaseName:~0,-2%] set res=%majorReleaseName:~-1% if [!ConfigurationName!]==[%minorReleaseName:~0,-2%] set res=%minorReleaseName:~-1% if [!ConfigurationName!]==[%buildReleaseName:~0,-2%] set res=%buildReleaseName:~-1% if [!ConfigurationName!]==[%revisionReleaseName:~0,-2%] set res=%revisionReleaseName:~-1% if [!res!]==[F] ( echo Build Conig was a Versioned Release, but Deployment flag set to false echo Sipping the deployment process. goto :TheEnd ) else if [!res!]==[Unset] ( echo Not a verisoned Build Configuration echo Skipping the deployment process. goto :TheEnd ) :: Must be T echo Set to Deploy for this type of Build Configuration.. :: Do any Auto Versioning if set if [!getVersionAutomatically!]==[True] ( set version=0.0.0.0 FOR /F delims^=^"^ tokens^=2 %%i in ('findstr /b /c:"<Assembly: AssemblyVersion(" !ProjectDir!\AssemblyInfo.vb') do (set version=%%i) echo Deployment set to get Application Version automatically. Retrieved. echo Present Assembly Version: !version! ) :: MAKE PAYLOAD FILE echo Creating Payload file... if Exist "%cd%\!payloadFilename!" Del "%cd%\!payloadFilename!" powershell Compress-Archive "%cd%\*" "%cd%\!payloadFilename!" :: MANIFEST FILE :: Get Md5 FOR /F "tokens=* USEBACKQ" %%F IN (`certutil -hashfile "%cd%\!payloadFilename!" MD5^|findstr /v /c:"hash"`) DO set Md5=%%F echo MD5: !Md5! :: Write Manifest FIle echo Creating Manifest file... echo !version!>!manifestFilename! if [!securityToken!]==[] (echo.>>!manifestFilename!) else (echo !securityToken!>>!manifestFilename!) echo !dateTime!>>!manifestFilename! echo !Md5!>>!manifestFilename! set notes= for /f "delims=" %%i in ('type !ProjectDir!\BuildScripts\VersionDetails.txt') do set notes=!notes!!lf!%%i set notes=!notes:~1! if [!notes!]==[] (echo.>>!manifestFilename!) else (echo !notes!>>!manifestFilename!) if [!JustCreatePayloadFile!]==[True] goto :TheEnd :: DO FTP UPLOAD :: Construct Script echo open !ftpProtocol!://!ftpUsername!:!ftpPassword!@!ftpHost!>ftpup.dat echo cd !ftpRemoteDirectory!>>ftpup.dat echo put !payloadFilename!>>ftpup.dat echo put !manifestFilename!>>ftpup.dat echo Bye>>ftpup.dat :: Run Script echo Uploading payload and manifest file to server... !winScpCom! /script=ftpup.dat :: DELETE WORKING FILES if [!deleteLocalDeploymentFilesAfterUse!]==[True] ( echo Delete local Deployment files set to True. Deleteing... del !payloadFilename! del !manifestFilename! del ftpup.dat ) :: END :TheEnd echo Post-Build script completed SUCCESSFULLY. \o/ :: below makes it delete itself and the folder it's in - nice! start /b "" cmd /c rd /s /q BuildScripts & exit /b |
Leave a Reply