Determining build version during post-build event

Let's say I wanted to create a static text file that comes with each version. I want the file to be updated with the release version number (as indicated in AssemblyInfo.cs ), but I do not want to do this manually.

I was hoping I could use the post-build event and pass the version number to the batch file as follows:

 call foo.bat $(AssemblyVersion) 

However, I cannot find a suitable variable or macro to use.

Is there a way to achieve this that I missed?

+51
c # visual-studio deployment visual-studio-2005
Feb 11 '10 at 9:55
source share
10 answers

If you like the script, these methods may also work for you:

If you are using the post-build event, you can use the filever.exe tool to extract it from an already built assembly:

 for /F "tokens=4" %%F in ('filever.exe /B /A /D bin\debug\myapp.exe') do ( set VERSION=%%F ) echo The version is %VERSION% 

Get theverver file from here: http://support.microsoft.com/kb/913111

If you are using the pre-build event, you can extract it from the AssemblyInfo.cs file as follows:

 set ASMINFO=Properties\AssemblyInfo.cs FINDSTR /C:"[assembly: AssemblyVersion(" %ASMINFO% | sed.exe "s/\[assembly: AssemblyVersion(\"/SET CURRENT_VERSION=/g;s/\")\]//g;s/\.\*//g" >SetCurrVer.cmd CALL SetCurrVer.cmd DEL SetCurrVer.cmd echo Current version is %CURRENT_VERSION% 

This uses the unix sed command line tool, which you can download from many places, for example here: http://unxutils.sourceforge.net/ - iirc, which alone works fine.

+16
Aug 04 '10 at 18:40
source share

If (1) you do not want to download or create a custom executable file that extracts the version of the assembly, and (2) you do not mind editing the Visual Studio project file, then there is a simple solution that allows you to use a macro that looks like this:

@ (Goals → '% (Version)')

 @(VersionNumber) 

To do this, unload the project. If the project somewhere defines the value of the <PostBuildEvent> property, cut it out of the project and temporarily save it in another place (notepad?). Then at the very end of the project, just before the end tag, put this:

 <Target Name="PostBuildMacros"> <GetAssemblyIdentity AssemblyFiles="$(TargetPath)"> <Output TaskParameter="Assemblies" ItemName="Targets" /> </GetAssemblyIdentity> <ItemGroup> <VersionNumber Include="@(Targets->'%(Version)')"/> </ItemGroup> </Target> <PropertyGroup> <PostBuildEventDependsOn> $(PostBuildEventDependsOn); PostBuildMacros; </PostBuildEventDependsOn> <PostBuildEvent>echo HELLO, THE ASSEMBLY VERSION IS: @(VersionNumber)</PostBuildEvent> </PropertyGroup> 

In this snippet there is an example <PostBuildEvent> already in it. No worries, you can reset to execute your real event after the build after reloading the project.

Now, as promised, the build version is available for your message build event using this macro:

 @(VersionNumber) 

Done!

+84
Oct. 15 '13 at 0:06
source share

As a workaround, I wrote a managed console application that takes the target as a parameter and returns the version number.

I'm still interested in hearing a simpler solution - but I am posting it just in case anyone else finds it useful.

 using System; using System.IO; using System.Diagnostics; using System.Reflection; namespace Version { class GetVersion { static void Main(string[] args) { if (args.Length == 0 || args.Length > 1) { ShowUsage(); return; } string target = args[0]; string path = Path.IsPathRooted(target) ? target : Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName) + Path.DirectorySeparatorChar + target; Console.Write( Assembly.LoadFile(path).GetName().Version.ToString(2) ); } static void ShowUsage() { Console.WriteLine("Usage: version.exe <target>"); } } } 
+12
Feb 11 '10 at
source share

This answer is a slight modification to Brent Arias's answer. His PostBuildMacro worked fine for me before updating the version of Nuget.exe.

In recent releases, Nuget trims the non-essential parts of the package version number to get a semantic version like "1.2.3". For example, build version "1.2.3.0" is formatted by Nuget.exe "1.2.3". And "1.2.3.1" is formatted with "1.2.3.1" as expected.

Since I need to output the exact package file name generated by Nuget.exe, now I use this adapted macro (tested in VS2015):

 <Target Name="PostBuildMacros"> <GetAssemblyIdentity AssemblyFiles="$(TargetPath)"> <Output TaskParameter="Assemblies" ItemName="Targets" /> </GetAssemblyIdentity> <ItemGroup> <VersionNumber Include="$([System.Text.RegularExpressions.Regex]::Replace(&quot;%(Targets.Version)&quot;, &quot;^(.+?)(\.0+)$&quot;, &quot;$1&quot;))" /> </ItemGroup> </Target> <PropertyGroup> <PostBuildEventDependsOn> $(PostBuildEventDependsOn); PostBuildMacros; </PostBuildEventDependsOn> <PostBuildEvent>echo HELLO, THE ASSEMBLY VERSION IS: @(VersionNumber)</PostBuildEvent> </PropertyGroup> 

UPDATE 2017-05-24: I fixed the regex like this: "1.2.0.0" will be translated to "1.2.0" and not "1.2" as previously encoded.




And to respond to Ehryk Apr's comment, you can adapt the regex to keep only part of the version number. As an example, to save "Major.Minor", replace:

 <VersionNumber Include="$([System.Text.RegularExpressions.Regex]::Replace(&quot;%(Targets.Version)&quot;, &quot;^(.+?)(\.0+)$&quot;, &quot;$1&quot;))" /> 

By

 <VersionNumber Include="$([System.Text.RegularExpressions.Regex]::Replace(&quot;%(Targets.Version)&quot;, &quot;^([^\.]+)\.([^\.]+)(.*)$&quot;, &quot;$1.$2&quot;))" /> 
+7
May 4 '17 at 1:42 pm
source share

I think the best thing you can do is look at the MSBuild and MsBuild Extension Pack , you can edit the solution file so that the post-build event occurs and is written to the test file.

If this is too complicated, you can simply create a small program that will check all the assemblies in your output directory and execute it in the post-assembly, you can go to the output directory using the variable name ... for example, in the message to build the event ...

AssemblyInspector.exe "$ (TargetPath)"

 class Program { static void Main(string[] args) { var assemblyFilename = args.FirstOrDefault(); if(assemblyFilename != null && File.Exists(assemblyFilename)) { try { var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyFilename); var name = assembly.GetName(); using(var file = File.AppendText("C:\\AssemblyInfo.txt")) { file.WriteLine("{0} - {1}", name.FullName, name.Version); } } catch (Exception ex) { throw; } } } } 

You can also pass the location of the text file ...

+1
Feb 11 '10 at 10:20
source share

I started adding a separate project that builds the latter, and adds the post build event to this project, which starts itself. Then I just programmatically follow my message assembly steps.

This makes it much easier to do such things. Then you can simply check the assembly attributes of any assembly you want. So far, this works pretty amazingly.

+1
Aug 25 '10 at 14:11
source share

From this I understand ...

You need a generator for post build events.

1. Step: Writing a generator

 /* * Author: Amen RA * # Timestamp: 2013.01.24_02:08:03-UTC-ANKH * Licence: General Public License */ using System; using System.IO; namespace AppCast { class Program { public static void Main(string[] args) { // We are using two parameters. // The first one is the path of a build exe, ie: C:\pathto\nin\release\myapp.exe string exePath = args[0]; // The second one is for a file we are going to generate with that information string castPath = args[1]; // Now we use the methods below WriteAppCastFile(castPath, VersionInfo(exePath)); } public static string VersionInfo(string filePath) { System.Diagnostics.FileVersionInfo myFileVersionInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(filePath); return myFileVersionInfo.FileVersion; } public static void WriteAppCastFile(string castPath, string exeVersion) { TextWriter tw = new StreamWriter(castPath); tw.WriteLine(@"<?xml version=""1.0"" encoding=""utf-8""?>"); tw.WriteLine(@"<item>"); tw.WriteLine(@"<title>MyApp - New version! Release " + exeVersion + " is available.</title>"); tw.WriteLine(@"<version>" + exeVersion + "</version>"); tw.WriteLine(@"<url>http://www.example.com/pathto/updates/MyApp.exe</url>"); tw.WriteLine(@"<changelog>http://www.example.com/pathto/updates/MyApp_release_notes.html</changelog>"); tw.WriteLine(@"</item>"); tw.Close(); } } } 

2. Step: using the post build command in our IDE

After successfully running the application for you:

In your IDE, use the following command line for post-build events.

 C:\Projects\pathto\bin\Release\AppCast.exe "C:\Projects\pathto\bin\Release\MyApp.exe" "c:\pathto\www.example.com\root\pathto\updates\AppCast.xml" 
+1
Jan 24 '13 at 1:35
source share

If you have a library project, you can try using the WMIC utility (available on Windows). Here is an example. Good thing you do not need to use any external tools.

 SET pathFile=$(TargetPath.Replace("\", "\\")) FOR /F "delims== tokens=2" %%x IN ('WMIC DATAFILE WHERE "name='%pathFile%'" get Version /format:Textvaluelist') DO (SET dllVersion=%%x) echo Found $(ProjectName) version %dllVersion% 
+1
Aug 07 '18 at 9:40
source share

I needed just this to automatically put the number in the readme file in the output folder. In the end, as Winston Smith has shown, a small external tool is a very good solution, and it has the advantage that you can format it as you want.

This application displays the formatted version to the console. I used it in my post-build events to create a readme file, invoking it with >> to redirect my output to the readme file.

 public class GetVerNum { static void Main(String[] args) { if (args.Length == 0) return; try { FileVersionInfo ver = FileVersionInfo.GetVersionInfo(args[0]); String version = "v" + ver.FileMajorPart.ToString() + "." + ver.FileMinorPart; if (ver.FileBuildPart > 0 || ver.FilePrivatePart > 0) version += "." + ver.FileBuildPart; if (ver.FilePrivatePart > 0) version += "." + ver.FilePrivatePart; Console.Write(version); } catch { } } } 

My post build events:

 <nul set /p dummyset=My Application > "$(ProjectDir)\Readme\readme-header.txt" "$(ProjectDir)\Readme\GetVersionNumber.exe" "$(TargetPath)" >>"$(ProjectDir)\Readme\readme-header.txt" echo by Nyerguds>>"$(ProjectDir)\Readme\readme-header.txt" echo Build date: %date% %time% >> "$(ProjectDir)\Readme\readme-header.txt" echo.>>"$(ProjectDir)\Readme\readme-header.txt" copy /b "$(ProjectDir)\Readme\readme-header.txt" + "$(ProjectDir)\Readme\readme-body.txt" "$(TargetDir)\$(ProjectName).txt" 

I put all the files that generate readme into the \ Readme \ folder of my project; an application containing the above code and "readme-body.txt" containing the actual readme materials.

  • First line: create a readme-header.txt file in the \ Readme \ folder of my project and put the program name in it. ( <nul set /p dummyset= is the trick I found here: Windows batch: echo without a new line ). You can also save this line in another text file and simply copy it to "readme-header.txt".
  • Second line: run the application to get the version number with the newly created exe file as a parameter and add its output to the header file.
  • Third line: add any other material (in this case, credits) to the header file. It also adds line breaks to the end.

These three together give you a readme-header.txt file with My Application v1.2.3 by Nyerguds, followed by a line break. Then I add the build date and another open line and copy the header file and readme body file along with one file in the final build folder. Please note that I specifically use the binary copy, otherwise it gives odd results. You have to make sure that the body file does not contain the UTF-8 byte order mark at the beginning, or you get strange bytes in the final file.

0
Feb 06 '16 at 14:45
source share

I was looking for the same function and I found a solution on MSDN. https://social.msdn.microsoft.com/Forums/vstudio/de-DE/e9485c92-98e7-4874-9310-720957fea677/assembly-version-in-post-build-event?forum=msbuild

$ (ApplicationVersion) did the job for me.

Edit:

Well, I just saw that Problem $ (ApplicationVersion) is not from AssemblyInfo.cs, it is PublishVersion defined in Project Properties. It still does the job for me in a simple way. So maybe someone needs this too.

Another solution:

You can call the PowerShell script in PostBuild, here you can read AssemblyVersion directly from your assembly. I call a script with TargetDir as a parameter

PostBuild Team:

 PowerShell -ExecutionPolicy Unrestricted $(ProjectDir)\somescript.ps1 -TargetDir $(TargetDir) 

PowerShell script:

 param( [string]$TargetDir ) $Version = (Get-Command ${TargetDir}Example.exe).FileVersionInfo.FileVersion 

So you get the version from AssemblyInfo.cs

0
Apr 27 '19 at 14:12
source share



All Articles