# Tuesday, December 08, 2009

I'm doing a little project right now that requires me to know (among other things) the number of hardlinks for a given file. I have a tool that already will tell me the number of hard links for a given file, but I need to collect a bunch more information, and I really hate calling out to an exe and collecting and parsing its output, as part of a larger app. So, I set out to write that slightly larger app.

Having never written an app that cares about hardlinks, I didn't know whether or not the BCL had APIs that exposed this info. It doesn't. Whether it should expose this info is a whole other question. So, I resorted to p/invoke, which is fine. I did a few searches and found that there isn't too much info out there on doing this from .NET, hence my motivation for writing this post.

I started out with NtQueryInformationFile. I'm pretty sure that the p/invoke signature on p/invoke.net is wrong. I wasn't able to get this function working to my satisfaction, but can share where I ended up, in the hope that it might help someone:

        [DllImport("ntdll.dll", SetLastError=true)] 
        static extern Int32 NtQueryInformationFile(IntPtr fileHandle, ref IO_STATUS_BLOCK IoStatusBlock, [MarshalAs(UnmanagedType.LPArray)] Byte[] arrayBuffer, uint length, FILE_INFORMATION_CLASS fileInformation); 

FWIW, I allocated a byte[2048], and passed in (uint)array.Length as the length paramter. 2k was overkill for what I needed, but at least got me a bunch of bytes. I wasn't too sure what to do next, so decided to look for something easier. I was guessing that I needed to write a struct who fields mapped over that byte[], but I wasn't sure what the meaning of those fields was going to be. I couldn't find any docs that would have that easier, and didn't see any code samples either.

The good news is that I found another function -- GetFileInformationByHandle -- that is much easier to use, and that did work for me.

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool GetFileInformationByHandle(IntPtr hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation);

You can see my app below. For now, it just contains calculates the hard-links, which is the part that I tackled first. I'll now move to writing the rest of my experiment.

using System;
using System.Runtime.InteropServices;
using System.IO;

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

            if (args == null || args.Length == 0)
            {
                Console.WriteLine("Please specify a file to check");
                return;
            }
            else if (!File.Exists(args[0]))
            {
                Console.WriteLine("File doesn't exist");
            }

            

            FileStream fs = null;

            fs = new FileStream(args[0],FileMode.Open,FileAccess.Read);
            BY_HANDLE_FILE_INFORMATION fileInfo;

            Boolean result = GetFileInformationByHandle(fs.Handle, out fileInfo);

            Console.WriteLine(fileInfo.NumberOfLinks);

            fs.Close();

        }

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool GetFileInformationByHandle(IntPtr hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation);


        struct BY_HANDLE_FILE_INFORMATION
        {
            public uint FileAttributes;
            public FILETIME CreationTime;
            public FILETIME LastAccessTime;
            public FILETIME LastWriteTime;
            public uint VolumeSerialNumber;
            public uint FileSizeHigh;
            public uint FileSizeLow;
            public uint NumberOfLinks;
            public uint FileIndexHigh;
            public uint FileIndexLow;
        }

    }
}

 

 

Tuesday, December 08, 2009 7:19:57 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, December 27, 2006

I decided to re-build dasblog (the blog software that I use) on Whidbey (VS 2005) over the holidays. It is something that I had always wanted to do and it seems like the dasblog folks have not yet publicly taken that on. Before anyone gets any strange ideas, I have no desire for a thinkjot-like schism, but wanted to move the codebase to Whidbey and work on getting the software to run under partial-trust. If this all works out, and the dasblog team wants to adopt my changes, cool, otherwise, I'm going to just use it myself.

Anyway, I decided to tackle this task over the holidays. Believe it or not, I almost exclusively use the free VS Express SKUs for my coding work. The "free" part isn't a big deal for me as I have a full copy of VS team suite a couple meters away from me, and I can download and install any program (including "Microsoft Bob") from the MS network that I want. Still, the Express SKUs are super convenient since I can download and install them in about 10mins and they satisfy most of my needs. Anyway, I downloaded the dasblog source and started playing with it. It became clear that I needed to use both VS express C# and VS express Web to get this done since the Web product didn't appear to support multiple projects in a single solution; in fact, it didn't appear to support the solution concept at all. And I then realized that since VS C# doesn't support JIT attach debugging (due to licensing issues), that the whole thing wasn't going to work at all. That's when I reached over for the quite large (requires two hands) VS team suite box to do some "real developlment" ;)

After a fairly lengthy install (and I didn't even install MSDN since I use the web mostly), I started back at it. I was able to get the web and class library projects into one solution in VS. Cool! I then hit F5 and it was immediately clear that something was terribly broken. The web project launched as expected, but was immediately detached from the debugger. Huh? I tried a couple more times, and I had the same experience. I was able to attach VS to WebDev.WebServer.Exe and then refresh the page, and then my breakpoints were hit. This approach though is anything but a good experience.

I had heard that there were some incompatibilities with VS on Vista, but I was under the impression that it was more niche issues, of which this is not. It is also very strange that I didn't have these same problems with the Express products, which I've been using on Vista for months. I wonder why the full product has some additional problems. I'm sure someone in building 41 knows.

Time to install VS 2005 SP1. I went to the following page. I downloaded the Vista-specific update. That didn't work, claiming that I was missing a file or two. I then downloaded and installed the non-Vista-specific SP1 package, which is just shy of 1/2 GB. Ouch! That worked. Upon launching VS, it claimed that I needed the Vista-specific update. Oh, I see, you need to install the generic VS 2005 service pack, and then the Vista-specific update. That was not at all clear to me from the VS 2005 SP1 page. Grrrr. Anyhow, now you can avoid the trouble that I had.

I then launch VS, but it claims that I need to launch the app elevated. I was actually expecting that, but thought that they would have manifested the application to force the elevation dialog. I guess not, or maybe that's still coming. Developers are going to go nuts if they have to remember to right click on the VS 2005 icon and hit "Run as administrator" every time, or just turn off UAC on their dev-boxes, which is a bad idea.

OK, launch VS again, but elevated, and voila, everything is working correctly again. Peace and harmony have now returned to my development experience.

I'm very thanksful that the VS team has pulled off this pretty significant service pack ... *before* Vista is generally available. I'm glad to be back and productive again. The directions on MSDN could use some improvement.

Wednesday, December 27, 2006 10:29:08 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [1]  | 
# Wednesday, December 20, 2006

I wrote a recent post about getting the list of loaded assemblies. That’s a pretty straight-forward operation as shown by the code listed in that post. I’d like to step up the problem one notch by looking at getting the list of assemblies from another domain. Seems like a very reasonable thing to do ... Or we’ll see …

To properly setup this example, I need to create another domain and keep a reference to that domain. That’s easy:

            //Create new domain

            AppDomain domain = AppDomain.CreateDomain("domain2");

 

Next, we need to load some code in that domain, or else there won’t be any assemblies loaded there to actually query. Note that Host is one of my types, as you’ll see later. The method below loads the DomainHost assembly in domain2, creates an instance of the DomainHost.Host type in domain2 and also returns a reference to that instance in the current domain. That’s why you see the cast to Host.

            Host host = (Host)domain.CreateInstanceAndUnwrap("DomainHost", "DomainHost.Host");

 

OK … this is the part that where it gets interesting. It is actually a little non-obvious on how you are intended to get the list of loaded assemblies from the other domains. Let’s first look at the most intuitive approach for doing this. There is the same GetAssemblies() method on AppDomain that I used in the last post.  So, given that I have a reference to the domain2 AppDomain instance, why not just call GetAssemblies() on it? This is what the code would look like:

            domain.GetAssemblies();

 

For a variety of reasons, assemblies are not marked as serializable objects, which means that they cannot be remoted across an appdomain (or any other) boundary. You can get around this limitation by remoting and then loading an assembly as a Byte[], but that’s a different blog post. This call gets around the limitation by remoting an array of representative AssemblyName objects, as opposed to the actual assemblies. The loader then does the equivalent of the following, assuming the AssemblyName[]is called asmNames:

            foreach (AssemblyName asmName in asmNames)

            {

                Assembly.Load(asmName);

            }

This behavior is not really expected or desirable. First, you really want the AssemblyName objects, not the Assembly objects, and you definitely do not want to cause the assemblies to be loaded in this domain. In addition, if the assemblies are not located in the GAC, and the other domain has a different AppBase, then it is very likely that the assembly loads will fail, resulting in the loader throwing an exception that you might not be prepared to catch. Ouch. That’s really bad. It is also important that not all assemblies play nicely with this behavior. For example, Reflection.Emit assemblies cannot be re-loaded cross domain, for fairly obvious reasons. Mixed-mode assemblies have another set of problems. So, let’s skip that option.

Another option is to call AppDomain.GetAssemblies() in the other domain, and then to remote the Assembly[] back through to the current domain.  That will have the same effect as what I just discussed above.

 I’ve skipped over some important details that I need to explain. My DomainHost.Host type is a regular old that type that happens to inherit from System.MarshalByRefObject. The fact that it inherits from this type is more of a marking than anything else, as I don’t override any of MBRO’s methods, nor do I have to know what they are. This is very conceptually similar to marking a type with the [Serializable] attribute. The difference is that MBRO provides copy-by-ref semantics as opposed to copy-by-value across a boundary, which is what the [Serializable] attribute provides. This means that MBRO-inherited types can be remoted across a domain, process or even machine boundary as a reference that you can easily call across. The method calls only affect the domain in which the type actually resides (not where the reference resides), with the exception that return types (which must be either MBRO or [Serializable]) are returned to where the call was made from (the current domain). The reference is called a transparent proxy, and you can see that in the debugger when you try to peer into what turns out to be the largely opaque System.Runtime.Remoting.Proxies.__TransparentProxy type. Woah! The fact that DomainHost.Host is MBRO is going to turn out quite useful, as we’ll see.

OK, now to the real solution. I need to add a method to DomainHost.Host that I can call that returns AssemblyName[] and that does not interact with the loader in any way on this side of the domain boundary, as I want to avoid any assembly loads on these AssemblyName objects. Let’s see what the method would look like:

        public AssemblyName[] GetAssemblyNames()

        {

            AssemblyName[] names;

            Assembly[] asms;

 

            asms = AppDomain.CurrentDomain.GetAssemblies();

            names = new AssemblyName[asms.Length];

 

            for (Int32 i = 0; i < asms.Length; i++ )

            {

                names[i] = asms[i].GetName();

            }

 

            return names;

        }

This method uses the AppDomain.GetAssemblies() method to get the list of loaded assemblies, but doesn’t return that. It creates an equal length AssemblyName[] array to the Assembly[] that it already has.  It then populates that array with the assembly name of each of the assemblies. After the assembly name array is populated, the method returns that array of serializable objects back to the caller, which happens to be on the other side of the appdomain boundary. And how does one call such a method on the other side of the appdomain boundary? Easy:

            AssemblyName[] asmNames = host.GetAssemblyNames();

 

This ease of cross-boundary calls is the beauty of .NET Remoting. You just call methods as if the instances were located directly beside you. Cool.

Well, that’s now about it. Let’s take a look at the whole program:

Main program:

using System;

using System.Reflection;

using DomainHost;

 

namespace GetAssemblyNamesFromDomain

{

    class Program

    {

        static void Main(string[] args)

        {

            AppDomain domain;

            Host host;

            AssemblyName[] asmNames;

 

            //Create new domain

            domain = AppDomain.CreateDomain("domain2");

//Load assembly in domain2 and create instance of DomainHost.Host

//A reference to the instance of DomainHost.Host is returned

            host = (Host)domain.CreateInstanceAndUnwrap("DomainHost", "DomainHost.Host");

 

            //Most obvious method for getting the list of loaded assemblies.

            //This method will cause the assemblies in the remote domain to

            //be loaded in this domain, which frequently won't work. Ouch!

            //domain.GetAssemblies();

 

            asmNames = host.GetAssemblyNames();

            Console.WriteLine();

            Console.WriteLine("Printing assemblies:");

            foreach (AssemblyName asmName in asmNames)

            {

                Console.WriteLine(asmName.FullName);

            }

 

        }

    }

}

 

DomainHost.Host (in DomainHost.dll)

using System;

using System.Reflection;

 

namespace DomainHost

{

    public class Host : MarshalByRefObject

    {

        public Host()

        {

            Console.WriteLine("Loading host in domain {0}",AppDomain.CurrentDomain.FriendlyName);

        }

 

        public AssemblyName[] GetAssemblyNames()

        {

            AssemblyName[] names;

            Assembly[] asms;

 

            asms = AppDomain.CurrentDomain.GetAssemblies();

            names = new AssemblyName[asms.Length];

 

            for (Int32 i = 0; i < asms.Length; i++ )

            {

                names[i] = asms[i].GetName();

            }

 

            return names;

        }

 

    }

}

 

The output of the program looks like:

Loading host in domain domain2

Printing assemblies:

mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

Microsoft.VisualStudio.HostingProcess.Utilities, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

DomainHost, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

 

The fact that I see “Microsoft.VisualStudio.HostingProcess.Utilities” loaded is a VS weirdness. VS is loading an assembly in domain2 to somehow “help me”, but I don’t know why. This only occurs when I’m running/debugging my app through VS. If I run the program outside of VS, I don’t see that assembly loaded. You have noticed executables ending in vshost.exe. That’s a similar issue, but for another day.

Wednesday, December 20, 2006 8:40:10 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, December 07, 2006

A guy from a well-known company mailed me asking how to avoid deploying statically referenced assemblies that he knows will not be loaded at runtime. The issue is that the assembly is being loaded, but he doesn’t believe that it is being actually used. His current workaround is to deploy the assembly to avoid FileNotFound exceptions, which nobody likes.

I have two questions for the guy:

1.      Why are you so certain that the assembly will not be needed?

2.      Is the assembly used in other scenarios, just not this one? There must be a reason that it is statically referenced by your app in the first place.

 

As you can guess, this whole exercise is a bit of a dangerous situation. You can spend a lot of time ensuring that certain code paths will never be called, and then your users do something unexpected and low-and-behold, that darned FileNotFound exception is thrown. Ouch.

Why is this a problem?

Anyway, the core of the problem is at the level of the JIT (just-in-time compiler). The JIT jits code (MSIL) at a method-level basis.  The following is how things work at a high-level:

1.      The app calls a method

2.      The method cannot be executed because it hasn’t yet been jitted to machine code

3.      The JIT compiles the method (MSIL) into x86 (or X64 or IA64) code

4.      For every method call that the JIT sees, it must fully understand the signature of that method, specifically the return type and the arguments/parameters. This requirement may cause an assembly load.

5.      The method can now be called. The method will not need to be jitted again (at least in this app domain).

 

For example, the return type might be a value type, requiring the JIT to know how large that type is. To get that information, the JIT must load the type, and must request that the assembly (in which the type is contained) be loaded if it is not already loaded. This is still the case even if the method call is within an if statement, and might not actually be called.

Code that exposes the problem

As already suggested, you are going to run into this problem anytime you have a direct cross-assembly method call anywhere in a method you know that you will call, and hence JIT. This is even true under an if statement where the condition will not be true in this scenario.

        static void Method1()

        {

            if (condition)

            {

                //directly calling method from ClassLibrary2

                Class2.Multiply(100, 200);

            }

        }

 

Code that avoids this problem

It is pretty easy to avoid this problem. Write the following code instead.

        static void Method1()

        {

            if (condition)

            {

                //indirectly calling method from ClassLibrary2

                Method2();

            }

        }

        static void Method2()

        {

                //directly calling method from ClassLibrary2

                Class2.Multiply(100, 200);

        }

As you can see, the call to Class2.Multiply() is now an indirect call and does not require the JIT to know anything about the Class2 or require ClassLibrary2 to be loaded (the symptom to be avoided), unless of course the condition is met and Method2() is called. This trick is a little awkward sometimes, but it is a great option to at least defer and even completely avoid assembly loads.

Gotcha

Unfortunately, there is a gotcha. The JIT does optimize code by inlining methods. When this happens, you lose your indirect call, and you are now in the same bad boat you were in before. I don’t know much about the JIT inlining policy, so cannot provide a list of where this happens. This is merely a caveat that my workaround doesn’t work in all cases.  If folks are interested, I can talk to the folks on the JIT and perf teams to learn more about this gotcha.

Thursday, December 07, 2006 8:25:44 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [2]  | 
# Tuesday, December 05, 2006

We often talk about the loaded assemblies list over here. This is the list of assemblies currently loaded in the app domain. Big surprise. There isn't anything incredible special about this list. It is pretty easy to access and use. At the minimum, you can print out the list of assemblies. Beyond that, you can load and instantiate any of the types within those assemblies. That's where reflection comes in.

Here's some code that prints out the list of loaded assemblies:

using System;
using System.Reflection;

namespace GetLoadedAssemblies
{
class Program
{
static void Main(string[] args)
{
Assembly[] asms;

asms = AppDomain.CurrentDomain.GetAssemblies();

Console.WriteLine("There are {0} assemblies loaded:", asms.Length);
foreach (Assembly asm in asms)
{
Console.WriteLine(asm.FullName);
}

Console.WriteLine();
Console.WriteLine("The currently executing assembly is:");
Console.WriteLine(Assembly.GetExecutingAssembly().FullName);

}
}
}
Tuesday, December 05, 2006 11:51:00 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, November 29, 2006

I took another look at the FileVersion sample. I wish the API was actually a little different. The API actually makes sense as a general use API, but it isn't as user-friendly as I would like. I wish that there were an instance method on the Assembly class called "GetFileVersion" or something like that it took nothing and returned a Version class.

Here is more of less what it would look like, except that the GetFileVersion wouldn't be static, it wouldn't take anything and would be on the assembly class.

If you look @ the FileVersion class, there is a lot of stuff on there, and it is a super wonky API anyway. I don't understand why it has a single static method that more or less acts that the instance constructor. Why not just have a constructor that takes a string or a FileInfo or even a FileStream. Bad API design. I prefer the Version class a lot more since it is super simple. I

using System;
using System.Reflection;
using System.Diagnostics;
namespace FileVersion
{
class Program
{
static void Main(string[] args)
{
Assembly asm;
Version ver;

asm = Assembly.Load("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
ver = GetFileVersion(asm);
Console.WriteLine(ver.ToString());
}

static Version GetFileVersion(Assembly asm)
{
FileVersionInfo versionInfo;
Version ver;

versionInfo = FileVersionInfo.GetVersionInfo(asm.Location);
ver = new Version(versionInfo.FileMajorPart, versionInfo.FileMinorPart, versionInfo.FileBuildPart, versionInfo.FilePrivatePart);

return ver;
}
}
}

If you look @ the FileVersion class, there is a lot of stuff on there, and it is a super wonky API anyway. I don't understand why it has a single static method that more or less acts like an instance constructor. Why not just have a constructor that takes a string or a FileInfo or even a FileStream. Bad API design. I prefer the above method (for the assembly case) that returns the Version class since it is super simple. I realize that the native file version is a string, so can contain more stuff, but the 4-part version number is really all I want.

Wednesday, November 29, 2006 3:39:29 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

The file version number is a native code concept – meaning not originating from the .NET Framework. This version number is a resource found within the resource section of the windows PE (portable executable) format of a managed or native code dll. This resource is named “FILEVERSION”. This version number is used for information purposes only, not for any runtime purposes such as binding. In addition, this version number does not have to conform to a particular format, but is only a string, although it does typically takes the form of a simple four-part number (i.e. 1.2.3.4).

Reading the File Version

The easiest way to view this number is to view the properties of a file in Windows Explorer. The version number listed is the file version number. The product version is also listed, although I don’t know how the two numbers differ exactly. Naturally, you can access the file version from code. The following code does just that, largely using the System.Diagnostics.FileVersionInfo class, which I’ve never used before. In fact, I had to ask someone else on the loader team for that information.

using System;

using System.Reflection;

using System.Diagnostics;

namespace FileVersion

{

    class Program

    {

        static void Main(string[] args)

        {

            Assembly asm = Assembly.Load("mscorlib, Version=2.0.0.0, Culture=neutral,  PublicKeyToken=b77a5c561934e089");

            System.Diagnostics.FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(asm.Location);

            Console.WriteLine(fvi.FileVersion);

        }

    }

}

 

Setting the File Version

The CLR provides an assembly-level custom attribute to set this version number for an assembly from managed code. This attribute is called System.Reflection.AssemblyFileVersion. You can see how to set it below.

using System;

using System.Reflection;

 

[assembly:System.Reflection.AssemblyFileVersion("2.3.4.5")]

 

namespace ConsoleApplication1

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("I just set the file version!");

        }

    }

}

 

You can actually set this attribute in Visual Studio 2005 via the properties menu. In that case, you cannot set it in code, as I’ve done above, since you’ll then have two instances of the attribute. You only need to set the attribute directly, as I’ve done  above, if you are using the compiler directly, from the commandline.

Wednesday, November 29, 2006 12:00:36 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, October 26, 2006

The CLR loader offers a few APIs for loading assemblies, each of which have a slightly different model and behaviour for how they go about the task. I'd like to cover those and hopefully set folks on the best path for using loading assemblies.

The APIs that I have in mind are:

  • Assembly.Load(), and
  • Assembly.LoadWithPartialName()

First, you need to understand the concepts of fully-specified and partial assembly names.  A fully specified name contains the following parts: the simple name, version, culture, and public key or public key token. A partial name contains at least the simple name and optionally any of the other parts of the full-specified name. This concept is most relevant to the textual identity of an assembly. For example, here is the fully-specified assembly textual identity for v2.0 System.dll: "System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089". The textual identity is a specially formatted string that is used to describe some or all of the aspects of identifying an assembly.

Assembly.Load() takes a string as one of the overloads. The textual identity, as you see formatted above, is just the sort of string that Load() is expecting. Load() also takes other types, such as AssemblyName, but that's not important for the moment. The textual identity can be fully or partially specified, and which one it is has an important impact on the way that these loader APIs operate. The one you see above for System.dll is fully specified, since all the parts are there. Note that there is an additional part (or attribute) of the textual indentity that I've missed -- ProcessorArchitecture -- but that complicates the discussion too much for not much benefit, so I'm not going to cover it here.

The following bit of code shows the use of these APIs with full- and partially-specified names. The comments inline should pretty well explain what to expect

using System;
using System.Reflection;

namespace BindingByIdentity
{
class Program
{
static void Main(string[] args)
{
Assembly asm;

//LoadWithPartialName() looks in both the appbase and the GAC, looking for the best match,
//where "best match" isn't very clearly defined
//In addition, this method has been deprecated, which means "don't use this anymore, and it may be removed later"
try
{
Console.WriteLine("Calling LoadWithPartialName");
asm = Assembly.LoadWithPartialName("System");
Console.WriteLine("Loaded: {0}",asm.FullName);
}
catch(Exception e)
{
Console.WriteLine("LoadWithPartialName threw with the following exception:");
Console.WriteLine(e.Message);
}


//Load() with a partial name looks only in the appbase
//There is no gaurantee that you will get the assembly that you want
//In the case that you have private bin paths specified, there are no order gaurantees
//This particular use of the Assembly.Load() will always throw, since this assembly will not be found (because it is GAC'd)
try
{
Console.WriteLine("Calling Load");
asm = Assembly.Load("System, PublicKeyToken=b77a5c561934e089");
Console.WriteLine("Loaded: {0}", asm.FullName);
}
catch(Exception e)
{
Console.WriteLine("Load threw with the following exception:");
Console.WriteLine(e.Message);
}

//Load() with a fully-specified name looks in the appbase and the GAC and gaurantees that you
//will get the assembly that you asked for
try
{
Console.WriteLine("Calling Load");
asm = Assembly.Load("System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
Console.WriteLine("Loaded: {0}", asm.FullName);
}
catch (Exception e)
{
Console.WriteLine("Load threw with the following exception:");
Console.WriteLine(e.Message);
}


}
}
}

Output:

Calling LoadWithPartialName
Loaded: System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Calling Load
Load threw with the following exception:
Could not load file or assembly 'System, PublicKeyToken=b77a5c561934e089' or one
 of its dependencies. The system cannot find the file specified.
Calling Load
Loaded: System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

The moral of this story is that Assembly.LoadWithPartialName() is always bad and shouldn't be used since its behaviour isn't well-defined or predictable, and that you should always fully-specify the textual identity strings that you pass into Assembly.Load(). It may be the case that partially specified strings "work" since the assemblies you are attempted to load are always going to be in the app-base, but the fully-specified names do make your code and your intentions more clear, particularly for the next guy that has to look at the code you wrote. The funny thing is that sometimes "the next guy" is you, just two months later ;)

There is also the case that your code might not be strong-named. You should still specify everything but the publickey/token in that case.

Thursday, October 26, 2006 7:43:59 AM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Saturday, December 03, 2005

Here is a better example of using an anonymous delegate that proves, in my mind, that they are lexical closures. I sure hope my definition of closures is correct ;)

Here's the code. Please do guess what it does or better yet, compile and run it. The important aspect is to guess which values of "s" do or do not match.

using System;

using System.Threading;





namespace AnonDelegateTest2

{

class Program

{

delegate void FunkyDelegate();



static void Main(string[] args)

{

FunkyDelegate fd = GetDelegate();



for (Int32 i = 0; i < 10; i++)

{

fd();

}

}



static FunkyDelegate GetDelegate()

{

String s = DateTime.Now.Ticks.ToString();



FunkyDelegate fd = delegate()

{

Console.WriteLine("Entering fd");

Console.WriteLine(s);

s = DateTime.Now.Ticks.ToString();

Thread.Sleep(100);

Console.WriteLine(s);

Console.WriteLine("Leaving fd");

Console.WriteLine();

};



return fd;

}

}



}
Saturday, December 03, 2005 2:06:27 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, November 30, 2005

I posted an interesting bit of C# a couple weeks ago relating to anonymous delegates. I asked in that post what the result of the following code is. Here is the code and then the result

Code:
using System;
using System.Threading;

namespace AnonMethods
{
    class Program
    {
        static void Main(string[] args)
        {
            for (Int32 i = 0; i < 20; i++)
            {
                Thread t = new Thread(delegate() { Thread.Sleep(10); Console.WriteLine(i); });
                t.Start();
            }
            Thread.Sleep(5000);
        }
    }
}

Result:
6
6
6
6
6
9
12
12
12
13
13
13
15
15
19
20
20
20
20
20

Why?
That's the strangest result from a for loop that I've ever seen. First, I'd suggest that you compile the code for yourself (remember, C# Express is free) and then take and then decompile it in either ildasm or Reflector. I find the C# in Reflector a whole lot easier to read than the IL, so I'd recommend that you start with it. I imagine that you'll get a real kick out of what you see.

First, I'd like to caveat my explanation by saying that this is a CLR guy's explanation of what the C# compiler is doing. I haven't talked to the C# team, but just took a look at the code emitted by the compiler, which both you and I are free to ponder. All that being said, here's the basic idea of what I think is going  on without going into great detail of the mechanics of anonymous delegates.

Once the C# source code is compiled, the anonymous delegate goes away and is replaced by the mechanism that I'm about to describe. Put another way, anonymous delegates are a C# source-code-only feature. For every anonymous delegate, there is a strangely, but probably predictably, named nested class added to the class that indirectly contained (within one of the methods within the class) the anonymous delegate. The class, as you might expect, exposes some surface area that is accessed from the parent class. The class is actually private, which means it cannot be accessed from anywhere but the parent class. There is a default constructor, which does nothing. There is a method that is the anonymous delegate transformed into a regular named method. Remember, anonymous delegates are a C#, not a CLR feature, so the CLR does need a named method to call. Lastly, there are a set of fields exposed on this compiler-generated class -- and this is the part that gets interesting -- that are the local variables that are accessed from both the containing method and the anonymous delegate. Variables that are defined in the containing method but not accessed from within the anonymous delegate or that are defined and used within the anonymous delegate do not get this special treatment. As you might guess, the C# compiler wires up the method that takes the delegate and the generated named method. In addition, all accesses to the shared local variables are wired up through the public fields on the generated class instead of through the actual locals. Very interesting.

OK, so that's the basic explananation of how anonymous delegates work. There are some other subtleties that I noticed, but they are not important for this explanation. I'm going to get further insight on those from the C# team and will post on those when I learn more about them.

So, then, how does all that lead to the strange and unexpected results from the for loop. Well, since the "i" variable is accessed by both the containing method and the anonymous delegate, the C# compiler rewires all accesses to "i" to the "i" field on the generated class. And since each call to the anonymous delegate in our example does its work on a separate thread, then "i" is updated by the for loop on a different schedule than it is written by Console.WriteLine in the anonymous delegate. That's why the value printed out by each call to the anonymous delegate is essentially a race condition between the for loop continually iterating and threads being created and getting time on the processor(s).

Another aspect of this is that shared locals with anonymous delegates essentially turn value types into reference types. That's a really strange behaviour and realization.

Like I said in the earlier post, the trick is determining a scenario where this behaviour is useful. I haven't found that yet, although I'm sure it will be very interesting once I find it.

Wednesday, November 30, 2005 3:51:11 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [5]  | 
# Friday, November 11, 2005

What does the following C# code do? Guess and then run it.

using System;
using System.Threading;

namespace AnonMethods
{
class Program
{
static void Main(string[] args)
{
for (Int32 i = 0; i < 20; i++)
{
Thread t = new Thread(delegate() { Thread.Sleep(10); Console.WriteLine(i); });
t.Start();
}
Thread.Sleep(5000);
}
}
}

We were playing with this and similar code in the experts area at the Ottawa VS launch yesterday. Fun, fun.

My task ahead is to find a scenario that makes the subtleties of anonymous delegates useful. Anonymous delegates are certainly useful. It is the trick above with "i" that I'm talking about. I'll post in a couple days with more data on what is going on.

Friday, November 11, 2005 2:51:50 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [1]  | 
# 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]  | 
# 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]  | 
# 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]  |