8

During a setup creation process, I am planning to do the following (within a C# Script):

  1. Read the AssemblyVersion and AssemblyFileVersion attribute values of one DLL.
  2. Iterate all DLLs and executables in the project and apply those version to their AssemblyVersion and AssemblyFileVersion attribute values.

Question now is: How to do step 2?

I successfully can do step 1, but for step 2 I don't see a real start point. What I probably have to do is to use some native P/Invoke methods since the attributes directly modify the version information resource information of a DLL/executable.

Any hints on this?

Uwe Keim
  • 38,279
  • 56
  • 171
  • 280

4 Answers4

13

Why don't you, during build process, read the AssemblyVersion and AssemblyFileVersion of one DLL, and save it back to other csproject's AssemblyInfo.cs, only then compile it?

As a matter of fact, I don't know whether it is possible to modify the DLL file directly, without resorting to something fanciful.

Or alternatively, make sure that all your DLLs share one common AssemblyInfo.cs. You can do this by adding the AssemblyInfo.cs as "Add As Link" when you add a new item in csproject. In this way when you do a compilation, all the DLLs will share the same AssemblyInfo.cs, and thus output the same AssemblyVersion.

Graviton
  • 79,554
  • 141
  • 413
  • 589
  • 1
    yes, that would be **much** easier! Set the version numbers straight at build time, e.g. using a continuous integration build server – marc_s Oct 11 '09 at 09:45
  • 1
    That would be the right way, changing the compiled files break clean information line between code and binaries. – Oliver Friedrich Oct 11 '09 at 09:53
  • Thank you very much, I do like the idea of sharing the AssemblyInfo.cs file! – Uwe Keim Oct 11 '09 at 10:32
  • Not a good idea to share the same AssemblyInfo.cs - if your DLLs has ComVisible, then you can't differentiate GUID and other info on assembly – johnnyontheweb Jan 27 '22 at 14:58
  • Just to remind the `AssemblyInfo.cs` contains not just the File & Assembly Version info but other information like ["Title","Description", "Company", "Product","Copyright","TradeMark"] and they cannot share the same name. – Vinod Srivastav Apr 08 '22 at 12:31
3

In my case, I created a T4 template for changing the AssemblyVersion and AssemblyFileVersion. I called the template Assembly.tt, and made it a linked file (when you add it choose Add Link, instead of Add). All my assemblies pull in the linked Assembly.tt file.

You can then run the T4 template from one location and it will update all the AssemblyVersion and AssemblyFileVersions. You don't have to call the file AssemblyInfo.cs for the information to be pulled into your dlls.

The code for the Assembly.tt file is:

<#@ template language="C#" hostspecific="true" #>
// 
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
// 

using System.Reflection;

[assembly: AssemblyVersion("4.<#= this.RevisionYear #>.<#= this.RevisionNumber #>.<#= this.RevisionTime #>")]
[assembly: AssemblyFileVersion("4.<#= this.RevisionYear #>.<#= this.RevisionNumber #>.<#= this.RevisionTime #>")]
<#+
    int RevisionYear = DateTime.UtcNow.Year;
    int RevisionNumber = (int)(DateTime.UtcNow - new DateTime(DateTime.UtcNow.Year,1,1)).TotalDays;
    int RevisionTime = (int)(DateTime.UtcNow - new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, DateTime.UtcNow.Day)).TotalMinutes;
#>

The output of the T4 template above will be:

// 
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
// 

using System.Reflection;

[assembly: AssemblyVersion("4.2016.284.1066")]
[assembly: AssemblyFileVersion("4.2016.284.1066")]
Kelly R
  • 119
  • 3
  • This actually will work as an answer to dynamically change the dll version on compile time, i wonder why this is not marked as answer. – Vinod Srivastav Apr 08 '22 at 12:16
1

If you have access to the sources, take the advice from Graviton

If you don't, you might be in trouble. Possibly you can disassemble with ILDASM and reassemble with ILASM. But this won't work out for strong-named assemblies.

Community
  • 1
  • 1
The Chairman
  • 7,016
  • 2
  • 37
  • 43
1

The attribute [AssemblyVersion()] and [AssemblyFileVersion()] both accepts a constant string as parameter.

So I can create a static class with a const string in the current assembly, and can supply it to these attributes as parameters as below

    public static class App
    {
        public const string Version = "1.0.0.1";
    }

and update the AssemblyInfo.cs as

[assembly: AssemblyVersion(App.Version)]
[assembly: AssemblyFileVersion(App.Version)]

This is an alternative suggestion then the automation/trick suggested by @Kelly R and @Gravtion above.

--Update 1--

In case you want to go for T4 template as @KellyR suggested the following can help you with the version:


private string Version()
{
    DateTime START = new DateTime(2021,2, 14); //StartDate
    DateTime NOW = DateTime.Now;
    int numMonths = (int)(NOW.Subtract(START).Days / (365.25 / 12));
    int Major = numMonths / 12;
    int Minor = numMonths % 12;
    int Build = (int)DateTime.Now.Day;
    string Revision = $"{(int)DateTime.Now.Hour}{DateTime.Now.Minute}";
    
    return $"{Major}.{Minor}.{Build}.{Revision}";
}

The START stores the start date of the project which is used to calculate the number of months passed till now. Then it's dividing the numMonths by 12 to get the number of year passed(considering it as Major version) and keeps the remaining months as Minor version then the current day as Build and hour + Minutes as Revision.

With that every time you build you will get the latest version of your product.

This can also be used in the T4 template as follows:

<#@ output extension=".cs" #>
<#@ template debug="true" language="C#" hostspecific="false" #>

using System.Reflection;

[assembly: AssemblyVersion("<#= NewVersion() #>")]
[assembly: AssemblyFileVersion("<#= NewVersion() #>")]



<#+
    private string NewVersion()
    {
        DateTime START = new DateTime(2021,2, 14); //StartDate
        DateTime NOW = DateTime.Now;
        int numMonths = (int)(NOW.Subtract(START).Days / (365.25 / 12));
        int Major = numMonths / 12;
        int Minor = numMonths % 12;
        int Build = (int)DateTime.Now.Day;
        string Revision = $"{(int)DateTime.Now.Hour}{DateTime.Now.Minute}";
    
        return $"{Major}.{Minor}.{Build}.{Revision}";

    }
    //Started On = 12-5-2021;
    
    
#>

Just remember to comment AssemblyVersion and AssemblyFileVersion in AssemblyInfo.cs when using it as T4 template.

//[assembly: AssemblyVersion("1.0.0.0")]
//[assembly: AssemblyFileVersion("1.0.0.0")]
Vinod Srivastav
  • 3,066
  • 1
  • 23
  • 34