C# Application - Custom Assembly Version Format - c#

Bit of an odd one maybe, but currently looking into if it is possible to implement a custom format for the Assembly Information for a project.
In the Assembly information you are given the option of a 4 number system, so major.minor.build.revision
I have been asked to try and change this to a 5 number system, so something like 1.2.34.556.1234 and wondering whether this is even possible.
I have simply tried just modifying it programmatically, but that just returns the error:
Error emitting 'System.Reflection.AssemblyVersionAttribute' attribute -- 'The version specified '1.2.34.556.1234' is invalid'

For that purpose, I prefer using the AssemblyFileVersion instead of the AssemblyVersion.
The former has an open format and can accommodate virtually any additional information, whereas the latter, AssmeblyVersion is intended for use by the .NET framework and enforces a strict numbering scheme that yields compiler errors if infracted.
[assembly: AssemblyVersion("4.0.*")] //Strict Format, for framework use
[assembly: AssemblyFileVersion("4.0.20.110708")] //Flexible Format more suitable for product versions
Update:
Per OP comment, here is how one can access this attribute easily via reflection:
Assembly assembly = Assembly.GetExecutingAssembly();
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
string version = fvi.FileVersion;

This will not work because the constructor for AssemblyVersionAttribute takes up to 4 values in the string.:
The format of the version string is: major. minor. build. revision.
MSDN Link

AssemblyVersionAttribute is converted to the Version class.
It has only the major,minor,build,revision number: you cannot use 5 numbers.
If you want to use more numbers you can use the AssemblyInformationalVersion
It is not a Version Class but a string for a more descriptive assembly versioning:
[assembly: AssemblyInformationalVersion("1.12.0.3050.1234 Release - Any CPU")]
But you should provide anyway AssemblyVersion and/or AssemblyFileVersion without the 5th number

Related

AssemblyInformationalVersion attribute behaviour change: deliberate or a bug?

In a C# project built with VS2013, I could put this in the AssemblyInfo.cs file:
[assembly: AssemblyInformationalVersion("7.1.0.0 Private (Debug build)")]
When I used the FileVersionInfo.GetVersionInfo .NET API against the executable from within another project, I found these values reported:
Product version: 7.1.0.0 Private (Debug build)
ProductMajorPart: 7
ProductMinorPart: 1
When I use the same attribute and string value in a C# project built with VS2015, the ProductMajorPart and ProductMinorPart properties are reported as zero!
Does anyone know if the behaviour change is intentional?
I have examined the binary file version information found within the executables, and whilst the string values within the version information are as expected in both files, the VS2015 executable has zero values within the VS_FIXEDFILEINFO.dwProductVersionMS and VS_FIXEDFILEINFO.dwProductVersionLS fields.
I can confirm the change in behavior for this case, with the observation that if the AssemblyInformationalVersion is in canonical format, for example "7.1.0.0" then it works as expected in all versions i.e. the Product version major/minor/build/revision fields are filled in.
For background, the docs for AssemblyInformationalVersion do in fact specify that:
The attribute defined by this class attaches additional version information to an assembly. If this attribute is applied to an assembly, the string it specifies can be obtained at run time by using the Application.ProductVersion property.
[...] Although you can specify any text, a warning message appears on compilation if the string is not in the format used by the assembly version number [...]
From the above:
there is no formal guarantee other than that the string itself can be retrieved;
there is a warning against using free-format strings.
You may, or even should, file a bug report on VS connect though my feeling is that MS sees free-format strings in AssemblyInformationalVersion as an unsupported "accidental" feature, and might not consider a change in undocumented behavior to be a "bug" proper.
Not directly related, but this VS 2010 bug report Localized build with free form AssemblyInformationalVersion causes ALINK warning AL1053 has been closed by MS as won't fix.
Also the accepted answer at Why is warning CS1607 “The version specified for the 'product version' is not in the normal 'major.minor.build.revision' format” generated? basically advises that once you deviate from the standard major.minor.build.revision format, you are pretty much on your own.

C# AssemblyVersion 3 digits for use with NuGet's PreRelease versioning

In AssemblyInfo.cs:
[assembly: AssemblyVersion("1.0.*")]
Will generates a 1.0.x.x four digits version number.
Which, if I use this nuspec metadata:
<version>$version$-test</version>
generates an error when packing:
The version « 1.0.5431.31092-test » does not follow semantic version control instructions
Is there a simple way around this?
Not possible, an assembly's version is stored in the System.Version class, that consists of Major, Minor, Build and Revision.
EDIT: I was a bit to hasty to answer. When you use the AssemblyVersionAttribute's constructor with a string containing an asterix, all four properties of a version will be generated. The only way to cause a version with lesser numbers is to specify the exact version number, without asterix, i.e "1.0.1". See: http://msdn.microsoft.com/en-us/library/system.reflection.assemblyversionattribute.assemblyversionattribute(v=vs.110).aspx
What you could do, if you want lesser numbers in the version and also generated version numbers, is to use an external tool altering version numbers in the pre-build step.
No post processing is necessary, NuGet is using [assembly: AssemblyInformationalVersion("")] as a package version, set it to whatever number of componets you please and be done with it.
P.S I strongly encourage you to also set AssemblyVersion as this is the one .NET actually uses, at least set it to auto increment
Some reading available here
Full example
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyInformationalVersion("1.0")]
Will generate a package Lib.1.0.nupkg containing assembly with 1.0.x.x version, version you will be dealing with is 1.0
Whenever you want to change nuget version, just change AssemblyInformationalVersion, not touch AssemblyVersion at all

Fixed Assembly Version with Auto Incremented File Version?

I'm trying to find a more meaningful way to handle versioning for my app and I came acrossed this KB article
http://support.microsoft.com/kb/556041
Basically it's recommending that the Assembly version be fixed, and the File Version be imcremented for each build. Now this makes perfect sense to me but for the life of me I can't seem to implement it.
The below snippet auto increments both Assembly version and FileVersion.
[assembly: AssemblyVersion("1.0.*")]
While this next one seems to set a fixed Assembly version of 1.0.0.0 and a fixed File Version of 1.0.*.
[assembly: AssemblyVersion("1.0")]
[assembly: AssemblyFileVersion("1.0.*")]
Incidentally, the Product Version in Details tab of the file properties reads 1.0.* now as well. Now I can fix the Product Version in the file properties with this...
[assembly: AssemblyInformationalVersion("1.0")]
But that doesn't help with my original task. Out of curiosity I tried the below and the File version changed to 2.0.*, so it is at least using it. It's just not auto incrementing.
[assembly: AssemblyVersion("1.0")]
[assembly: AssemblyFileVersion("2.0.*")]
So from what I can gather the only version number that auto increments is the Assembly Version, but on the off chance you haven't specified a File Version it gets set to the same as the Assembly Version.
Does anyone know of a way to auto increment the File Version while leaving the Assembly Version fixed?
Yes it's a bit silly, Microsoft seems to have got it the wrong way round. AssemblyVersion is used in the .NET assembly versioning system, so you should never auto-increment it, but AssemblyFileVersion is written to the file version entry in the file's version resource, so you might reasonably expect it to always auto-increment by default.
I'm sure that there are some 3rd party build systems out there that can do this for you, but I just wrote a little command line C# app to do it, and it gets run on every project as part of our build process. It's very straightforward:
Read the AssemblyInfo.cs file line by line.
Do a RegEx search for the AssemblyFileVersion line, capturing all four version parts into separate capture groups. You could parse it yourself, but a regex will do all the detecting and parsing in one go, so it seems silly not to take advantage.
Once you have the four integers, implement your own incrementing logic as you see fit.

.NET 4.0 to 3.0 could not find any resources appropriate for the specified culture or the neutral culture

I found a free program on the web that was .NET 4.0, but had to copy over the code to compile VS2008. I'm thinking the way cultures is handled must be different in the versions of .NET.
I'm getting this error:
System.Resources.MissingManifestResourceException: Could not find any
resources appropriate for the specified culture or the neutral
culture. Make sure "A.B.C.Resources.ExceptionMessage.resources" was
correctly embedded or linked into assembly "A.B.C.csproj" at compile
time, or that all the satellite assemblies required are loadable and
fully signed.
It's a C# .dll (class library), and I'm calling it from a Console Program.
It does have a strong-key file assigned to it.
It's blowing up on any statement like this:
return ResourceManager.GetString("XYZ");
It looks like all the resources are in English, and that's the only language I need.
I'm just looking for how to avoid the exception.
When I copied over files, and rebuilt a new VS2008 project, there was no hierarchical relationship in Visual Studio Solution Explorer for the resource file. For example, ExceptionMessage.resx and ExceptionMessage.Designer.cs were at the same level; whereas normally the Designer.cs file is indented under the .resx file. I'm not sure what that happened.
So what I did was create a new .resx file, and carefully copy over using NotePad and filemerge programs, pieces of the .resx file and .cs file. Then it worked fine.
I'm still not absolutely sure what the problem was, but I know this fixed it. Lost about 5 hours today on this issue.
It might be worth to compare the [assembly: AssemblyCulture("")] properties in the assemblies from both your version 4 and version 3 solutions.
The default is - I think - none.
MSDN documentation:
Putting this attribute on an assembly and using something other than
the empty string ("") for the culture name will make this assembly
look like a satellite assembly, [...]
Perhaps you need to define it explicitly OR it already is defined but should not be?
I've had this difficulty and found that the cause had to do with Assembly name and Default namespace from project properties. It helps to set them both the same, or something to that effect.

Can i specify the module version id (MVID) when building a .net assembly?

We have some shared assemblies that get build automatically every night. When there are no changes made to the sources, i would expect the assembly binaries to be exactly the same as a previous version.
However, there seem to be minor differences between assemblies.
I have done some effort to determine the difference between two builds. I used ildasm to generate an il version, and compared the resulting text versions. The only difference (in IL) is the MVID (a random guid) in the module.
Some googling tells me that the module version id gets generated by the compiler, so it is possible to determine the build source, even when everything else is the same.
This MVID creates an artificial diff betweeen builds of the same code, and an artificial checkin of the resulting assembly.
Is it possible to supply the MVID to the C# compiler?
The ECMA-335 standard says:
The MVID is a Guid used to distinguish
between two versions of the same
module
Based on this description, supplying this is an argument to C# compiler will defeat it's purpose since you can pass the same MVID for different builds so I would say No.
I think the easier way would be to build only when something changes not necessarily every night.
I realize this is a 5 year old question, but I made a Fody addin that allows you to specify a custom MVID for an assembly (needed for my own tests)
You can get it via nuget:
Install-Package Mvid.Fody
You can then specify a custom MVID like this:
[assembly: Mvid("your-guid-string-here")]
When the assembly compiles, it will have an MVID with the Guid you specified.
More info here: https://github.com/hmemcpy/Mvid.Fody

Categories

Resources