Assembly version ".001" becomes ".1" - c#

In WinForms I have an AssemblVersion
[assembly: AssemblyVersion("01.01.01.002")]
However when the splash screen comes up it completely ignores the zeros showing:
1.1.1.2
as the version which is very inconvenient since later I will actually want to have an assembly version
[assembly: AssemblyVersion("01.01.01.200")]
Is there a way to avoid this or do I Have to add some number at the beginning of last part of the version like so:
[assembly: AssemblyVersion("01.01.01.102")]

The AssemblyVersion attribute stores it's information as a Version object. The components of the Version struct are integers, and are treated as such. So 1.2.3.4 == 1.02.003.004 but 1.2.3.4 != 1.2.3.400
You can use the AssemblyInformationalVersionAttribute to provide aditional, arbitrarily formatted information about your product, as it's information is stored as a string, rather than a Version. So you can do:
[assembly: AssemblyVersion("1.1.1.102")]
[assembly: AssemblyInformationalVersion("v.01 alpha")]
Or whatever you like

Related

C# Two strings, visually the same, yet they are not Equal nor Equivalent

I have a strange situation I can't figure out.
I am using a third party conversion framework which is expecting units in abbreviated form e.g. "μV" which is MicroVolts
But when I go to parse the string "μV" as MicroVolts it fails.
I boiled it down to the fact the abbreviation string I pass in is not equal to the string the third party framework is using for Microvolts, even though they look identical.
Here is the output of the Immediate window, to help shed some light on the context:
targetUom
"µV"
targetUom.GetHashCode()
-837503221
"μV".GetHashCode()
-837502956
targetUom.Equals("µV") // This is using the value of targetUom
true
targetUom.Equals("μV") // This is using the value from the 3rd party framework
false
I have obtained the value used in the third party framework by debugging and copying the value of the abbreviation I know they use for MicroVolts.
Any idea why two strings, even though the look to be made up of the exact same characters, would not be considered equal?
I've also compared the first character, the micro unit representation, between the two strings which yields:
'μ'.CompareTo(targetUom[0])
775
*********** UPDATE ****************
So I've found that the two micro characters are different encodings.
But when i attempt to use the same encoding that the target framework uses, Visual Studio gives me this message:
What are the implication of changing the encoding of the file..should I be doing this or should i collaborate with the framework author to enable their framework to handle both encodings?
Turns out there are two unicode characters which are probably identical in most fonts:
Greek small letter mu, U+03BC
Micro sign, U+00B5
You can access them both in strings using the \u escape:
Console.WriteLine("Greek small letter mu: \u03bc");
Console.WriteLine("Micro sign: \u00b5");

Semantic versioning in WPF projects

We are starting to use semantic versioning for some of our projects here, and are struggling to incorporate it into the .NET world. Semantic versioning seems to use 3 digits, a major, minor and patch. WPF projects in .NET use 4 digits.
When printing the version using the Assembly.GetExecutingAssembly().GetName().Version property the program will obviously return 4 digits and we would like only 3. Is there any way to achieve this? We want support for semantic versioning in our projects. I've tried just deleting the fourth digit in the Assembly Information, and although it does allow me to delete it, the Version property will always print that 4th digit. What can I do?
I use this method in my WPF applications (although its for the fileversion rather than the assembly version - I always have these the same in my small projects):
public static string ReturnApplicationVersion()
{
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
string versionMajor = fvi.ProductMajorPart.ToString();
string versionMinor = fvi.ProductMinorPart.ToString();
string versionBuild = fvi.ProductBuildPart.ToString();
string versionPrivate = fvi.ProductPrivatePart.ToString();
string fVersion = fvi.FileVersion;
return versionMajor + "." + versionMinor + "." + versionBuild + "." + versionPrivate;
}
You can easily modify it to return just 3 numbers. If you absolutely have to have the assembly version rather than the fileversion then perhaps someone else can help.
According to MSDN the way that versioning in .NET works is Major.Minor.Build.Revision. You can do this without defining a revision, but note that in C#, if the revision is undefined Version#Revision will return -1. If you are using the .NET Framework it is likely worthwhile to follow their semantic versioning principles.

Dollar ($) character used in resource.GetObject

I just spotted this line in an old Windows Forms app (created by the designer):
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
it seems to be using ResourceManager.GetObject() in order to get the icon. My question is regarding the significance of the $ prefixing this. There is no mention of the dollar symbol in the docs.
Does the dollar have a special meaning (reflection possibly?) or merely just to do with the implementation of GetObject()?
In addition where is the icon actually stored?
This is a pretty standard trick used in .NET, the compiler uses it too when it needs to generate a name for a auto-generated class or field. Using a character like $ ensures that there can never be a name collision with an identifier in the program.
There isn't much chance of that when you only program in C#, this is a keyword. But certainly in other languages. You could for example create a VB.NET Winforms project, drop a button on the form and name it "this". When you localize the form, the button's Text property source appears as:
<data name="this.Text" xml:space="preserve">
<value>Button1</value>
</data>
That would be a name collision with the form's Text property resource if it didn't put the $ in front of it. Not until you program in a language that permits $ in an identifier name anyway. None of the standard VS languages do.
Yet another detail is that you'll have trouble referencing that button from C# code. There's an escape hatch for that as well, you can use #this in your code. The # prefix makes sure that the compiler doesn't recognize it as a keyword but just a plain identifier.
The WinForms designer actually dumps quite a bit of hidden items like this into the resource file (.resx) assocaited with each form in order to support, mostly, internationalization (though other designer meta-data is there as well). While text and icons may be obvious, even layout information can be there. I suppose those German words are pretty long so when internationalizaing the form you may actually need to change label widths.
The $ I would assume is a way to make sure the designer-added resources don't conflict with user resources.
It turns out that the icon is stored within the corresponding .resx file and was actually defined with the dollar prefix $this.Icon. This would imply that the dollar doesn't have a special meaning at all.

How do I display only the class name in doxygen class diagrams?

Using doxygen and graphviz with my C# project, I can generate class diagrams in the documentation pages. These diagrams have the full class names and namespaces in them, e.g.
Acme.MyProduct.MyClasses.MyClass
Is it possible to configure doxygen to cut this down a bit to just the class name?
MyClass
The fully qualified paths make even simple diagrams rather wide and unwieldy. I'd like to minimize the need for horizontal scrolling.
I suspect that you've already solved this as it is a year old, but an answer might be useful for anyone else searching for this (as I just did). You can use the "HIDE_SCOPE_NAMES" option. Setting it to YES (or checking it in the doxywizard GUI) will hide namespaces. From my doxygen file:
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = YES
The HIDE_SCOPE_NAMES works great but only hides the scope in the class diagram but not the caller/callee graphs for each method.
To reduce the width of those diagrams to a readable size you can rename the scope using the input filter. This will not remove the namespace but will reduce it to a more readable width.
For example to rename the namespace "COMPANY_NAMESPACE" to "sf" use:
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output. If FILTER_PATTERNS is specified, this tag will be
# ignored.
INPUT_FILTER = "sed 's,COMPANY_NAMESPACE,sf,'"

put build date in about box

I have a C# WinForms app with an About box. I am putting the version number in the about box using:
FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location)
.FileVersion
This ends up giving me the Subversion revision number from which the executable was built.
I would also like to get the date of the build into the About box. I tried:
File.GetLastWriteTime(Assembly.GetEntryAssembly().Location)
But that gives me the write date of the executable, which only corresponds to the date when the app was installed (we are using ClickOnce) not built.
How can I get the build date?
If you use automatic versioning, you can convert the last two bits of the version number into a build date: MSDN
We're using this very similiar piece of code:
DateTime buildDate = new FileInfo(Assembly.GetExecutingAssembly().Location).LastWriteTime;
and I'm pretty sure it doesn't change when installing from ClickOnce.. If I'm wrong please correct me!
You could change your assembly versioning to encode the date, but that would probably mean losing your subversion revision information which is arguably more useful.
This should work: write the current date/time into a .cs file as a pre-build task like so:
[assembly: AssemblyCreated(CreatedDate = new DateTime(...))]
You could use a batch file, PowerShell script or executable for that.
Include the file in your project (build action: compile) and include the custom attribute:
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public sealed class AssemblyCreatedAttribute : Attribute
{
public DateTime CreatedDate { get; set; }
}
On application start you can use reflection to get the custom attribute from the assembly for display in the about page.
The only way i was able to do it in C/C++ was to actually have a post-build process do a search and replace of a special string allocated as a "static const" in the binary.
There might be an easier way in c# though.
I don't think a standard way of doing it exists, but you can roll something up yourself. Create a custom assembly-level attribute, give it a cool name like 'AssemblyDateAttribute'. Let it take a string that you can parse into a DateTime in the constructor that is accessible via a property.
As part of a build process, create a new file with only the attribute being applied to the assembly. (Make it look like AssemblyInfo.cs) and then include that in your build input.
Then in your about box, search your assembly for instances of this attribute and display the date value in your box.
In Visual Studio projects there is a file AssemblyInfo.cs, but you can use any other .cs file. Look at the attribute AssemblyVersion:
// 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("2.0.*")]
Now you can calculate the build date by using the Version.Build property. The value that Version.Build returns is the number of days since: 2000/1/1
Assembly.GetExecutingAssembly().GetName().Version.ToString();
From my own C# code.

Categories