16

I have a simple batch file that I'm running from a DOS command line that is used for building a small C# application that publishes a ClickOnce project. One line is this:

msbuild MyApp.csproj /t:publish /property:PublishDir="deploy/"

This currently publishes the application, but it uses the Publish Version that I set up in Visual Studio's "Publish" tab. I'm hoping to be able to set the publish version at the command line, and specifically, I'd like to use the Assembly Version of the project. Something like:

msbuild MyApp.csproj /t:publish /property:PublishDir="deploy/" /property:PublishVersion="$(Proj.AssemblyVersion)"

I'm hoping to do without creating a custom task, since this is just an interim solution, and I will replace it with a more proper build system later.

Alternatively, I've looked at updating the published manifest version using the Mage Command Line Tool with the -Update flag, but I did not know how to retrieve the assembly version number from the project or built assembly without using PowerShell or some program that would need to be downloaded. If I could use something that comes with Visual Studio, that would work as well.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mark Hildreth
  • 42,023
  • 11
  • 120
  • 109
  • Does the answer to [this question](http://stackoverflow.com/questions/1859328/setting-assemblyfileversion-with-msbuild-call) help at all? – adrianbanks Sep 17 '12 at 22:51
  • @adrianbanks: That sets the assembly version from some variable in the batch script. I'm hoping to set the deployment version from the assembly version (where the assembly version is stored in the AssemblyInfo.cs for the project). – Mark Hildreth Sep 17 '12 at 22:53

3 Answers3

14

Try adding this to your .csproj file. The target will retrieve the version from the output assembly and update the ApplicationVersion before the Publish:

<Target Name="AfterCompile">
  <GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
    <Output TaskParameter="Assemblies" ItemName="fooAssemblyInfo"/>
  </GetAssemblyIdentity>
  <PropertyGroup>
    <ApplicationVersion>%(fooAssemblyInfo.Version)</ApplicationVersion>
  </PropertyGroup>
</Target>

There's probably a nicer way to dynamically get the assembly name but for your purpose it should do the trick.

Credit to this answer for the GetAssemblyIdentity syntax: https://stackoverflow.com/a/443364/266882

Questioner Edit:

See comment below for update.

RubberDuck
  • 11,933
  • 4
  • 50
  • 95
Dan Nolan
  • 4,733
  • 2
  • 25
  • 27
  • I eventually went with another solution (changing the rules a bit), but this appears like it would work if my way doesn't pan out. Thanks! – Mark Hildreth Sep 19 '12 at 14:29
  • I came back to this, and it didn't work exactly as I expected. My hope was to have the deployment version defined in the deployment manifest that is generated. However, this is generated before publish. Doing a similar step as shown on BeforeBuld would work, but the assembly isn't available by then. My workaround is to pass in the version to msbuild on the command line, and use that in the BeforeBuild task. – Mark Hildreth Dec 14 '12 at 16:58
  • 1
    bin\$(Configuration)\WpfApplication1.exe could be replaced by $(TargetPath) – rudolf_franek Jan 03 '14 at 10:07
  • Agreed @rudolf_franek, that's much better. I've updated my answer. – Dan Nolan Jan 07 '14 at 10:36
  • `$(TargetPath)` was not working, changing it to `` fixed it for me. – Christophe Devos May 19 '21 at 15:08
12
msbuild xxx.csproj /target:clean;publish /property:ApplicationVersion=1.2.3.4
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
Robin B
  • 159
  • 1
  • 3
  • 1
    If using VSTS you can use `/property:ApplicationVersion=1.0.0.$(Build.SourceVersion)` to get the changeset / commit ID automatically appended. Of course you can still do major versioning here if you wish, but it means a new build will always have a new version and you can always track back to the source version. – Simon_Weaver May 19 '17 at 06:47
  • That feels amazing - for the last 7 years I've been auto-incrementing it myself – Simon_Weaver May 19 '17 at 06:48
  • This is the simplest and most minimal approach, works awesome with Jenkins! Thanks! – Ojingo Jan 08 '19 at 16:08
10

In order to correctly update the version declared in the deployment manifest you need to modify the ApplicationVersion at the "AfterCompile" step rather than the "BeforePublish" step, since the application manifest is generated at build time. But then you can't rely on the $(TargetPath) property to point to the assembly and instead use the following path: $(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)

So here's the updated Target code snippet that you can add to the .csproj file:

<Target Name="AfterCompile">
  <GetAssemblyIdentity AssemblyFiles="$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)">
     <Output TaskParameter="Assemblies" ItemName="AssemblyInfo" />
  </GetAssemblyIdentity>
  <PropertyGroup>
    <ApplicationVersion>%(AssemblyInfo.Version)</ApplicationVersion>
  </PropertyGroup>
</Target>
Run-O
  • 109
  • 1
  • 3