Tuesday, July 29, 2008
One of the coolest debugger features introduced in VS2005 was DataTips (grey editable, navigable tooltips on steroids that also become transparent when you hold down the Ctrl key). Did you know that you can get data tips for commented code? At first this made me raise an eyebrow, but I can see how for some piece of code I may always need to inspect some other variables quickly and do not want to have to enter them in the watch window manually or navigate to the required area from existing variables that do exist in code. Here is a screenshot that shows this feature in action:

Notice how the datatip appears after highlighting a variable that is in a commented area of the editor (my highlight is set to yellow).
Tip #2 – save output window
In Visual Studio many times we need to transfer the text from the Output window to an actual txt file. Dunno about you, but I always selected all (Ctrl+A), copied (Ctrl+C) and then pasted (Ctrl+V) into a notepad instance that I always have running (Alt+TAB). It turns out that there is a direct way of saving that output to a file. Simply hit Ctrl+S (or invoke it from the menu item) once you've given focus to the Output window – nice!
What cool debugger features do you like in Visual Studio (or would like to see)?
Labels: dot NET general
Tuesday, May 27, 2008

Back in 2004 I described what the class looks like (inc. links to MSDN) when I implemented it for the .NET Compact Framework v1.0/v2.0 (and for .NET Framework v1.1): BackgroundWorker. I also provided sample code to demonstrate the usage.
An added incentive to learn about it is that Silverlight 2 includes a fully interface-compatible version of BackgroundWorker. A good way to learn about it is by porting to Silverlight the desktop PI sample from my previous blog post and follow what the code does... have fun!
Labels: dot NET general, Silverlight
Monday, May 19, 2008
Background
XAML was introduced as part of Windows Presentation Foundation (WPF) which was released in November 2006 as part of .NET Framework v3.0. In addition, XAML is at the core of Silverlight, v2 of which will be released this year. Whilst XAML itself is independent of those two technologies, I am a practical person so I associate XAML with those two presentation technologies (WPF for the Windows desktop and Silverlight for the cross-platform browser) and have no qualms in intermixing those terms in this blog post. The XAML that Silverlight 2 will support is a subset of the XAML that WPF supports but the core principles and most capabilities are the same.
XAML is an XML language for describing a hierarchy of objects and their properties; in our concrete examples, it describes a hierarchy of visual objects that make up a Graphical User Interface (GUI).
Relationship to managed code
An important fact about the XAML elements (more precisely the WPF/Silverlight graphical system and controls) is that they are fully composable. For example, the following screenshot shows some crazy XAML that places a TextBox inside a button as its content (and in the bottom right corner the result):

It is important to note that anything you can do with XAML, you can also do in code (C#, VB etc). For the previous example, the alternative code required is a single statement in the ctor:

Regardless of that important fact, it is our preference to use XAML for the (naturally) declarative part of describing a GUI. We then use code, of course, to programmatically react to user interaction with the GUI elements that were declared in XAML, i.e. we use code to capture the behaviour.
The obvious question that arises is how we connect the XAML bits to our managed code. In brief, the technique of partial classes ensures that the XAML bits and the managed code bits end up making a single class. XAML properties assign names to controls so we can reference them in the code-behind and, finally, XAML properties connect events in XAML to event method handlers in code. The following screenshot shows a GUI where clicking on the button, updates the time in the textbox.

Take a look at the combination of XAML and C# to achieve this.

Tool Support and the Designer-Developer Workflow
Visual Studio 2008 has a designer tool that allows you to type XAML (with full intellisense) and instantly see the results. For WPF projects it allows you to also drag and drop controls onto the surface and have the XAML generated for you. Have a look at this VS2008 screenshot of Silverlight designer.
For Silverlight 2, the VS2008 is just a read-only designer so you have to type things in the XAML pane or use an external tool to generate the XAML such as Expression Blend.
Expression Blend allows your designer friends to work on the same project/solution and more importantly on the same XAML that you, the developers, are working on.

Have a look at the screenshot of the exact same project you saw just now, but this time in Blend.

That is one of the reasons XAML is an XML-based language: XML is very toolable. Because of that we have a nice workflow between designer people in Blend and developer folk in VS2008, where there is no exchange of bitmaps or binaries but they are both truly working on the same asset: XAML files. The designer-developer interaction for WPF with XAML is described in this paper.
In my relevant demo, I use Blend to style the Button, add a storyboard for animating it and changing the background color to the LayoutRoot to a gradient color. You can see glimpses of that in both of the above screenshots of VS2008 and Blend, so revisit them paying attention to the XAML parts.
Concepts Worthy of Further Exploration (MSDN links)
If you are a seasoned .NET developer, you'll find that XAML/WPF/Silverlight introduce some new concepts. Below I list MSDN links to the top 5 areas I recommend you investigate – just follow the hyperlinks.
- The Layout System. Note that from the list of layout panels, Silverlight 2 only supports Canvas, StackPanel and Grid. Explore all 3 by changing the LayoutRoot type and dragging various controls on it. This is a good time to grok Attached Properties.
- Dependency Properties. These are important to understand because they enable the following 3 equally important areas:
- Animations (in my session I make a button fly around a bit when clicked).
- Databinding (in my session I bind the results of a WCF call to a list).
- Control Styling/Templating (in my session I change a button to look like a happy face)
Conclusion – XAML levels of competency
If you have been ignoring XAML so far, I don't think you can afford to do so any longer. IMHO there are 4 levels of XAML competency:
Level 100 – truly understand all of the above.
Level 200 – confidently read XAML (e.g. as spat out by VS2008 or Blend).
Level 300 – be able to type XAML yourself with an aim to create a structure of a bland GUI (setting basic properties and hooking events etc).
Level 400 – create styles, templates, animations and set gradient colours by hand.
Labels: dot NET general, Silverlight
Tuesday, May 06, 2008
Have a look at the XML file that looks like this (the results of programmatically calling this Amazon service).
Each
Item element represents a book and I wanted to retrieve the Title. How would you form that query with LINQ to XML?I went for the obvious:
var res =When that did not produce the expected results I scratched my "tired" head at the time and pinged MikeT who came up with the correct way of doing this (you still have time to work it out on your own).
from ia in XElement.Parse(e.Result).DescendantsAndSelf("ItemAttributes")
select ia.Element("Title").Value;
The clue (and at the same time further "excuse") is that all my previous experiments with LINQ to XML involved using my own demo XML files that never had namespaces inside so I forgot all about them (haven't paid the tax in a while). I find quite ugly what you have to do to incorporate namespaces in a LINQ to XML query, but there seems to be no nicer alternative to the following (thanks Mike):
void SomeMethod()I still didn't like this solution for the simple demo I wanted to use it for. So, I recalled VB's superior support for XML and I converted the project to VB and used the following instead which needs no extra method and is all round more elegant:
{
var res =
from ia in XElement.Parse(e.Result).DescendantsAndSelf(n("ItemAttributes"))
select ia.Element(n("Title")).Value;
// TODO use res
}
static XName n(string name)
{
return XNamespace.Get("http://webservices.amazon.com/AWSECommerceService/2005-10-05") + name;
}
Dim res = _...and if you are wondering where the
From ia In XElement.Parse(e.Result)...<n:ItemAttributes> _
Select ia...<n:Title>.Value()
n comes from, that is at the top of the VB file:Imports <xmlns:n="http://webservices.amazon.com/AWSECommerceService/2005-10-05">...another aspect of VB's beauty and another thing I had the opportunity to mention in my demo ;-)
Labels: dot NET general, LINQ
Friday, February 29, 2008
For those of you that can't get a hard/physical copy, they have kindly made it available online for your reading pleasure.
Labels: dot NET general, ParallelComputing
Thursday, December 20, 2007
On the surface without too much digging it appears that the native RegCreateKeyEx is wrapped by RegistryKey.CreateSubKey. So for the BCL team to add support for volatile keys to the managed API, one way would be to add a new overload to CreateSubKey that accepts our desire for volatileness and at the point it calls RegCreateKeyEx it passes in REG_OPTION_VOLATILE instead of 0 which is what the implementation does now (i.e. a change of one line of code).
But since we are not the BCL team and we cannot edit the library's code, we can create a helper static method to do that job for us. Maybe that method would live in the static Program class with a signature something like this:
public static RegistryKey CreateSubKey(this RegistryKey rk, string subkey, bool isVolatile)Note on the above:
{
if (!isVolatile)
{
return rk.CreateSubKey(subkey); // i.e. no change
}
else
{
// call our own method since we cannot change the framework's
return MothCreateVolatileSubKey(rk, subkey, RegistryKeyPermissionCheck.Default);
}
}
1. I've made the method an extension method which means that we can call it in either of these two ways (the first being more natural):
RegistryKey rk1 = Registry.CurrentUser.CreateSubKey("my vol", true);
RegistryKey rk2 = Program.CreateSubKey(Registry.CurrentUser, "my vol", true);2. As you can imagine the implementation of MothCreateVolatileSubKey is a simple duplication of the implementation of the existing framework method with 2 differences:a) Where the framework's implementation passes 0 as the 4th argument to the native RegCreateKeyEx, we will pass REG_OPTION_VOLATILE.
b) Wherever the framework's implementation calls private/internal methods we will have to use reflection to access them (unless you fancy duplicating all of that too;)).
Yes, I know the above is very ugly, very unsupported and very much a hack. I have created a VS2008 solution with the above that you can use to test it out at your own risk. It contains two projects, one for NETCF to run on your Windows Mobile and one for the desktop.
It is quite possible that by running the code from the project your machine will be wiped clean and that your monitor will go up in flames after transferring all your money out of your bank account. You have been warned!
So, at your own risk, get the VS2008 projects here.
Labels: dot NET general, Mobile and Embedded
Tuesday, December 18, 2007
So what is in Fx v2.0 Service Pack 1?
1. Tons of bug fixes. See the list here.
2. Performance Improvements.
+ NGEN boosts.
3. Some new public APIs:
+ New members on the GC class.
+ DateTimeOffset class (this has also propagated to many other APIs that in addition to DateTime now use this new type e.g. XmlConvert.ToDateTimeOffset()).
+ Addition of the ShieldIcon for drawing.
+ IME additions.
+ File Dialog Enhancements.
4. Internal changes:
+ Increase of ThreadPool limit.
Some devs are aiming at using VS2008 to target Fx v2.0. Please note that you are really targeting v2.0 SP1. I blogged a pointer before on potentially addressing this goal, but it is important to stress again that the supported framework for VS2008 is v2.0 SP1 and not v2.0 RTM.
By the way, at the same time, the .NET Framework v3.0 SP1 was also released. Everything I wrote in the first paragraph of this blog post for v2.0 SP1 applies to v3.0 SP1 too. The list of fixes for v3.0 SP1 is in this KB article.
Labels: dot NET general
Monday, December 17, 2007

There are broadly 3 enhancements:
1. The OpenFileDialog has a new property (SafeFileName) that returns just the name and extension of the selected file without the path information. Because of that it is accessible to applications running with limited trust. Should the selected files be more than one, you can use the corresponding SafeFileNames property that returns an array of strings.
2. There is a new property for both Save- and OpenFileDialog that is only applicable on Windows Vista (it gets ignored on XP): AutoUpgradeEnabled. The default is true, and it means that the dialogs will have the Vista look and feel when run on Vista.
3. If you have not opted out from auto upgrading for Vista just discussed, then another property of the 2 dialogs may be useful: CustomPlaces (of type FileDialogCustomPlacesCollection). You can use this to add strings (or Known Folder GUIDs) that represent locations on your disc that are then easily accessible to the user of the dialog you are showing via the "Favorite Links" section.

To see the Vista dialog in action with custom places, watch my screencast.
Labels: dot NET general
Sunday, December 16, 2007
However, if you are writing your own control (e.g. UserControl) then with v2.0 of the Framework you may run into issues. This is a fairly niche scenario but if you are facing it then you should obtain hotfix 934197 that solves the issue by providing a property you can override in your control: CanEnableIme.
Also read the MSDN docs for the protected property.
Hopefully the details on the links above make it clear, but I also found this connect feedback item that makes it crystal clear with a repro. As per the MSFT response there, this property is now available in v2.0 Service Pack 1 on all controls. Maybe now that it is in an SP this angry guy here won't have such an issue distributing the fix...
Bonus IME topic: Also in v2.0 SP1, relevant to Chinese IMEs only, you will find a new member for the ImeMode enumeration for HalfShape: OnHalf.
Labels: dot NET general
Saturday, December 15, 2007
void button1_Click(System.Object sender, System.EventArgs e)With Service Pack 1 of .NET Framework v2.0 we get a new member of that class: SystemIcons.Shield. So, if you are on Windows Vista and you are working with User Account Control, you may find it a useful icon to use (for example on a menu).
{
// use Error
pictureBox1.Image = Bitmap.FromHicon(SystemIcons.Error.Handle);
// use Warning
this.Icon = SystemIcons.Warning;
// use Information
int h = button1.ClientSize.Height / 2;
Icon ico = new Icon(SystemIcons.Information, h, h);
Bitmap bitmap1 = Bitmap.FromHicon(ico.Handle);
button1.Image = bitmap1;
button1.ImageAlign = ContentAlignment.MiddleLeft;
}
Below is a screenshot of what the code above looks like side by side, before clicking the button and after. The screenshot at the bottom is after replacing the 3 icons with shield:
Labels: dot NET general, UAC, Vista
Friday, December 14, 2007
The subtle point is that there is no convention for how we specify the name so, for example, all of the following are valid and will work at runtime:
[DllImport("kernel32.dll")]
static extern ...;
[DllImport("kernel32")]
static extern ...;
[DllImport("Kernel32.DLL")]
static extern ...;
[DllImport("KERNEL32")]
static extern ...;
[DllImport("KeRnEl32.DlL")]
static extern ...;Now, I know that there is no convention, but if you used the above this is what you would see in ILDASM (and indeed in reflector too):
You may think: "So what, isn't just one kernel32 loaded in my process at the end of the day?". Well, yes, but there is a slight performance penalty because the loader treats each separate string as a separate module!
Some of you are thinking that "for that performance reason alone" you should standardize on a convention e.g. always use lowercase and include the ".dll" extension... or something like that. Others are probably thinking that "the performance gains are negligible" for you to make a rule for this.
In my opinion (and it is my blog so don't be shocked that these are my opinions here!), you are both wrong and right at the same time. For me, this is an issue of hygiene. Once I learnt about this fact (many moons ago :-), I couldn't live with myself if in my assemblies I didn't define a standard for pinvoking. Nothing to do with performance – it just feels dirty to me not to use the same DLL name throughout my assembly. That's just the kind of person I am...
So I sighed when I discovered that System.Core.dll is the first and only assembly so far in v2.0/3.0/3.5 of the framework not to follow the "all lower case with .dll appended" convention, as viewing it through a disassembler proves :-(
Labels: dot NET general
Wednesday, December 12, 2007
Labels: dot NET general
Sunday, December 09, 2007
+ Parallel LINQ.
+ Parallel class and friends.
+ TaskManager, Task, Future and friends.
Labels: dot NET general
Friday, November 30, 2007
If you are then ready to dig into it, I have three 20' screencasts (plus more cooking):
1. Tour of the Samples. A tour of what gets installed to get you started.
2. Declarative data parallelism. This is about PLINQ.
3. Imperative data parallelism. This is about the static Parallel class.
After watching the above, visit the relevant MSDN dev centre. For any questions please use the dedicated online forums. For feedback please use the connect site. If you want to congratulate or blame the product team, visit their blog.
Labels: dot NET general, ParallelComputing
Thursday, November 29, 2007
First, in all videos I am using the old internal sort-of-a codename "PFX". This is no longer used internally or externally. Instead just refer to it as Parallel Extensions.
Second, in the PLINQ video, when I very briefly mention what pipelining does, my description is outdated; for an up to date description of pipelining please see this. Also in the same video I do not make it clear that the
ForAll option will *not* allow you to preserve ordering.Third, in the Parallel video, where I use
return sum and imply that it is the same as return 0, I am obviously wrong: The issue is that it’s possible for the first thread to complete so fast that the second thread doesn’t have any work to process. The first thread will store its partial result back into the total sum, but since the thread local selector delegate has captured that total sum variable, the second thread will be initializing its partial sum with the total sum that already includes the first sum’s partial. Thus, you could end up counting values twice so you should use return 0 instead. In the same video, if you really wanted to simulate break, in the parallel version you would have to add a return statement after the ps.Stop() statement that I used.Labels: dot NET general
Wednesday, November 28, 2007
Apparently, the ThreadPool now defaults to having a max of 250 threads instead of 25. I found this ironic because I recall that the NETCF ThreadPool had 256 in v1.0 and changed to 25 to match the desktop behaviour in v2.0 and I wondered if they caught this change in NETCF v3.5 so they can be in sync again. Seems not :-)
Regardless, remember that starting with v2.0 you can change the max yourself not just through hosting APIs but through the managed
SetMaxThreads method. In fact, to validate all of the above, I used the counterpart method, GetMaxThreads that you can try yourself:int a, b;:-)
ThreadPool.GetMaxThreads(out a, out b);
MessageBox.Show(a.ToString());
Labels: dot NET general
Wednesday, October 03, 2007
The cool bit is not that you can just read the framework code in your favourite text editor once you download and accept the license; no, the real goodness is that when you debug your applications with Visual Studio 2008 you will have the option to debug right down into the Framework code (with an autodownload feature from an MSDN server)! Are you still debating the move to VS2008? ;-)
For more details read ScottGu's blog post or listen to ScottHa's podcast or watch ch9 interview with the man that made it happen.
Labels: dot NET general
Monday, October 01, 2007
But how about those people still using VS.NET 2003 (shocking I know :) who wish to take advantage of the VS2008 enhancements and move closer to our latest platform? That's a different kettle of fish. The issue there is that: you are on a different CLR version (1.1) which has some breaking changes compared to the CLR 2.0 (which is used by Fx 2.0/3.0/3.5). You are also on a different framework version (1.1) which has some breaking changes compared to Framework v2.0 (which is also an essential part of Fx 3.0/3.5). There is no reason for you to go to VS2005 as an intermediate step, so by all means go from the IDE of 2003 to 2008, but be prepared to face all the issues people faced when they moved from Fx 1.x to Fx 2.0.
I thought I'd resurface below some links to documents that help people move from v1.x to v2.0, the first two being the most important ones IMO:
- Design time Breaking Changes in .NET Framework 2.0
- Runtime Breaking Changes in .NET Framework 2.0
- Microsoft .NET Framework 1.1 and 2.0 Compatibility
- Compatibility Testing Scenarios
Also note that if you search you'll find plenty of issues in particular for web projects since the project model fundamentally changed from VS.NET 2003 to VS2005. It was later amended via separate downloads for VS2005 but since you are moving to VS2008 you don't have to worry about that (both web site projects and web application projects are included out of the box with VS2008). So, just one extra link for you pre-ASP.NET v2.0 devs:
- Feature changes in ASP.NET 2.0
A much older blog post on the same topic may also be of use to you.
Labels: dot NET general
Friday, September 21, 2007
Anyway...
In a not so unrelated area, on a list that I am a member of, a question came up about affinitising a managed thread to a specific CPU. Jeffrey Richter came to the rescue by pointing out the
System.Diagnostics.ProcessThread and its ProcessorAffinity property but then the harder question came along of how to associate that class with the System.Threading.Thread class. Below is the answer in C# from Mr Richter again: // Call this passing in 0...where
public static ProcessThread GetProcessThreadFromWin32ThreadId(Int32 threadId) {
if (threadId == 0) threadId = ThreadUtility.GetCurrentWin32ThreadId();
foreach (Process process in Process.GetProcesses()) {
foreach (ProcessThread processThread in process.Threads) {
if (processThread.Id == threadId) return processThread;
}
}
throw new InvalidOperationException("No thread matching specified thread Id was found.");
}
ThreadUtility is a class containing at least: [DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
public static extern Int32 GetCurrentWin32ThreadId();The code (and much more) is part the Power Threading Library which is available on the Wintellect site.
Labels: dot NET general, ParallelComputing
Wednesday, May 16, 2007
So, on your system navigate to your %windir%/Microsoft.NET/Framework/v2.0.50727 directory. Pick any of the DLLs starting with "mscor", e.g. mscorjit.dll, and look at its full version information. Note that the presence of Fx v3.0 has no effect on the scenarios below or to this post as a whole.
1. If you have installed NetFx v2.0 on XP or lower, the revision will be 42 i.e. full version is v2.0.50727.42
2. If you have installed Orcas Beta 1 on your machine the revision is actually 1318.
3. If you are on Vista (which comes with NetFx 2.0 by default) and have *not* installed Orcas, then your revision is 312 (that's right, it is "the same version" as RTM)
So there isn't much point to this post, other than to highlight/reinforce that when we say it is the same version, we do not count the Revision part – just the Major.Minor.Build parts.
Labels: dot NET general
Sunday, February 18, 2007
Sub MainIn the code above you were expecting myVariableName to be 7 when actually it is 1, the reason being that you misspelled your variable. Because you don't have to declare the variable, a new one was created for you when you misspelled it and of course it starts with a value of zero. Crazy world! Luckily, in VB6 and before, you could specify Option Explicit and that would not allow you to use variables without declaring them... phew. In .NET land with VB 7.0 by default Option Explicit On is specified for all projects but if people want to be stupid they can turn it off.
myVariableName = 6
myVariableName = myVariableNmae + 1
Debug.WriteLine(myVariableName)
End Sub
Another bad thing you could do in VB6 still remains today and that is the ability to declare untyped variables, for example:
Sub MainEffectively, myVariableName is a Variant (or Object in .NET land) which means it can take any value you want and you never get a compile time error, instead you get a logical error. Similarly for variable o where the compiler cannot tell you that FeelingLucky is not a method of the Collection class so you get a runtime error/exception. So how can you escape this crazy world? A new option in VB 7.0 and beyond is Option Strict. Unfortunately, to this very day, you have to manually turn this option On yourself - it is not the default. If you haven't already, do it now for all your projects. You will prevent logical errors at runtime, runtime exceptions *and* you will make your code faster since method calls will be early bound rather than late bound.
Dim myVariableName = 6
myVariableName = myVariableName + 1
myVariableName = "hello"
Debug.WriteLine(myVariableName)
'
Dim o
o = New Collection
o.FeelingLucky
End Sub
Now, there are some niche scenarios where Option Strict Off may be convenient, namely when doing COM Interop with old automation models that are constructed in a certain way or if you have large codebase that already works and you do not want to touch it (hence you do not want to deal with the compile time errors that you will get when you turn option Strict On). The point here is that you can turn this option on/off at the file level. So I suggest that you turn it On at the project level and turn it off for the files that you think could do without the compile time checking.
Before I close this blog post, note that C# does not have either of these options which basically can be seen as that they are both On and you cannot turn them Off. While Option Explicit is useless, the convenience of doing easy late binding in VB with Option Strict Off can be cool. In c#, you have to do explicit late binding using reflection (which is what the VB compiler does for you in the VB case).
For much more on this topic use your favourite search engine i.e. like this or like that.
Labels: dot NET general
Monday, January 01, 2007
The year of 2006 I made 142 blog entries and below are a select few. Happy New Year!
01. I didn't have a chance to play with it as much as I wanted to, but with very little public info available, this blog served it well: .NET Micro Framework, its product sheet and other NETMF links.
02. Recognising an idiom of the using statement.
03. A cute desktop feature implemented for the Windows Mobile/WinCE platform in a reusable NETCF control: TextBox cue banner.
04. A picture is worth a 100 words and a video is... a whole bunch of pictures! Check mine out following the instructions here for my nuggets.
05. A comprehensive collection of links for Windows Workflow Foundation (WF).
06. I collected the links to my 9 blog posts on sharing assets between desktop and mobile platforms in one place. Follow the numbered links.
07. The most controversial feature of Windows Vista is something every developer must understand: User Account Control.
08. One of Vista's features is becoming my obsession and that is SideShow. My series of SideShow gadgets blog posts will continue in 2007 and so far you can read parts one, two, three, four and five.
09. I spent 6 months last year focusing almost entirely on Vista developer features that are new and that are *not* part of NetFx3. I have catalogued my blogging & screencasting efforts in a large collection of links to content that supports my speaking engagements on Vista. IMO this blog post alone could have been the best of "The Moth" this year:
Vista-only features for the managed developer.Stay tuned in 2007 via one of the subscribe options on the left :-)
Labels: dot NET general, Links, Mobile and Embedded, Vista
Monday, December 11, 2006
Let's drill into it. If you write a shell extension of any sort with managed code, you have introduced a dependency onto the version of the CLR that you are using. The classic example is to think of all the managed applications on a computer that open a file dialog. Every time they do that, your .NET shell extension code gets injected into their process and bad things can happen (not just to the shell) but more importantly to those applications *IF* the version used in your managed extension, is not the same as the version used by that application. So the real root of this issue is the fact that each process can only load one version of the CLR combined with the fact that a version of the CLR can side by side on the same machine with other versions of the CLRs.
It sounds like we are pretty serious about this advice. An article written in 2004 demonstrating how to write namespace extensions with managed code was edited this June 2006 to include the following warning in red at the top of the article:
[ Editor's Update - 6/23/2006: Because shell extensions are loaded into arbitrary processes and because managed code built against one version of the runtime may not run in a process running an earlier version of the runtime, Microsoft recommends against writing managed shell extensions and does not consider them a supported scenario.]
Now at this point, some of you will have arguments and workarounds of how to avoid this limitation. I doubt they haven’t been raised already, but if you think you have something new to offer, go contribute to this extremely interesting discussion on the msdn forums (inc. contributions from Raymond Chen).
Labels: dot NET general
Thursday, October 05, 2006
When I was trying to call the WerRegisterFile API as described previously, I run into an interesting situation: Calling the API without specifying any CharSet should have attempted first the WerRegisterFile. If I specify CharSet.Auto, it should first attempt WerRegisterFileW and if it cannot find that then go back to try WerRegisterFile. Either way, you would have thought that this would succeed or blow. As it turns out, leaving the CharSet off, silently fails (no exception, return value is 0, Marshal.GetLastWin32Error is 0 etc) but specifying CharSet.Auto works as expected! For the record, CharSet.Unicode behaves like CharSet.Auto and CharSet.Ansi fails like when we omit altogether CharSet from the DllImport declaration.
Download a repro VS2005 project here (obviously requires Vista).
Solution
Looking at kernel32.dll (which exports this function) shows that there is only one entry for the API (screenshot of dumpbin). This seems to be a pattern with Vista, according to my colleague MikeT.
Well it seems that after a series of chats with Mike, he updated his post with useful thoughts. Read his 4th thought in the updated section and come back... I’ll wait...
[...time passes...]
So to prove the thought, I looked at another Vista API that takes strings: RegisterApplicationRestart. It too has no trailing A or W (screenshot). So calling this API without CharSet also gives no errors, but the string you get passed back to the application at the command line is definitely not the one I passed to it (something Chinese-looking on my system when I gave it something English).
That rests the case. I should have realised earlier that CharSet is not just about finding the correct entry point but also about how the string will be marshalled.
As an excuse I should state that, having mostly coded for WinCE, I think I have been spoilt since that is all Unicode and I can’t remember using CharSet with any of NETCF pinvokes and they all worked fine :)
Final thoughts
1. Whoever thought the default of CharSet should be Ansi has a lot to answer for. Note that it is a C# decision as the CLR defaults to Auto!
2. I wonder if the Vista change (that threw me off track) is going to bite others or if it just muppets like me that fell for it :S
3. Why is WerRegiserFile in kernel32.dll when all the other WER APIs are in wer.dll?!
4. WerRegisterFile should be giving some indication to the developer that it failed. At the end of the day, you give it a path (string), it thinks it is a different string (path), so it cannot find the file and then it silently fails! WTF?
5. I detest silent failures. Make an explosion next time. A big loud one or a quiet one, but not a silent one. Silent ones are the worst!
Labels: dot NET general
We all know that to call unmanaged code from managed code you have to pinvoke (i.e. use the DllImport attribute). One of the enumerations that becomes relevant when calling native methods that accept strings is CharSet.
It is also relevant for native structures with strings but I am explicitly ignoring that in this post. I am also ignoring the CharSet.None enumeration as it means the same as CharSet.Ansi and is there for C++ legacy reasons, I think.
CharSet is useful so you can instruct the runtime to invoke the "A" version of an API or the "W" version (Ansi or Unicode) e.g. MessageBoxA or MessageBoxW. If you select CharSet.Ansi the CLR attempts to invoke an entry point with an appended "A" if the entry point specified by the signature doesn't exist. If you select Auto, then on modern OSs it will default to Unicode. This means the CLR will attempt to invoke an entry point with an appended "W" before attempting to invoke the entry point specified by the signature. If you miss the CharSet from your DllImport declaration, the default is Ansi with the behaviour described above.
Labels: dot NET general
Wednesday, October 04, 2006
So the alternative I offer is... the alternative I have always offered! The title gives it away: pinvoke.net
If you read my older entry then you’ll know where to go to get the interop book.
There is also a Visual Studio 2005 add-in for the pinvoke wiki site, but I haven’t personally tried it. Get it from gotdotnet.
I plan to update the wiki with Vista API definitions at some point (the power API I mentioned previously is already there). I’ve added this to my TODO list (item # 88345602), but if you feel you’d like to take on the task, please go for it (Vista dllimports all over my blog entries since May this year)!
Labels: dot NET general
Thursday, September 28, 2006
While looking on the web for something irrelevant, I came accross an old post by Geoff Appleby that offers a custom implementation of CommandLink for XP. Check it out!
Labels: dot NET general
Monday, July 03, 2006
"The using statement accepts as an argument an object that implements IDisposable; it defines a coding block where the ctor of the said object is called at the start and the Dispose method is called in the end."
Taking the definition above, a design pattern is formed (or to be more precise in this case, an idiom):
Sometimes you have a piece of code that has to be enclosed between two code blocks A and B. Code blocks A and B are repeated in multiple places in your project(s). When you recognise that, you can extract a new class with a ctor containing code block A and the Dispose method containing code block B. Replace all client side occurrences with a using block passing in the newly extracted class.
As an example, instead of:
void SomeMethod()we write:
{
Cursor.Current = Cursors.WaitCursor;
statusBar1.Text = "Busy...";
button1.Enabled = false;
// do some real work here
button1.Enabled = true;
statusBar1.Text = "Ready";
Cursor.Current = Cursors.Default;
}
void SomeMethod()...after extracting the following class:
{
using (BusyTaskRegion bt = new BusyTaskRegion(statusBar1, button1))
{
// do some real work here
}
}
class BusyTaskRegion : IDisposableAnother example would be measuring performance of some code (i.e. extract the timer setup and tear down into a class and then use it via using). I was trying to find the pattern formally documented online but I couldn't. However, I did find examples of its usage here, here and here (much better than my fictitious example above!).
{
private Control _c1;
private Control _c2;
public BusyTaskRegion(Control c1, Control c2)
{
this._c1 = c1;
this._c2 = c2;
Cursor.Current = Cursors.WaitCursor;
c1.Text = "Busy...";
c2.Enabled = false;
}
public void Dispose()
{
this._c1.Enabled = true;
this._c1.Text = "Ready";
Cursor.Current = Cursors.Default;
}
}
When I first saw this (at a previous project for some impersonation code), it felt wrong on two levels. First, it felt like using was being misused in scenarios that it wasn't originally intended for (e.g. when people read the client side code they have to take an extra mental step to digest that no memory management stuff takes place). Second, it felt wrong to define classes that have just a constructor and a Dispose method with nothing else in-between.
What do you think?
Labels: dot NET general
Given a class like this:
class SomeType : IDisposable{
public SomeType(){
// do some ctor stuff
}
public void DoSomething(){
// do some useful stuff
}
public void Dispose(){
// clean up unmanaged resources
}
}We know that the client code should use it like this:SomeType st = new SomeType();The using statement makes that cleaner, easier to remember and easier to enforce like this:
try
{
st.DoSomething();
}
finally
{
st.Dispose();
}
using (SomeType st = new SomeType())So, the easy way to describe the purpose of
{
st.DoSomething();
}
using (without a code example) is this:The using statement offers an elegant way of ensuring that the developer does not forget to call Dispose on an object that (directly or indirectly) holds unmanaged resources. (My links to msdn at the top pretty much say the same thing)
Effectively, we all associate the using statement (or at least I always did) with not leaking. However, if we look at the using statement not from an intent point of view but instead from a practical point of view, we would probably come up with this:
The using statement accepts as an argument an object that implements IDisposable; it defines a coding block where the ctor of the said object is called at the start and the Dispose method is called in the end.
Next, we'll see how to take that last statement further to describe a design pattern.
Labels: dot NET general
Sunday, November 13, 2005
We are also familiar with Generics (supported on NETCF as well).
At first there isn't much relation between the two. There are some cases, though, when you design an API (that depends on a type to be passed to it) where either of the two can satisfy your goal: A generic class or a class with a constructor accepting a Type. So in that case, which approach should you choose and why?
1. Blah<T>{...} //type declaration
2. Blah(Type t); //ctor
Just to be ultra-clear, the calling code for each occasion looks something like this:
1. new Blah<SomeType>();
2. new Blah(typeOf(SomeType));
Just FYI, and don't allow this to affect your thoughts, the indigo (or WCF if you prefer) team chose the 1st approach originally and then, after Beta 1, changed to the second. I am referring, of course, to the
ServiceHost class. Why did they do that?Since this blog doesn't have comments, reply on your own blog (or if you don't have one, feel free to email me your reply).
UPDATE:
1) .NET design guidelines guru provides comments.
2) Ayende describes his preferences
3) Apparently, there is no mystery on the Indigo change:
"The ServiceHost just needs to know the type of the object being hosted - none of the methods or properties were accepting or returning the
Labels: dot NET general
Sunday, July 31, 2005
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 managed3. Just so you can see the IL for a C# version compiled under Visual Studio 2005 Beta 2, here is some code:
{
// 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
private ArrayList ar = new ArrayList();...and equivalent IL:
public void Box() {
ar.Add(5);
}
public void Unbox() {
int i = (int)ar[0];
}
.method public hidebysig instance void Box() cil managedBy 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
{
// 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
a) No boxing/unboxing penalty takes place
b) No cast is required
c) Compiler prevents anyone adding objects of other types to our List
Labels: dot NET general
Monday, May 30, 2005
Dim b As Boolean 'b is already initialised to FalseIn C-based languages (inc. C#) this does not apply; you must initialise the variable before you use it, e.g.
bool b = false;The above is the reason we cannot have
ByOut in VB (only ByVal and ByRef) whereas C# has both ref and out (ByVal is implied by omission).I have seen VB code that follows the C-style and there are two common reasons for doing so; one is to be explicit and the other is because of a C-based upbringing. The question is what IL will the VB compiler generate, faced with code that differs only by explicit assignment (we know it is pretty crap at optimising the simplest of scenarios, so we don't go in with our hopes high).
Given these two methods (and assuming a private method
GetNumber):Public Sub VBStyle()I can tell you that the VB compiler generates slower code for the second scenario (I have to say if you have a bottleneck in your project, cases like this will not be it, but it is still good to know :-).
Dim i As Int32
i = GetANumber()
End Sub
Public Sub CsStyle()
Dim i As Int32 = 0
i = GetANumber()
End Sub
Here is the corresponding IL:
.method public instance void VBStyle() cil managedNeedless to say that the C# version closely reflects the first version (it is even better, since it uses a
{
// Code size 8 (0x8)
.maxstack 1
.locals init ([0] int32 i)
IL_0000: ldarg.0
IL_0001: callvirt instance int32 VBWinApp.Class3::GetANumber()
IL_0006: stloc.0
IL_0007: ret
} // end of method Class3::VBStyle
.method public instance void CsStyle() cil managed
{
// Code size 10 (0xa)
.maxstack 1
.locals init ([0] int32 i)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldarg.0
IL_0003: callvirt instance int32 VBWinApp.Class3::GetANumber()
IL_0008: stloc.0
IL_0009: ret
} // end of method Class3::CsStyle
call rather than a callvirt - but that is a different story...).Labels: dot NET general
Tuesday, May 10, 2005
What does mscorlib stand for? Stop reading! Don’t look for the answer, just try and work out the answer. What does the main dll of .the NET Framework stand for? What was the codename or first candidate name if you like, for C#? Well here are my answers (this is just my understanding which I cannot track back to a reference!):
C# and the design of this new .NET language ws COOL! More importantly, mscorlib has 3 parts to its name: ms cor lib.
ms: Magnificent Software (ok, it is Microsoft :-)
lib: as you expect this means library
cor: Before .NET was chosen as the name, this new platform was a successor to COM so it was codenamed COM 3.0 and then the name chosen was… Common Object Runtime (cor) and that is where mscorlib derives its name from (and that stuck regardless of the fact that .NET was the final name)!
So, now you know ;-) And if you knew already now you have something to point to!
Labels: dot NET general
Wednesday, March 16, 2005
If you are reading that blog entry to understand polymorphism, please read my (complementary) take on the topic below.
First I would ignore overloading. This has nothing to do with polymorphism and I would not bring it up in any discussions on the topic. Just for info, overloading is the ability to define two or more methods on the same class with the same name but different argument lists. Nothing more, nothing less.
Second, do not directly associate polymorphism with inheritance (as you can probably tell this is my pet peeve :-). Polymorphism directly depends on subtyping. Unfortunately, many people confuse subtyping with implementation inheritance. Inheritance is *a* way to achieve subtyping, but not the only one (another is interface implementation). If you ask the question in reverse: Is inheritance the same as polymorphism? The answer is no. Inheritance offers a way to achieve subtyping *and* a way to reuse code.
So if someone asks you to explain polymorphism with a VB.NET example using inheritance, you can do something simple like this:
Public Class EntryPointThe client code uses the type Animal. It does not know what objects it will be given (i.e. instances of what class) but the fact that they support the programmatic interface of the Animal type is enough for it to use them: polymorphism in action.
Shared Sub Main()
Dim m As New Mouse
Dim s As New Shark
DoSomethingWith(m)
DoSomethingWith(s)
End Sub
' Client code
Public Shared Sub DoSomethingWith(ByVal a As Animal)
a.Bite()
End Sub
End Class
Public MustInherit Class Animal
Public MustOverride Sub Bite()
End Class
Public Class Mouse
Inherits Animal
Public Overrides Sub Bite()
MsgBox("Disease")
End Sub
End Class
Public Class Shark
Inherits Animal
Public Overrides Sub Bite()
MsgBox("ouch!")
End Sub
End Class
If someone asks you to explain polymorphism with a VB6 example, you can do something like this:
In a Standard EXE project, change the startup Object in project properties to Sub Main.
Add a module1 with this code:
Sub Main()Add a Animal class module:
Dim m As New Mouse
Dim s As New Shark
DoSomethingWith m
DoSomethingWith s
End Sub
' Client code
Sub DoSomethingWith(ByVal a As Animal)
a.Bite
End Sub
Add a Mouse class module:
Public Sub Bite()
End Sub
Implements AnimalAdd a Shark class module:
Private Sub Animal_Bite()
MsgBox "Disease"
End Sub
Implements Animal
Private Sub Animal_Bite()
MsgBox "ouch!"
End Sub
That's it. Polymorphism in VB6: nothing fake or incomplete about it.
Naturally you can mix many concepts in your designs including polymorphism, inheritance and overloading etc. If you want to see a design combining these topics, then Raymond's post has a nice VB.NET example.
Labels: dot NET general
Friday, March 04, 2005
"Event X from control Y gets fired twice" or "I want to stop this event from firing while I am waiting for Z"
For example assume that you do stuff in the event handler of the selectedindexchanged event of a list; you now need to select an item in a list programmatically but do not want to run your event handling in that case (only when it is done by the user). Here is a simple example:
Given a form with a listbox and a button let's assume your event handler looks something like this:
Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object, _And let's assume as part of a button click you are doing something like this:
ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
MessageBox.Show(ListBox1.SelectedItem.ToString())
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, _When you click the button you don't want to see a messagebox.
ByVal e As System.EventArgs) Handles Button1.Click
ListBox1.SelectedIndex = 0
End Sub
As you'd expect the solution is simple:
1) Use a boolean flag and check it in your event before processing
or
2) Dynamically remove the event handler
1) Define a boolean in your form code like this:
Private mDontRun As BooleanChange your button click event handler body to be like this:
mDontRun = TrueAnd add to the selectedindexchanged event handler the following as the first line:
ListBox1.SelectedIndex = 0
mDontRun = False
If mDontRun = True Then Return2) The alternative is not to declare a boolean, not to change the selectedindexchanged event handler and simply change the button click method body like this:
RemoveHandler ListBox1.SelectedIndexChanged, _Simple really... and one more entry I can point to from the ng...
AddressOf ListBox1_SelectedIndexChanged
ListBox1.SelectedIndex = 0
AddHandler ListBox1.SelectedIndexChanged, _
AddressOf ListBox1_SelectedIndexChanged
Labels: dot NET general
Monday, February 28, 2005
"...I have this C# code I need to translate to VB..."Occasionally we get requests for translating VB to C# and the same principle applies.
If you really need to translate the code, *please* learn how to at least read the other language: it will make you a better .NET developer, guaranteed. There are many sites that list the differences and there are many converters for VB-to-C# or for C#-to-VB or both.
However, if you just picked up a C# file and you need to use it from your VB project you can do just that by adding it to a dll first. Given that the advice leads to more "how to" questions (believe me it does!), here are the steps needed to achieve just that:
1. Create New C# Smart Device project (not for Full Fx)
2. From the wizard select the target and then Class Library. Choose a suitable name and location.
3. Delete the default file Class1.cs
4.
Project->Add Existing Item (from the menu)5. Navigate to the folder where you have saved/downloaded your C# file. Open the file (which makes a copy to the project's directory) or Link to it (which allows you to use it in the project but only keeps one copy on disc)
6. Double-click in solution explorer to view the file. Note the namespace declaration at the top (e.g. namespace OpenNETCF.IO). Optionally change it to the name of your project.
7. Repeat steps 5-6 for any other files
8.
Build->Rebuild Solution9. You now have a dll in the bin\Debug directory under the project you just created
From your exe/application project select from the menu
Project->Add Reference and browse to the dll; Select it and OK.Labels: dot NET general
Wednesday, February 16, 2005
Dim i As Int32Years ago I upgraded some nasty VB6 code that, amongst other things, used the Collection class. The VB.NET Collection object allows removals from it while iterating. If you upgrade it to ArrayList, though, (apart from making changes to reflect the 0 index base), you soon find that ArrayList forbids removing items while iterating. At the time I came up with the above smelly hack. Due to recent refactorings the design/code has been modified, so I am capturing the hack here for posterity...
Dim k As Int32 = mCol.Count
For i = 0 To mCol.Count - 1
Me.MethodThat_May_ResultInRemovalFromCol()
If k > mCol.Count Then
i -= 1
k = mCol.Count
End If
If k <= i + 1 Then
Exit For
End If
Next i
PS I upgraded Collection to ArrayList for performance reasons
PS2 Locking the collection is irrelevant here
PS3 I am aware of Synchronized - I don't like it
PS4 The real solution is not to remove while iterating; it is bad design.

