Intro
Table of Contents
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.
Set-up
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.
There are some subtle difference if using on .net Framework or .net/.net Core so make sure you read the intro notes on the scripts.
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 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 |
::Error Thrown by Pre-Build Script @echo off setlocal ENABLEDELAYEDEXPANSION :: ============================================================================================== :: Automated Visual Studio Deployment Script :: ? stigzler/MagoCode 2025 - free for non-commercial use :: PRE-BUILD SCRIPT :: Automatically increases Version numbers :: Out of the box, it increases the Build number in standard SemVer :: You can either add MajorRelease, MinorRelease, (Revision)Release 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. :: PRE-REQUISITES: :: 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. :: For use with .net. .net Framework and .net Core projects. :: FOR .NET AND .NET CORE architecture: you will need to ensure the following: :: Project for packaging has the file [Project]\Properties\AssemblyInfo.cs :: Above can be auto-created: Create Properties folder. Right Click>Add New Item>Assembly Information File :: in the .csproj file, ensure following is extant: :: <GenerateAssemblyInfo>false</GenerateAssemblyInfo> :: Your AssemblyInfo.cs file should contain the two lines below (with your desired starting version in AssemblyVersion): :: [assembly: AssemblyVersion("1.4.14.0")] :: [assembly: AssemblyFileVersion("1.4.14.0")] :: Paste the below verbatim in your Pre-Build box: :: call $(ProjectDir)..\BuildScripts\PreBuild.bat "$(ConfigurationName)" "$(ProjectDir)" "$(ProjectDir)..\BuildScripts" "$(AssemblyName)" :: User settings: :: autoIncreaseOff: Set to True to disable auto-incrementing of version numbers :: majorReleaseName, minorReleaseName, buildReleaseName, revisionReleaseName: Set to the names of your build configurations :: updateAssemblyVersion, updateFileVersion: Set to 1 to update the respective version numbers in your csproj file (0 to skip) :: backupFile: Set to 1 to backup the csproj file before updating it (recommended) :: ================================================================================ :: USER VARIABLES: :: ================================================================================ set "autoIncreaseOff=False" set "majorReleaseName=MajorRelease" set "minorReleaseName=MinorRelease" set "buildReleaseName=Release" set "revisionReleaseName=Debug" set "updateAssemblyVersion=1" set "updateFileVersion=1" set "backupFile=1" :: ================================================================================ :: !!!!!!!!!!!!!!!!!!!! DO NOT EDIT BELOW THIS LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :: ================================================================================ echo ================================================================================================================ echo PRE-BUILD: AUTO-INCREMENT VERSION SCRIPT echo ================================================================================================================ set "ConfigurationName=%~1" set "ProjectDir=%~2" set "PsReplaceDir=%~3" set "AssemblyName=%~4" echo User Set Options: echo Auto-Increase Off: !autoIncreaseOff! echo Major, Minor, Build, Revision config names set to: [!majorReleaseName!], [!minorReleaseName!], [!buildReleaseName!], [!revisionReleaseName!] echo Versions to update (Assembly, File, Package): [!updateAssemblyVersion!], [!updateFileVersion!], [!updatePackageVersion!] echo Backup csproj: [!backupFile!] echo. echo Recieved parameters: echo Build Config Name: [!ConfigurationName!] echo ProjectDir: [!ProjectDir!] echo PsReplaceDir: [!PsReplaceDir!] echo AssemblyName: [!AssemblyName!] echo. if [!autoIncreaseOff!]==[True] ( echo Auto Increase Version number switched off. Finishing. Goto :skipAutoIncrease ) set version=0.0.0.0 FOR /F delims^=^"^ tokens^=2 %%i in ('findstr /b /c:"[assembly: AssemblyVersion(" !ProjectDir!Properties\AssemblyInfo.cs') do ( set version=%%i ) :: For vb change above to: :: FOR /F delims^=^"^ tokens^=2 %%i in ('findstr /b /c:"<Assembly: AssemblyVersion(" !ProjectDir!\AssemblyInfo.vb') 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 AssemblyVersion: [!version!] if [0.0.0.0]==[!version!] ( echo Present Assembly version at zero - exiting script goto :skipAutoIncrease ) 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 file... echo. powershell.exe -ExecutionPolicy Bypass -File "!PsReplaceDir!\psReplace.ps1" -Version !updatedVersion! -AssemblyFile !ProjectDir!Properties\AssemblyInfo.cs' -UpdateAssemblyVersion !updateAssemblyVersion! -UpdateFileVersion !updateFileVersion! -BackupFile !backupFile! :: For VB change above to: :: powershell.exe -ExecutionPolicy Bypass -File "!PsReplaceDir!\psReplace.ps1" -Version !updatedVersion! -AssemblyFile !ProjectDir!AssemblyInfo.vb' -UpdateAssemblyVersion !updateAssemblyVersion! -UpdateFileVersion !updateFileVersion! -BackupFile !backupFile! :skipAutoIncrease echo Batch script completed successfully. Exiting. echo ================================================================================================================ echo PRE-BUILD: AUTO-INCREMENT VERSION SCRIPT FINISHED. echo ================================================================================================================ exit 0 |
psReplace.ps1:
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 |
[CmdletBinding()] param ( [Parameter(Mandatory=$true)][String]$Version, [Parameter(Mandatory=$true)][String][String]$AssemblyFile, [Parameter(Mandatory=$false)][String]$UpdateAssemblyVersion = 1, [Parameter(Mandatory=$false)][String]$UpdateFileVersion = 1, [Parameter(Mandatory=$false)][String]$BackupFile = 1 ) $AssemblyFile = $AssemblyFile.replace("'","") $Version = $Version.replace("'","") Write-Host "----------------------------------------------------------------------------------------------------------------" Write-Host "REPLACE VERSION POWERSHELL SCRIPT " Write-Host "----------------------------------------------------------------------------------------------------------------" Write-Host "Updating AssemblyInfo file with new version number" Write-Host "New Version Number: $Version" Write-Host "Assembly File: $AssemblyFile" Write-Host "Versions to update (Assembly, File): $UpdateAssemblyVersion", $UpdateFileVersion Write-Host "Backup File: $BackupFile" if ($BackupFile -eq 1) { $BackupFile = $AssemblyFile + ".bak" Write-Host "Creating backup file: $BackupFile" Copy-Item -Path $AssemblyFile -Destination $BackupFile } $content = Get-Content -path $AssemblyFile $newAssemblyVersion = "AssemblyVersion(""" + $Version + """)" $newAssemblyFileVersion = "AssemblyFileVersion(""" + $Version + """)" Write-Host Attempting version changes via -Replace command if ($UpdateAssemblyVersion -eq 1) {$content = $content -Replace 'AssemblyVersion\("(\d+).(\d+).(\d+).(\d+)"\)', $newAssemblyVersion} if ($UpdateFileVersion -eq 1) {$content = $content -Replace 'AssemblyFileVersion\("(\d+).(\d+).(\d+).(\d+)"\)', $newAssemblyFileVersion} Out-File -FilePath $AssemblyFile -InputObject $content -encoding ASCII Write-Host "----------------------------------------------------------------------------------------------------------------" Write-Host "*** POWERSHELL: VERSIONS UPDATED SUCCESSFULLY *** \o/ \o/ \o/ \o/ \o/ \o/ \o/ \o/ \o/" Write-Host "----------------------------------------------------------------------------------------------------------------" |
Auto Deployment:
PostBuild.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