# Friday, May 20, 2005

Claudio, Mike and I had a great week in Phoenix. We definitely noticed the change in temperature from what we're used to in Redmond. The hottest day was about 40C/104F. And this is referred to as "cool" by the weather man here! Hate to experience "hot", which apparently starts at around 115F and heads up to 125F. Ouch! If I was here then, I'd end up in the hospital. Although, now that we're heading back to Redmond, we'll miss the warmth of the Arizona climate since we're likely headed to much cooler temperatures and a bit of a tropical storm. From talking to Annie, my wife, during our trip, I've been hearing about all of the rain that we've been missing.

I'd like to thank Tim Heuer, the Developer Evangelist for the SouthWest region, for organizing our trip. He worked for a number of weeks before we arrived with a number of customers to develop a jam-packed schedule for us. We met with 2-3 customers per day and then had dinners at night with Microsoft partners and the local .NET user group. This resulted in 13 hour days on average. Must sleep now.

We took the time out to travel to Phoenix with three goals: (a) get feedback from our customers on their use (i.e. challenges and wins) of the .NET Framework, (b) provide customers with access to CLR experts to address their questions, and (c) ask customers for their apps and/or unit tests for use in our compatibility lab (more on this later).

We left Phoenix feeling quite happy with achieving our goals. We took a lot of notes and are going to use those in our planning for the next version of the .NET Framework (v3.0). We are almost done working on Whidbey (v2.0) and are starting to move the Program Management team (i.e. Claudio, Mike and me) to writing high-level specs on v3 features. For example, I'm doing a lot of work on managed code versioning. In terms of providing customers with access to CLR experts, I was very stoked about getting Scott Guthrie to meet with one lucky customer. This only worked out due to Scott being in town for just over 24 hours to speak at the Beta Days conference (where I am now) on Thursday. Scott didn't even break a sweat explaining how to best use certain aspects of ASP.Net. The customer quesions varried quite a bit but were more focussed on the use of viewstate. He also spent some time describing the new features in ASP.Net v2. One of the developers had this look in his eyes like he wasn't planning to go to bed that night, but migrating his company's website to v2 in order to get access to the new features!

Many customers were very excited about Visual Studio 2005 Team System. Claudio did an awesome demo of the CLR profiler built into the team system. I hadn't seen that before either and was quite impressed too. I can see using the profiler on the ASP.Net site that I'm currently building. I'm sure that I'm using much more memory than I need to be. There are many other new features in VSTS that customers are dying to start using, including load testing, code defect tracking, source control (not VSS), and FXCop. If you are in the South-West area, please contact Tim Heuer if you'd like a demo of VS 2005 (or any other developer technology).

I'd like to take a moment to address compatability. You've probably seen that as a recurring theme in my blog entries -- and this blog is supposed to be about the CLR loader ;). We made an offer to all of the customers that we met that I'd like to offer more generally. I haven't asked if this is OK to offer to the whole Web, but I'll do it anyway ;). We are very serious about backwards compatibility. We have a compatibility lab on the CLR team, in which we test v1.x apps on the v2.0 .NET Framework. Just to be super clear, we are testing the binary backwards compatibility of Whidbey. If an app fails to work/behave as expected, we determine why and then fix the problem in the v2.0 .NET Framework before it ships. We need more applications in the compatibility lab in order to have a better sample size of apps relative to the universe of managed apps out there in the wild. Ideally, we would have more apps that we can test and that they were very varried in terms of: internal business apps versus boxed apps, data components versus visual controls, ASP.Net versus Windows Forms, Windows Services versus Web Services, simple apps versus complex apps, database-oriented versus XML-oriented, natural language-specific (i.e. English) versus localized (i.e. Chinese, Hebrew, French), VB.Net versus Cobol, data-heavy (megs and megs of data in memory) versus CPU-bound. Hopefully you get the idea since I cannot think of any other axis of programs. Anyway, if you'd like to submit your apps or some part thereof, we'd love to talk. Unit tests are also great. We'll test the app until we ship Whidbey and then continue to ship it in the future to ensure that we don't break v1.x compatibility. In future, we'll look for v2.0 apps in addition to v1.x, ensuring that we don't break v2 compatibility on the v3 CLR.

Anyway, we had a great time in Phoenix. Turned out that our flight is delayed by 1 hour, but that's OK. This way we get to watch the sun go down in Phoenix. Quite fitting for the end of a great trip.

Just got home. It is is 1AM now. It is raining and 11C/51F. Just a minor change from Phoenix ;)   Definitely found out that flying -- landing in particular -- with a head-cold is not recommended. I still cannot hear anything, but fortunately my ears have stopped hurting. 

Friday, May 20, 2005 9:01:40 AM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, May 19, 2005

Some time ago, I moved my blog to a 64-bit X64 server. This server was running Windows Server 2003 SP1 Beta 1 and an early version of Whidbey Beta 2. I thought that this was an excellent opportunity to dogfood (MS term for early adoption) the 64-bit version of the framework, not to mention Server 2003 SP1. Another side aspect of this exercise was that I was testing out the backwards compatibility of the .NET Framework, since DasBlog is built with the v1.1 version of the Framework.

I'm happy to report that I've had zero problems with this new configuration, even with beta software. The OS has now shipped, so there is no issue there, but the version of Whidbey is still only Beta 2 and it is chugging day after day without issue. Doesn't get better than that! It also shows the incredible value of MSIL -- what C#, VB.Net, Eiffel, IronPython, Cobol and any other managed code compiler compiles down to -- given that the Everett DasBlog code "just works" on 64-bit Whidbey, even though 64-bit was not a supported (or possible) configuration of Everett.

One of the major features of Whidbey ASP.Net is XHTML compliance. DasBlog was not designed to be 100% XHTML compliant, so would not work on the first try on Whidbey. We had to use a special config switch to turn off XHTML compliance in Whidbey. After that, everything worked perfectly, in terms of performance, backwards compatibility and general behaviour of the app. I'm very happy and can say that Whidbey Beta 2 is ready for prime-time development. To that end, the .NET Framework is allowing companies to "go live" with our "go live" license. This means that you can build/migrate a public-facing application with Whidbey Beta 2.

Back to 64-bit ... I must say that the 64-bit support in Whidbey is very cool. I have two high-end X64 boxes in my office, one from Intel and the other from AMD. I use them for various purposes and am quite happy with them. In particular, I really like building and debugging apps on my 64-bit machines, having them run in native 64-bit, but then being able to deploy them to both 32- and 64-bit machines. The portability of managed code assemblies across different CPU architectures (IA64, X64, X86) is a huge win.

I've also been running early 64-bit versions of Longhorn on these two X64 machines. I haven't done any tests using >2GB of virtual address space, but I would like to see a managed app that does that, taking full advantage of the 64-bit address space. I can imagine that companies running SQL Server will immediately see the benefit of that removed barrier.

Thursday, May 19, 2005 8:35:01 PM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, May 12, 2005

Managed Debugging Assistants are an existing feature (Customer Debug Probes) improved on and expanded. They are exposed in a similar manner to exceptions (don't let that scare you) but occur not because of an error condition, but because the runtime has noticed a condition that could cause you problems. We've talked to lots of customers over the years and have received feedback that there are a set of scenarios that cause developers pain more often than others. As a result, we've written a bunch of code -- the MDAs themselves -- that can be used while your code is running to protect you against these pain points ... that's good, right?

The MDA infrastructure is always "on", but only a few MDAs are activated by default. That's easily changed, by selecting the "Debug" menu and "Exceptions" within it. From there, you can turn on or off any MDA of your choosing, as you can see in the image below. There is only one MDA turned on in that part of list in the image below, but you turn on as many as you want.

VS 2005 exceptions window

Anyway, I want to introduce you to the LoadFromContext MDA. If you want to know more about the joys of LoadFrom, check out Suzanne's blog. I'll post more on binding contexts at some point, but want to stay on the subject of this MDA for the moment. Here is some code that exercises this MDA -- this is just an exe project attempting to load a built assembly from a class library project in the same solution (hence the strange pathing) ...

using System;
using System.Reflection;

namespace LoadFromMDA
{
class Program
{
static void Main(string[] args)
{
Assembly asm = Assembly.LoadFrom(@"..\..\..\SomeAssembly\bin\debug\SomeAssembly.dll");
Console.WriteLine(asm.FullName);
}
}
}

If the MDA is enabled, I get the following exception-looking popup window as soon as hit the first line of code.

LoadFromContext MDA window

The reason that this MDA is so useful is that it is really quite difficult to determine for certain which binding context an assembly was loading into, other than following a certain set of rules and closely watching the way that the binder binds to dependent assemblies. However, with this MDA, you can know for sure if you are loading assemblies into the LoadFrom context.

There are several other MDAs to play with. I recommend taking a look through them and turning on ones that might apply to your program. There is no harm and you may avoid your program throwing an exception in some edge-case scenarios for reasons that may not be super clear to you.

 

Thursday, May 12, 2005 2:27:53 AM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, May 09, 2005

A few of us are heading to Phoenix in a week to visit companies and user groups interested in or currently deep into .NET Framework development. Our schedule is fully booked, but we can likely make some time still (there are three of us) if you are going to be in Phoenix during that time and would like to meet someone from the CLR team to talk about various aspects of .NET Framework development. Mail me if you are interested. There is also BetaDays happening on the thursday of that week. See Brad's post for more about that. Scott Guthrie, the Product Unit Manager of ASP.Net, will be at BetaDays and will be coming along with us to visit with one of the companies, which happens to be quite deep into ASP.Net-based development.

Brad also has an interesting post and links to many others about his Atlanta trip last week. It sounds like Brad, Kit, Claudio and Jason had an amazing time, at least judging from all the blog posts.

We're (the Phoenix tripsters) meeting the Atlanta tripsters later this afternoon for drinks to get some tips and feedback from their recent trip. It should be interesting to hear how everything worked out after a week of intense interaction with the Atlanta community. From the pics, it looks like everyone was having a lot of fun. 

There are a set of other trips still in the process of being booked. Please ping me if you've got some compelling reasons (bunch of companies using or wanting to use the .NET Framework, active usergroup(s), good restaurants)for us to come visit your city.

Phoenix, here we come!

Monday, May 09, 2005 2:51:42 PM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

Brad sent me mail on Friday night asking about our plans (or non-plans) to change the assembly version number again for Whidbey. The mail was the result of a developer -- let's call him Marc -- who had pinged Brad earlier in the week through his blog asking that exact question ...

Here is the basic question from Marc:

I'm using Beta 2 of the .NET Framework SDK 2.0 ... I'm curious, if I roll this app out, built on a beta ... Would the app continue to function or would it need to be rebuilt with the 2.0 final SDK?

There's too many exciting features to stick with the 1.x version of .NET. :-) Every day I find something new and exciting that can be done. It makes programming fun again!

I'm glad to hear that Marc likes Whidbey. That's definitely the plan from building 42 (where the CLR team works)! Back to the original question: will Marc's app continue to work or is a re-compile required? Marc isn't specific about which beta he is using, so I'm going to have to resort to a multi-part answer, unfortunately ...

1. If Marc is on Whidbey Beta 1 (or earlier), then the answer is "yes ... a recompilation is in your future".

2. If Marc is on Whidbey Beta 2 (or later), then the answer is "no ... your app should work just fine".

W/rt (2), I do recommend re-compiling against the final product even though it isn't strictly required (from a technical perspective). Naturally, there will have been further changes/fixes in the compilers and the metadata sub-system that will very likely result in a better built assembly.

Some of you might wonder what this is all about. I'll attempt to explain w/o going on any tangents. Please email if there are some tangents that you are interested in ;)

We set the assembly version number of each of the assemblies (all the same version fortunately) in the .NET Framework at major milestones, treating it as an contract between the .NET Framework and it's consumers. We then break that contract by changing the assembly version number again when we start a new milestone (i.e. Beta 1 versus Beta 2; Everett versus Whidbey). Why do we do that? We change the assembly version number for two reasons: (A) the contract has changed since the code inside the assemblies is very substantially different, and (B) a strong identifier (i.e. a version number) needs to be changed to remain a strong identifier.

We changed the assembly version number last early in the Beta 2 milestone, for the reasons described above. We will not change it again in the Whidbey product since the rate of changes to the product has slowed down and because we only want to make changes at this point that are absolutely required to ship the product.

As a result of how we've changed the assembly number and since the assembly binder binds strictly on the whole version number, apps built with Whidbey Beta 2 will continue to reference Whidbey RTM .NET Framework assemblies since their version number will be the same as what the Whidbey Beta 2 app is expecting.

Hope that helps Marc!

Monday, May 09, 2005 6:36:31 AM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
# Monday, January 24, 2005

As you may guess/hope, we're doing our best to close down Whidbey Beta 2 ... so that we can ship it out to you to use. As part of that, we recently completed a security push to ensure that we are shipping a secure product. Another product axis that we also strive to deliver upon is compatibility. We have a set of processes and tools for ensuring that Whidbey is backwards compatible, to ensure that assemblies compiled against the v1.0 or v1.1 .NET Framework execute without issue on the v2.0 (Whidbey) .NET Framework.

You can help too, to ensure that we are delivering on compatibility in Whidbey. First, check out my colleague Jesse's posting @ GotDotNet that allows you to easily do compatibility testing against Whidbey Beta 1.

If you do find a problem, compatibility issue or otherwise, tell us about it @ the MSDN Product Feedback Center. We get this feedback delivered directly into our bug database and we deal with this feedback alongside the regular bugs that we get from our testing teams. Here is an example of a user-reported bug that we fixed that happened to be a compatibility-break.

I also plan to do a series on compatibility here to provide more transparent information on our compatibility bar and story.

One last thing ... here is our existing .NET Framework compatibility site. Jesse and I are planning on building a new site that is easier to use. I would have built it against Whidbey Beta 2, but he suggested that we build it against Everett/SQL 2000 and then host it on Whidbey/Yukon to dogfood Whidbey and Yukon compatibility. So, that's what we're doing. Cool, eh?

Monday, January 24, 2005 5:57:22 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [13]  | 
# Saturday, January 15, 2005

I decided to whip up a quick app today to test some behaviour of Assembly.LoadFrom() that I wasn't 100% certain about. In particular, I was curious about the dependency resolution behaviour of Assembly.LoadFrom(), as compared to Assembly.Load(). I know that Load() will find static dependencies for you, provided that the dependencies are in a place that the loader looks (i.e. GAC, appbase, private bin paths). I also know that Assembly.LoadFile() doesn't do any dependency resolution for you; you have to pre-load dependencies when you use LoadFile(). So, the test is to determine which camp -- dependency resolution or not -- that LoadFrom falls into. I'm pretty sure that it will fall into the dependency resolution camp, but I've never explicitly tested this case in issolation, so I'm checking it out. I've also written a bunch of apps that depended on LoadFrom resolving dependencies for you, so this likely isn't going to end up being a big surprise.

An Exercise in Reflection

So, I have to admit up front that I'm not great at using Reflection -- another bloke works on that. Anyway, I had to brush up on my reflection skills to get this working and ask Joel if I'd done it properly once I was done, which turned out to be mostly the case.

Here's the main program:

        static void Main(string[] args)
        {
            Assembly a;
            Type t;
            MethodInfo m;
            Object[] myArgs;
            Object myInt;

            Console.WriteLine(
"In main program");

            
//Loading assembly
            
//a = Assembly.LoadFile(@"C:\Documents and Settings\rlander\My Documents\Visual Studio 2005\Projects\LoadFromApp\FooLibrary\bin\debug\FooLibrary.dll");
            a
= Assembly.LoadFrom(@"../../../FooLibrary/bin/debug/FooLibrary.dll");

            
//Getting type to call into
            t
= a.GetType("FooLibrary.Foo");

            
//Getting the specific method that I'm interested in
            m
= t.GetMethod("GetInt", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(System.Int32)},null);

            
//args to pass to the method
            myArgs
= new Object[1] {5};
            
            
try
            {
                
//Calling the method and printing the return value
                myInt
= m.Invoke(null, myArgs);
                Console.WriteLine(myInt.ToString());
            }
                
//in case something bad happens
            
catch (TargetInvocationException e)
            {
                Console.WriteLine(e.InnerException.ToString());
            }
        }

Indeed, there is more to this program than just the Main method, however, the additional aspects are not particularly interesting. The code above is the whole of a Console exe project, called LoadFromApp, in VS 2005. There are two other projects that I wrote too: (1) a Class Library project called FooLibrary that the exe loads via Assembly.LoadFrom(), and (2) another Class Library project called BarLibrary to which FooLibrary statically links. You can see these too/two in the code sample, which is linked at the bottom of the entry.

The expected behaviour, now that you have a mental model of my project, is that BarLibrary is automatically loaded by the CLR loader when I load FooLibrary from LoadFromApp via Assembly.LoadFrom(). BarLibrary is necessarily in the same directory as FooLibrary; otherwise, there would be no way that LoadFrom() could find BarLibrary, unless BarLibrary was in the GAC or something like that. This is why VS adds referenced assemblies into your bin/debug (or release) folder when you build an assembly.

The interesting thing is that this exercise turned out to be more of a lesson in reflection than in the loader, but that's how these things end up. I'll tell you what I learned about LoadFrom and then reiterate what Joel told me about reflection.

What I Learned

First, the loader part. So, it does indeed turn out to be true that Assembly.LoadFrom() does resolve dependencies, provided that there are in a findable place, which turns out to be any place that would be consulted for Assembly.Load() and the path (minus filename.dll) of the Assembly.LoadFrom(String path). That wasn't too hard, but was worth the exercise.

You'll also notice that I commented out Assembly.LoadFile(), just above Assembly.LoadFrom(). I tried this too for kicks, which resulted in an exception of type System.Reflection.TargetInvocationException. That's the “something bad happens” and what the exception handler is for above. So, this proves that LoadFile() does not resolve depencies, which I already knew, but was a good test anyway.

Now, onto the reflection aspect. The comments in the source above mostly explain what is going on, I hope. If not, I load an assembly, get a known type from that assembly, then get a known method from that type and then call through on that method with known data. Do remember/realize that this isn’t normally what .net code looks like. Reflection is one of the mechanisms of handling late bound scenarios for .net coders. It is probably the most flexible, but not the most approachable.

Back to the interesting review of reflection … The line that I'm most interested in is the call to t.GetMethod, which is the instance method MethodInfo.GetMethod. I'll re-print it here:

            //Getting the specific method that I'm interested in
            m = t.GetMethod("GetInt", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(System.Int32)},null);

The GetMethod method allows you to specify enough information for the reflection system to get a single method for you from a given type. The thing is that you'll get some type of exception if you haven't specified enough information to single out your desired method from the set of methods on the type. Put another way, you’ll get this exception if the reflection system ends up finding >1 methods that fit your description since the method only returns MethodInfo, not MethodInfo[]. GetMethods() returns MethodInfo[] and obviously doesn’t have this particular problem. So, you need to be pretty specific about the method that you want. It may not be neccesary this version, but you may add overloads next version and forget that your GetMethod call was pretty sloppy and then stuff breaks, which is bad.

It is the first two and fourth parameters that are the most interesting to me. The first one is the method name. So, this differentiates the method from all other methods. You can make the search case insensitive via the BindingFlags, but I would not recommend this approach since the CLR doesn’t work this way and it will slow down the whole operation. The next parameter is the BindingFlags. I've stated that the method I'm looking for is static and public. So, the search will not retreive any instance or internal/protected/private methods that happen to have the same name, which is quite possible. You’ll need to pick among these flags carefully to ensure that you have the correct level of specificity. The fourth parameter specifies the signature of the method. Rememer, the CLR doesn't consider the return type when determining which overload of a method to call, so the signature is just the types of the parameters that the method takes. At this point, you will have provided enough data that the reflection system can narrow its search of methods on the given time to 1, or 0 if it is not there.

The actual code sample that I wrote is on another machine. I'll post it in a day or two when I get a chance. The sample is nothing big, but you'll be able to see how LoadFrom() and LoadFile() work for yourself with my small contrived example.

Saturday, January 15, 2005 5:10:21 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [3]  | 
# Friday, January 14, 2005

I'm currently working on some samples that showcase how best to use shadow copying, set private bin paths and load/use add-ins. I'll start posting these when I get the samples done and come up with a good story around them. My next post, which is almost done, is on Assembly.LoadFrom() and Reflection.

Anyway, I'm curious about what aspects of the CLR Loader and AppDomains that folks are most interested in/confused about. I've seen a bunch of posts on the microsoft.public.dotnet.framework.clr newsgroup that I'm using as a good sample of areas to post on -- hence my first post.

Friday, January 14, 2005 6:39:59 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [12]  | 
# Wednesday, December 15, 2004

I was reading the CLR newsgroup and noticed the following post about unhandled exceptions. I wasn't quite sure exactly how this worked, so I wrote a quick app that caught exceptions from other domains in the defaul domain. This behaviour was what the poster was looking for.

You can download the code [Everett | Whidbey ] to see how it works.

The basic idea is that you register for the AppDomain.UnhandledException event. This event will be fired for any exception that is not handled in any domain in the process. You cannot swallow the exception at this point, so your app will die no matter what. You can, however, do any cleanup that is required or put up some kind of user notification. In the case below, you can see that I tell the user that an unhandled exception occured. I'm sure that this is going to be quite useful to them ;)

Here is the bulk of the code:

    class Program
    {
        static void Main(string[] args)
        {

            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

            AppDomain domain2 = AppDomain.CreateDomain("domain2");
            domain2.CreateInstance("DomainLib", "DomainLib.ThisClassThrows");

        }

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Exception ex = (Exception)e.ExceptionObject;
            Console.WriteLine("Unhandled exception!!");
            Console.WriteLine(ex.InnerException.Message);
        }
    }

Another option, which is a good idea, is to use try/catch blocks in your code around calls to other domains. That way you can catch the exceptions that come across the domain boundary as opposed to just settle for process termination.

Wednesday, December 15, 2004 6:45:03 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [11]  |