ProjectProperties->Signing vs AssemblyInfo

Sat, August 6, 2005, 05:54 AM under Whidbey | VisualStudio
This has been on my "to blog" list but, since someone else beat me to it, please go read: Visual Studio 2005 and Signing with strong name keys.

Why is there a warning against using the old way of signing in the AssemblyInfo.cs? When sharing code between Smart Device and desktop projects, we used to share the AssemblyInfo file. Now, to strong name both projects/assemblies, I need to do it via two different project properties dialogs rather than a single code file!
Note that VB projects seem more tolerant to using the AssemblyInfo.vb for this purpose.

In addition, there is another bug with Beta 2. Say you created a desktop project and added the strong name (resulting in the silly copying of the snk file to your project folder). Now you create a Smart Device project in the same folder and using *its* project properties try to add the snk file from its original location: VS2005 dies a horrible death! The workaround is to browse to the snk file that was copied in your project folder.

Project properties nuisance

Fri, August 5, 2005, 12:54 PM under Whidbey | VisualStudio
Nobody likes modal dialogs, but the Visual Studio.NET 2003 properties dialog is *not* modal.

Nevertheless, we prefer docked windows (apparently), so in Visual Studio 2005 the properties window is "inlined" in the main area as if it were a code file.

With this change we lost a great usability feature. Easiest way to describe this is an example:
1. Open a VS2003 solution with more than 1 project (e.g. 3 or 10)
2. Collapse them all [btw, when are we going to get a "Collapse all" in VS?!]
3. Select a project and choose Project Properties to show the popup window
4. Select "Common Properties" -> "References Path"
5. Change the value(s) (or verify it is what you want)
6. Without closing the dialog, select another project in the solution
7. See how the “project properties” updates for that project?
8. Go back to step 4 and select some other section of the Properties dialog
9. In solution explorer, use the keyboard up/down keys to quickly verify that a setting is the same for all projects

I use the above all the time (e.g. to quickly toggle Debug/Release constants, change default namespace etc). When you change project selection, if you have made changes, you get the prompt to save or discard changes (which is nice).

So how can I achieve the same with VS2005? That wasn't a rhetorical question... please tell me!

For all projects in a VS2005 solution, try to change the output path from bin\Debug to bin\DebugCF. Count the number of clicks/mouse movements and do the same for VS2003 in no time.

How irritating when a great product takes a step backwards...

...or maybe I should get out more ;)

How to upgrade VS2003 projects to VS2005

Thu, August 4, 2005, 01:04 PM under Whidbey | VisualStudio
If in Visual Studio 2005 you try to open a project created with Visual Studio .NET 2003, the conversion wizard appears. Apart from the option to backup the existing solution, there isn't much more to it other than clicking the "Finish" button. It basically takes the project file (which is v7.1 or v7.0) and converts it to VS2005 (v8.0); all code files (.vb or .cs) remain untouched.

When you install VS2005 you can quickly tell in your file explorer which solutions were created with which version of Visual Studio, check out this screenshot.

Note that if you double click on a 7.x *project* file in explorer, you will be presented with the upgrade wizard in VS2005, whereas doing the same for a 7.x *solution* file, correctly opens it in VS.NET 2003.

So I was upgrading some VB device projects with Beta 2 and noted a few subtle differences between the *upgraded* VS2005 projects and *new from scratch* VS2005 projects of the same type. The differences are easier observed by opening the project files in notepad (or an XML editor) and comparing them (you know of course about MSBuild).

For example, the upgraded project has a bunch of empty tags (which are not needed): ApplicationIcon, AssemblyKeyContainerName, AssemblyOriginatorKeyFile, AssemblyOriginatorKeyMode, StartupObject and PreBuildEvent/PostBuildEvent under PropertyGroup under FileUpgradeFlags. It also has a bunch of tags with default values (whereas new projects omit them) or tags that don't apply to NETCF projects: DelaySign, OptionCompare, OptionExplicit, OptionStrict, RegisterForComInterop, RemoveIntegerChecks, TreatWarningsAsErrors, WarningLevel and Name/Private under Reference Include under ItemGroup.

Newly created projects will have the new properties structure I described previously here. You can observe this in the new files in the text editor with tags such as: AutoGen/DesignTimeDependentUpon under Compile Include for Resources.Designer file. Also for tags such as: Generator/LastGenOutput/CustomToolNamespace under EmbeddedResource Include for Resources.resx file.

Sooo...

If you still wish to go down the upgrade wizard path for your VB device projects, here are my recommendations for your project properties window:
1. Select Option Strict On
2. Select “Error” as the Notification for all Conditions except "Use of variable prior to assignment"
3. Check "Treat all warnings as errors"
4. Check "Generate XML documentation file"
5. Go to "Advanced Compile Options". On the "Generate debug info" combo, select "Full" (at least for a debug configuration) DebugType
6. Go to references and remove unused ones (Unused References->Remove)
7. Uncheck assembly COM-Visible [unless you explicitly want it to be visible]
8. If you want AssemblyInfo in its own folder, create one in the project and move it there.

Alternatively, if you want clean projects following the new style:
a) Create a brand new project in VS2005 (of the same type as the one you will upgrade)
b) Delete the default code file (e.g. Form1 or Class1 etc)
c) Copy attributes from the old AssemblyInfo file to the new one as appropriate
d) Copy settings from the old project properties to the new one as appropriate
e) Add references to the new project to match the old ones
f) Deal with resx files as discussed here

Finally, and continuing from my last point above, it makes sense that you upgrade your projects (one way or the other) bottom up. In other words, start with your class library that references nothing but framework assemblies and work the projects up to your Application (the exe). Note that VS2005 will allow you to reference assemblies built against v1 of the framework! So be sure you are referencing *upgraded* dlls and not the original/old ones.

AssemblyInfo 1.0.* -> 1.0.0.0

Wed, August 3, 2005, 09:24 AM under Whidbey | VisualStudio
In VS2005 the version number does not default to "1.0.*" like it does with VS.NET 2003. Instead it starts off with more sensible "1.0.0.0". You can check this for yourself by examining the AssemblyInfo file (or through the project properties and the "Assembly Information" button).

However, I would prefer a checkbox on the dialog (or a wildcard character in the file) that would result in auto-incrementing the revision part of the version. This is exactly what VS2005 offers for ClickOnce application and you can see that for yourselves by navigating to the "Publish" of the project properties dialog ("Automatically increment revision with each publish").

To be perfectly honest, what I would really like is to pass to the AssemblyVersion attribute the following parameter "1.0.*.0". I would then expect the build part of the version number to increment by one every day as it does now, to indicate the number of days since January 1st 2000. Alas, we cannot add anything after the *... maybe in Orcas!

Another use of partial types

Tue, August 2, 2005, 04:03 PM under Whidbey | VisualStudio
We've looked at partial types before but what use are they?

Their primary use is for code generation tools. The main/best example is the windows forms designer which uses them for splitting the designer code from the code we (the developers) write. I think that code generation will play an even larger part in every day development as years go by but that is another story...

Another use could be to split a class in privates and publics. So one file has all the (private) fields and private methods while the other has all the members that are externally callable.

You can take the previous idea too far and have a file per member category i.e. one for fields, one for methods, one for properties and one for events (or even another for internal types such as structs/classes/delegates).

If a class implements an interface (or many), why not split the interface implementation into its own file...

Some might even split a class into files according to the areas that different developers are working on (thus assisting with source control check ins/outs).

Finally, if you find yourself declaring your own code regions in VS.NET 2003, consider whether you can extract them into their own file using partial classes.

I am not advocating any of the above but I am not being a purist against it either. For the record, I do believe that classes should be controlled from growing too large; objects should be designed to do one thing only and do it well.

Recently I discovered another reason. A few years back, when I migrated a whole bunch of dotnet code to the compact framework, I came across types that while designed to do one thing only, they had a fatter interface than what appropriate for an embedded platform (and some of their members were simply not applicable to windows ce). There were a number of approaches I took depending on the situation:
1. "Carry" the extra class members but not call them
2. Conditionally compile parts of the class for the NETCF (or vice versa)
3. From a single class, extract a base abstract class and two specialisations (each in their own file). In the Smart Device Project I only use two files out of the three (the base class and only the one subclass that is applicable).

It is obvious where this is going, isn't it? :-)

A 4th option with Visual Studio 2005 is to use partial classes and thus exclude the files you don't want from one of the projects. One more support option for sharing projects between the two platforms.

Resx compatibility for Smart Device projects

Mon, August 1, 2005, 04:05 PM under MobileAndEmbedded
The punchline is that with VS2005 there is no more incompatibility for resource files (resx) between the compact and full frameworks!

To quote from my post on writing cross-platform code with VS.NET 2003:
"Trying to share the form code would effectively mean not using the designer at all."

This statement is no longer true with VS2005. You can follow the steps for sharing code files (as described in that blog entry) for forms as well. You may still prefer not to share forms between the two platforms but at least it will be technically possible now.

A side effect is that we no longer need cfresgen (as previously mentioned here) and instead we can use resgen (for both platforms).

Another side effect of this improvement is that existing resx files you have that work in your cf v1.0 projects, cannot be added to VS2005 projects. They have to go through the upgrade wizard. So although you have been told that the VS2005 upgrade wizard only affects solution and project files and nothing else, now you know that it also affects resx files; even though the (Beta 2) conversion report does not indicate that!

Overall, good stuff from the VSD team (and in this particular case, Xin Yan).

Boxing

Sun, July 31, 2005, 04:06 PM under dotNET
If I am interviewing you for a dotnet position and I ask you about boxing I expect you to be able to quickly describe what it is, why one should care and give me a quick example. If I see you struggle, I'll help you by asking "If I add an integer to an ArrayList, does boxing occur?". If you hesitate answering that then... [this really happened recently when I interviewed someone for a senior .NET position].

So it was with pleasure that I saw a post on boxing this week. If you are struggling with the concept go read Raymond Lewallen's Boxing and Unboxing for Beginners.

I don't really have anything to add to that post other than a couple of comments on the Intermediate Language:
1. Note the IL instruction box. That is where boxing gets its name (should be obvious but thought I'd spell it out :-)
2. Raymond's example uses VB and unfortunately has Option Strict Off. If it had Option Strict On, you'd see that when you retrieve the result you have to cast it to the integer
i.e. b = DirectCast(a(0), Int32)

If you make that modification, then you see the other magic IL instruction: unbox (rather than the *really* ugly VB-compiler-injected-statement:
[Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.IntegerType::FromObject(object)).

Here is the IL with that small modification for VB in VS.NET 2003 (note that it is compiled in Release mode so we get cleaner IL):
.method public instance void  Method1() cil managed
{
// Code size 39 (0x27)
.maxstack 2
.locals init (class [mscorlib]System.Collections.ArrayList V_0,
int32 V_1)
IL_0000: newobj instance void [mscorlib]System.Collections.ArrayList::.ctor()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldc.i4.s 10
IL_0009: box [mscorlib]System.Int32
IL_000e: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
IL_0013: pop
IL_0014: ldloc.0
IL_0015: ldc.i4.0
IL_0016: callvirt instance object [mscorlib]System.Collections.ArrayList::get_Item(int32)
IL_001b: unbox [mscorlib]System.Int32
IL_0020: ldobj [mscorlib]System.Int32
IL_0025: stloc.1
IL_0026: ret
} // end of method Form1::Method1
3. Just so you can see the IL for a C# version compiled under Visual Studio 2005 Beta 2, here is some code:
private ArrayList ar = new ArrayList();
public void Box() {
ar.Add(5);
}
public void Unbox() {
int i = (int)ar[0];
}
...and equivalent IL:
.method public hidebysig instance void  Box() cil managed
{
// Code size 19 (0x13)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.Collections.ArrayList BoxUnbox.Form1::ar
IL_0006: ldc.i4.5
IL_0007: box [mscorlib]System.Int32
IL_000c: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
IL_0011: pop
IL_0012: ret
} // end of method Form1::Box

.method public hidebysig instance void Unbox() cil managed
{
// Code size 19 (0x13)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.Collections.ArrayList BoxUnbox.Form1::ar
IL_0006: ldc.i4.0
IL_0007: callvirt instance object [mscorlib]System.Collections.ArrayList::get_Item(int32)
IL_000c: unbox.any [mscorlib]System.Int32
IL_0011: pop
IL_0012: ret
} // end of method Form1::Unbox
By the way, a great follow up to the above is to show how Generics eliminate the need for boxing in such a scenario pointing out that
a) No boxing/unboxing penalty takes place
b) No cast is required
c) Compiler prevents anyone adding objects of other types to our List

Blog link of the week 30

Sun, July 31, 2005, 02:00 PM under Links
"Thorough" doesn't begin to describe the coverage: Mouse Input and drag'n'drop.

Highlights of the performance enhancements in Whidbey

Generics Variance

Replies to some JIT questions

Notes and screenshots of longhorn client Windows Vista Beta 1

Visual Form Inheritance with netcf

Thu, July 28, 2005, 12:54 PM under MobileAndEmbedded
One of the features that devs got excited with when Visual Studio .NET 2002 launched, is Visual Form Inheritance. I have never used this feature in a commercial app but I guess I can see its appeal.

.NET Compact Framework v1.0 projects do not support Visual Form Inheritance in the designer (you cannot view the results of inheriting your form from another of your own forms). Specifically, if you attempt to directly inherit from anything other than System.Windows.Form, the winforms designer will not render your form's design surface. However, your application will still compile and execute with the visual inheritance correctly observed at run time.

With Visual Studio .NET 2003, you should do your design work before changing the parent of your form to be another form (i.e. do it while it still inherits from Form and the designer works). When you need the designer again, change your class to inherit from System.Windows.Forms.Form
public class Form4 
//: System.Windows.Forms.Form // Use this line for design time
: Form2 // Use this line for runtime

This has been discussed multiple time previously in the newsgroup archives e.g. here

So what is the story with v2.0 of the compact framework and Visual Studio 2005?

Start with a new Device Application with a single form and add some controls to it. If you navigate to "Project->Add New Item", the dialog does not include the "Inherited Form" template (in Beta 2). However, you can add a "Windows Form" and then change the code to achieve visual form inheritance. Here are the steps:

1. Create a new Smart Device Project
2. To the default Form1, add a button
3. Add a new form (Form2)
4. Delete the mainmenu from Form2
5. Go to the code and change it (Form2.cs) so it does not inherit from Form and instead inherits from Form1
6. Rebuild the solution
7. Open Form2 in the designer and observe how it shows button1

If you are using VB, make sure at step 5 you go to the Form2.Designer.vb (instead of the Form2.vb) - see my previous post on partial classes and how to get to the designer file.

Hopefully by RTM the VSD team will add the template so it will be even easier!

UPDATE: September 2005 - Visual Studio 2005 Release Candidate supports the "Inherited Form" template

Bye bye Lotus Notes

Wed, July 27, 2005, 03:38 PM under UserInterfaceDesign
If you haven't used it then I envy you. If you have, then you know as well as I do that Lotus Notes sucks. It deserved the dedicated pages on the Interface Hall of Shame (cannot find the URL right now).

It is easy for me to write a book on the topic but instead here are just a couple of screens I've personally faced that show the quality of the product (since the non user friendliness of it is well documented).

Over the past 6 years I've had this crappy waste of space app installed on two PCs here at home, a tower at work, an older laptop and my current laptop.

Finally, I have a computer in my possession (the tablet I mentioned earlier this month), which I am setting up and the Notes piece of sh1t will not go on it. Combined with the fact that I am changing jobs, this means that I am not going to meet with that abomination any time soon. Anyway, there may be kids reading so, I am going to hold off telling you how I *really* feel (or start talking about Planta PPMS)!