AssemblyInformationalVersion attribute behaviour change: deliberate or a bug? - c#

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.

Related

C# Application - Custom Assembly Version Format

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

Assemblies and Little More In C# (part 1)

If you go to:
Solution Explorer -- > Properties -- >(double click) Assembly Info
you will see some information about assemblies for your project. At the end of it there are some different versions for each assemblies that they are:
Major Version
Minor Version
Build Number
Revision
And I Understood that These are numbers of these:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
but I don't understand the meaning.
When the project is built those values are baked into the dll so that when you view the dll's properties via the Windows File System you will see that version number.
Managing those numbers is a bit of a pain in the ass. In older projects you'll often see some ugly build scripts that do things like check out the files then increment the number then check them in then continue with the build... The most elegant solution I've seen is implemented by TeamCity (though there are probably similar products); it basically copies all of the projects files to your build server, then it edits it's local copy with values it maintains (you can alter or reset them in UI), then builds the project. This allows it to never touch source control while giving you good control over dll versioning.
They are whatever you want them to mean. You are free to use your own definitions for each section of the version number; beyond the fact that different numbers are different, there is no functionality driven off of this by the language.
AssemblyVersion is used in the strong name of the assembly(signing).
AssemblyFileVersion is displayed by Windows in the Version tab on the file properties.
AssemblyInformationalVersion is used in the assembly manifest for things like NuGet.
As far as how to version, I recommend Semantic Versioning, which uses a 3-part version number:
Given a version number MAJOR.MINOR.PATCH, increment the:
1. MAJOR version when you make incompatible API changes,
2. MINOR version when you add functionality in a backwards-compatible manner, and
3. PATCH version when you make backwards-compatible bug fixes.
AssemblyVersion used for strong name of the assembly with sn.exe, but
AssemblyFileVersion display the version on the file properties.

.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.

Compile CSProj in Visual Studio with /CLR:Safe? Fatal Error LNK1302: only support linking safe .netmodules

So I am having an issue converting an opensource project (SQLite) to use a different build system and now I'm having trouble linking projects. Essentially I have a VCProj file that has a definition like this:
<Tool
Name="VCLinkerTool"
AdditionalOptions="/ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteCommand.bmp,System.Data.SQLite.SQLiteCommand.bmp
/ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteConnection.bmp,System.Data.SQLite.SQLiteConnection.bmp
/ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteDataAdapter.bmp,System.Data.SQLite.SQLiteDataAdapter.bmp"
AdditionalDependencies="..\System.Data.SQLite\bin\System.Data.SQLite.netmodule"
OutputFile="..\bin\System.Data.SQLite.DLL"
GenerateManifest="false"
IgnoreDefaultLibraryNames=""
ModuleDefinitionFile="src\sqlite3.def"
EmbedManagedResourceFile=""
DelayLoadDLLs="advapi32.dll"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=""
KeyFile="..\System.Data.SQLite\System.Data.SQLite.snk"
CLRUnmanagedCodeCheck="true"
/>
And I am unable to properly link the System.Data.SQLite.netmodule due to the following error:
Linking...
4>..\System.Data.SQLite\bin\System.Data.SQLite.netmodule : fatal error LNK1302: only support linking safe .netmodules; unable to link pure .netmodule
And the System.Data.SQLite.netmodule is generated from a C#/.NET project. How is it I can force it to compile with the /clr:safe option since according to MSDN this is the way to fix the issue. The problem is is that I don't know how to compile it with /clr:safe. How is it I can do that in the csproj file or in visual studio somewhere? If I am off base in my attempts to fix this please let me know a better way.
UPDATE:
So I have determined the issue but I'm not sure why it is an issue. So the interop project (the C project which compiles the sqlite code and links) uses the VCLinkerTool to link to the System.Data.SQLite.netmodule. There is then a C# project that creates the System.Data.SQLite.netmodule using the following command (Anything in {} was added to reduce length):
C:\Windows\Microsoft.NET\Framework\v3.5\Csc.exe /noconfig /unsafe- /nowarn:1701,1702 /platform:AnyCPU /errorreport:prompt /doc:..\bin\System.Data.SQLite.XML {DLL REFEERENCFES /debug- /filealign:512 /optimize+ /out:obj\Release\System.Data.SQLite.netmodule {RESOURCES AND CS FILES}
The problem is with the /platform:AnyCPU. In my build it is /platform:x86 and for some reason this causes issues when linking and I'm not sure why but this is what I have narrowed it down to since I can change it to AnyCPU and it will build and link properly. Any insight on this is appreciated.
Ok so I finally narrowed down what the issue was and maybe someone can spread some more light onto why that is but I have a rough idea why. Basically you can't have the VCLinkerTool link to .netmodules that were created targetting the /platform:x86 (and I assume any other variant that isn't AnyCpu. I would assume this has to do with the way that the linking occurs internally when linking the mixed mode dll with a .netmodule. So it looks like for this to work you have to have your C# project compiled with /platorm:AnyCpu.
This may be what you are looking for:
To set this compiler option in Visual Studio
1.
In Solution Explorer, right-click the project name, and then click Properties to open the project Property Pages dialog box.
2.
Select the Configuration Properties folder.
3.
On the General property page, modify the Common Language Runtime support property.
Note
When /clr is enabled in the Property Pages dialog box, compiler option properties that are not compatible with /clr are also adjusted, as required. For example, if /RTC is set and then /clr is enabled, /RTC will be turned off.
Also, when you debug a /clr application, set the Debugger Type property to Mixed or Managed only. For more information, see Project Settings for a C++ Debug Configuration.
For information about how the create a module, see /NOASSEMBLY (Create a MSIL Module).
You would have to edit the CSProj to not use features that cause the code to no longer be safe. These are easy to spot -- anywhere where you're using P/Invoke, or anywhere where there's an unsafe code block, that code is not safe. If any of the code in your assembly is unsafe, the whole assembly gets marked as unsafe.
If you remove the unsafe code the resultant assembly will automatically be safe.
(In the case of SQLite I believe this will be impossible, because SQLite is a C library, which cannot be compiled as safe)

C# .NET Application Crashes Immediately After Starting

I was experimenting with the Assembly and File version number. Though my program runs well from the IDE, but after creating a Setup file and installing the application crashes with InvalidDeploymentException.
What should I do to resolve the matter?
The [AssemblyVersion] and [AssemblyFileVersion] attributes play different roles. [AssemblyVersion] is only visible to managed code and is important for the GAC. Whenever a make a breaking change in the assembly's public interface you should bump this number up.
The compiler embeds an unmanaged resource in an assembly with the /win32res command line option. This includes the VERSIONINFO resource, readable by all unmanaged code, including the shell. It determines what you see when you right-click the assembly in Explorer and look at the Details property page. The "File version" value shown there is set by the [AssemblyFileVersion] attribute. The [AssemblyVersion] value isn't visible there, Explorer doesn't (yet) know how to read that.
It is up to you to decide how to use this attribute. The crash indicates that there's some minimum sanity checking going on in the deployment code, never tried to get it wrong myself to see what would happen. Making them the same would however make a lot of sense.
Microsoft uses [AssemblyFileVersion] a different way, they automatically increment it for each build and nail [AssemblyVersion] down. That's a good idea and the strategy I use. What is however quite ironic is that the automatic version increment feature works exactly backwards, it can only auto-increment [AssemblyVersion]. Sigh.
Try using the fusion log viewer to see what's not being loaded in your deployed app.

Categories

Resources