54

It says in AssemblyInfo.cs for C# projects that it's possible to specify version information with *

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Revision and Build Numbers 
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

I changed it to this:

[assembly: AssemblyVersion("1.0.*.*")]
[assembly: AssemblyFileVersion("1.0.*.*")]

and this is the error I get from the compiler:

error CS0647: Error emitting 'System.Reflection.AssemblyVersionAttribute' attribute -- 'The version specified '1.0.*.*' is invalid'
warning CS1607: Assembly generation -- The version '1.0.*.*' specified for the 'file version' is not in the normal 'major.minor.build.revision' format

How does (does it even?) it work?

Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
mare
  • 13,033
  • 24
  • 102
  • 191

5 Answers5

75

Syntax (see MSDN) for "automatic" build number can be:

[assembly: AssemblyVersion("1.0.0.*")]

or:

[assembly: AssemblyVersion("1.0.*")]

* means after this everything is automatic. You can't have automatic build number and fixed revision number then this syntax isn't correct:

[assembly: AssemblyVersion("1.0.*.0")]

For the AssemblyFileVersionAttribute you cannot use the * special character so you have to provide a full and valid version number. Please note that if you do not provide an AssemblyFileVersionAttribute then you'll get the right FileVersionInfo automatically (with the same version of AssemblyVersionAttribute). You need to specify that attribute only if you need to set a different version.

Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • 5
    Doesn't work for me. The file version on the DLL is always 1.0.0.0 and the product version on the DLL is either 1.0.* or 1.0.0.* ? – mare Apr 19 '12 at 15:05
  • 1
    what about , it also shows same invalid error – shyamnathan Jan 24 '14 at 19:43
  • 1
    @shyamnathan yes, each part must be a 16 bit unsigned integer - 1 so you can't use anything else than `*` (and only in `x.y.*` or `x.y.z.*` form). Of course unless it's kind of placeholder and you apply some sort of preprocessing (useful if you do not have a shared assembly info and you want to keep version aligned across different assemblies). Error message is pretty generic, any invalid version number will give that message whichever is the reason. – Adriano Repetti Jan 24 '14 at 20:10
  • and the assembly file version does not show any errors, guess I'll stick to 2.0.0.* for assembly version and 2.0.0 for assembly file version which doesn't show any errors and thank you. – shyamnathan Jan 24 '14 at 20:26
  • It might be worth noting that it does not auto increment *by one* with every build as you might expect, but makes some numbers up (random? time dependent?) -- so you can just use it to tell versions apart, but not to tell which is the most recent build (at least not at first glance) – Tommy Mar 06 '14 at 13:52
  • 5
    @Tommy in form X.Y.Z.* build number is random, in form X.Y.* revision is number of days from a reference date and build is number of seconds from midnight. – Adriano Repetti Mar 06 '14 at 14:02
33
[assembly: AssemblyVersion("1.0.*")] 
//[assembly: AssemblyFileVersion("1.0.*")] 

just remember to comment the AssemblyFileVersion line, otherwise the automatically generated assembly version will always be "1.0.0.0".

chamos
  • 331
  • 2
  • 3
  • the automatically generated assembly version will always be "1.0.0.0", this happens to my solution. – chamos Apr 19 '12 at 14:37
  • Let me suggest that you `edit` your answer and add that information as well. "it may not work as expected" does not exactly explain why the OP should follow this suggestion, compared to the answer that [Adriano](http://stackoverflow.com/a/10229738/238902) gave. – default Apr 19 '12 at 14:47
  • 5
    yes, commenting out the second line was required in my case too for the autonumbering to work – mare Apr 19 '12 at 15:11
  • 2
    In VS2010 and prior versions, attribute `AssemblyFileVersion` does *not* support wildcards. If `AssemblyFileVersion` is *not* explicitly set, it takes its value from the `AssemblyVersion` attribute. See [this answer](http://stackoverflow.com/a/15506131/1497596) for more details. – DavidRR Oct 29 '14 at 20:18
11

So why does the supplied comment say

// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.0.0")]

but builds generate CS8357? Somebody didn't get the memo.

Work around:

 1. Close all open documents
 2. In the Solution Explorer, right-click the Project and select Unload Project
 3. In the Solution Explorer, right-click the Project (now marked as unavailable) and select Edit to access the `.CSPROJ` file
 4. In the opened window, find `<Deterministic>true</Deterministic>` and change it to `<Deterministic>false</Deterministic>`
 5. Save the file and ensure that the edit window is closed
 6. In the Solution Explorer, right-click the Project and select Reload Project

Your build (should then) work. :)
We B Martians
  • 367
  • 2
  • 12
6

In my opinion, using [assembly: AssemblyVersion("x.y.z.*")], Patch shouldn't be automatically numbered. Eg:

[assembly: AssemblyVersion("1.2.3.*")]

Using '*' in AssemblyVersion is good, but follow seemver.org we should use * for the revision part from version structure <major version>.<minor version>.<build number>.<revision>).

Given a version number MAJOR.MINOR.PATCH, increment the:

MAJOR version when you make incompatible API changes,

MINOR version when you add functionality in a backwards-compatible manner, and

PATCH version when you make backwards-compatible bug fixes.

fred
  • 693
  • 1
  • 7
  • 19
  • That format is no good. [The auto generated revision number is defined as the number of seconds since midnight, divided by 2.](https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assemblyversionattribute?redirectedfrom=MSDN&view=netframework-4.8#remarks) So if you happen to build your assembly earlier in the day than the last time, you will actually decrease the revision number. – Joakim M. H. Aug 23 '19 at 08:39
0

I have using the '*' in the version to an easy control version, and for information to the customers. I have a small program that run in handhelds(PointOfSell), sometimes update happen. :-) In my code, I use:

Fragment from AssemblyInfo.cs

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers 
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.*")]
// Need to comment this line, 
//[assembly: AssemblyFileVersion("1.0.0.0")]
//to avoid the following error:
// ...\Properties\AssemblyInfo.cs(36,32,36,39):
// warning CS7035: The specified version string does not conform to 
// the recommended format - major.minor.build.revision
// warning AL1053: The version '1.0.*' specified for 
// the 'file version' is not in the normal 'major.minor.build.revision' format

When check for update, I send a list of Version to client from a small web service.

void smsReceive1_OnCabUpdate(object sender, CabDataEventArgs e)
{
    try
    {
        var cabVer = e.CabVersion;
        var sms1 = (SmsService.SmsService)sender;
        SmsService.CabinetVersion progVer = null;
        var exeApp = Path.GetFileName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
        foreach (var item in cabVer)
        {
            if (string.Compare(item.FileName, exeApp, true) == 0)
            {
                progVer = item;
                break;
            }
        }

        var msgForm = new MessageBoxForm();
        if (!forceUpdate && !WillUpdateVersion(progVer))
        {
            Buzzer.Warning();
            sms1.StopReceive();
            msgForm.Message = "\r\nNewest Version!\r\n" +
                "Version\r\n" + progVer.AssemblyVersion.ToString() + "\r\n" +
                "Last Modified:\r\n" + progVer.AssemblyVersion.ToDateTime().ToString("yy/MM/dd HH:mm") + "\r\n" +
                "\r\nNo need to update";
            msgForm.OKShowDialog();
            return;
        }
        // 
        byte[] buffer = e.CabData;
        var filename = "\\ramdisk\\Setup.cab";
        if (File.Exists(filename))
        {
            File.Move(filename, string.Format("{0:yyMMdd_HHmmss}_Setup.cab"));
        }
        var fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
        fs.Write(buffer, 0, buffer.Length);
        fs.Flush();
        fs.Close();
        //
        Buzzer.Warning();
        //Stop SmsReceive
        sms1.StopReceive();
        msgForm.Message = "There is an update.\r\n" +
            "Version \r\n" + progVer.AssemblyVersion.ToString() + "\r\n" +
            "Last Modified:\r\n" + progVer.AssemblyVersion.ToDateTime().ToString("yy/MM/dd HH:mm") + "\r\n" +
            "※After the update\r\nIt will restart automatically";
        msgForm.SetSubMessage("Do you want to update?");
        var resp = msgForm.OKCancelShowDialog(true) == DialogResult.OK;
        if (resp)
        {
            CabFileUpdatePath = filename;
            UpdateApplication = true;
            Invoke((Action)(() => restartApplicationTimer.Enabled = true));
        }
        else
        {
            File.Delete(filename);
        }
    }
    finally
    {
        if (smsReceive1 != null) smsReceive1.ServicePaused = ServiceStatus.None;
    }
}

private bool WillUpdateVersion(SmartShooter.SmsService.CabinetVersion ver)
{
    var appVer = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
    if (ver.CompareToExe(appVer) > 0) return true;
    return false;
}

progVer.AssemblyVersion.ToDateTime().ToString("yy/MM/dd HH:mm")

Finally, this the reason because I have using ’*’ in the version.

public partial class MyVersion {
    
    public ushort Build { get; set; }
    
    public ushort Major { get; set; }
    
    public ushort Minor { get; set; }
    
    public ushort Revision { get; set; }
    

    public override string ToString()
    {
        return string.Format("{0}.{1}.{2}.{3}", Major, Minor, Build, Revision);
    }

    public DateTime ToDateTime()
    { 
        var dt = new DateTime(2000, 1, 1, 0, 0, 0);
        //plus days
        dt = dt.AddDays(Build);
        //plus seconds
        dt = dt.AddSeconds(Revision * 2);
        return dt;
    }
}

I use 'Build' value to find the day that the project is compiled, and 'Revision' to get the precise hour.

antonio
  • 548
  • 8
  • 16