Home   Cover Cover Cover Cover
 

Virtual Execution System (VES)

Example "simple probing"

Every time a running application uses a type from another assembly, this assembly has to be loaded. If it is not already available in memory, the CLR searches the Global Assembly Cache (GAC) first of all.
If it cannot find it there and the configuration files do not indicate a CodeBase (= URI that references the file of the assembly), the CLR will use a heuristic, called probling, to find the assembly. Therefore different locations relative to the application base directory will be searched. The example shows those locations.
We have a simple application TestLoading.exe that invokes a method from the assembly MyAssembly.

MyAssembly.cs
public class MyAssembly {
  public static void SayHello () {
    System.Console.WriteLine("Hello World!");
  }
}

TestLoading.cs
public class TestLoading {
  public static void Main () {
    MyAssembly.SayHello();
  }
}

>csc /target:library MyAssembly.cs /nologo

>csc /reference:MyAssembly.dll TestLoading.cs /nologo

>dir /b
MyAssembly.cs
MyAssembly.dll
TestLoading.cs
TestLoading.exe
We will now remove (rename) MyAssembly ...
>rename MyAssembly.dll ma.dll
... and thus prevent that the CLR can find it at runtime. This produces an unhandled exception.
>TestLoading.exe

Unhandled Exception: System.IO.FileNotFoundException: File or assembly name MyAssembly, or one of its dependencies, was not found.
File name: "MyAssembly"
   at TestLoading.Main()

=== Pre-bind state information ===
LOG: DisplayName = MyAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null (Fully-specified)
LOG: Appbase = N:\book\samples\3\VES\
LOG: Initial PrivatePath = NULL
Calling assembly : TestLoading, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null.
===

LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Post-policy reference: MyAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/MyAssembly.DLL.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/MyAssembly/MyAssembly.DLL.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/MyAssembly.EXE.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/MyAssembly/MyAssembly.EXE.
The output of the error message shows that the CLR has tried to find MyAssembly by probing. The last four lines shows which locations the CLR has explored: only the application base directory and a subdirectory with the same name as the assembly looked for are searched for an assembly file with the extensions .dll or .exe.

Example "probing with private searchpath"

In the simple case (see Example "simple probing") the CLR only searches for the assembly file only in the application base directory and a subdirectory with the same name as the assembly looked for.
With an application configuration file (TestLoading.exe.config) we can extend this search with entries in the probing element. All paths listed there have to reference subdirectories of the application directory.
In the example we additionally specify the subdirectory bin.

TestLoading.exe.config
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="bin"/>
    </assemblyBinding>
  </runtime>
</configuration>

Because the assembly file MyAssembly.dll is missing (see Example "simple probing"), the error message again shows us the URIs that the CLR has explored during probing.


>TestLoading.exe

Unhandled Exception: System.IO.FileNotFoundException: File or assembly name MyAssembly, or one of its dependencies, was not found.
File name: "MyAssembly"
   at TestLoading.Main()

=== Pre-bind state information ===
LOG: DisplayName = MyAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null (Fully-specified)
LOG: Appbase = N:\book\samples\3\VES\
LOG: Initial PrivatePath = NULL
Calling assembly : TestLoading, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null.
===

LOG: Private path hint found in configuration file: bin.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Post-policy reference: MyAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/MyAssembly.DLL.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/MyAssembly/MyAssembly.DLL.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/bin/MyAssembly.DLL.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/bin/MyAssembly/MyAssembly.DLL.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/MyAssembly.EXE.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/MyAssembly/MyAssembly.EXE.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/bin/MyAssembly.EXE.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/bin/MyAssembly/MyAssembly.EXE.

Example "probing with culture attribute"

Now there is still the possibility of assigning a so-called culture attribute to an assembly.
In the example we want to create a US-american version of our MyAssembly. We can achieve this with the attribute System.Reflection.AssemblyCultureAttribute, which we set to en-US.

MyAssemblyUS.cs
using System.Reflection;

[assembly:AssemblyCulture("en-US")]

public class MyAssembly {
  public static void SayHello () {
    System.Console.WriteLine("Hello USA!");
  }
}

We now have to regenerate the assembly TestLoading so that it references the new US-american version of MyAssembly. (For this example we can safely ignore the compiler warning. It only points out that assemblies with a specific culture attribute should not be referenced directly (with compiler option /reference:), but only be connection with the application via configuration files.
>csc /target:library /out:en-US\MyAssembly.dll MyAssemblyUS.cs /nologo

>csc /reference:en-US\MyAssembly.dll TestLoading.cs /nologo
warning CS1607: Assembly generation -- Referenced assembly 'MyAssembly' is a localized satellite assembly

>TestLoading.exe
Hello USA!
The CLR employs a different strategy when probing for assemblies with a specific culture attribute as opposed to assemblies with Culture=neutral. All probing URIs always contain a directory whose name corresponds to the culture attribute.
>rename en-US\MyAssembly.dll ma.dll

>TestLoading.exe

Unhandled Exception: System.IO.FileNotFoundException: File or assembly name MyAssembly, or one of its dependencies, was not found.
File name: "MyAssembly"
   at TestLoading.Main()

=== Pre-bind state information ===
LOG: DisplayName = MyAssembly, Version=0.0.0.0, Culture=en-US, PublicKeyToken=null (Fully-specified)
LOG: Appbase = N:\book\samples\3\VES\
LOG: Initial PrivatePath = NULL
Calling assembly : TestLoading, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null.
===

LOG: Private path hint found in configuration file: bin.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Post-policy reference: MyAssembly, Version=0.0.0.0, Culture=en-US, PublicKeyToken=null
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/en-US/MyAssembly.DLL.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/en-US/MyAssembly/MyAssembly.DLL.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/bin/en-US/MyAssembly.DLL.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/bin/en-US/MyAssembly/MyAssembly.DLL.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/en-US/MyAssembly.EXE.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/en-US/MyAssembly/MyAssembly.EXE.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/bin/en-US/MyAssembly.EXE.
LOG: Attempting download of new URL file:///N:/book/samples/3/VES/bin/en-US/MyAssembly/MyAssembly.EXE.