Microsoft KB Archive/897297

From BetaArchive Wiki

Article ID: 897297

Article Last Modified on 11/14/2007



APPLIES TO

  • Microsoft Visual Basic 2005
  • Microsoft Visual Basic .NET 2003 Standard Edition
  • Microsoft Visual Basic .NET 2002 Standard Edition




INTRODUCTION

This article discusses how to consume assemblies that are located in a folder than is different from the application base folder in a Microsoft Visual Basic .NET or Microsoft Visual Basic 2005 solution.

MORE INFORMATION

When you run a Visual Basic .NET or Visual Basic 2005 application, the common language runtime (CLR) expects to locate any assemblies that the application uses in either the global assembly cache or the application folder. When the CLR does not successfully bind to an assembly, you receive an error message that is similar to the following:

System.IO.FileNotFoundException. File or assembly name AssemblyName, or one of its dependencies, was not found.

You can use many methods to locate an assembly that is located in a different folder. This article describes the following three methods.

Method 1: Install the assemblies in the global assembly cache

This method requires that you sign an assembly with a strong name. To sign an assembly with a strong name and to then install the assembly in the global assembly cache, follow these steps:

  1. Name an assembly by using a strong name. To do this, follow these steps:
    1. Use the Strong Name tool (Sn.exe) that is included with the Microsoft .NET Framework software development kit (SDK) to generate a cryptographic key pair.

      At the Microsoft Visual Studio .NET or Microsoft Visual Studio 2005 Command Prompt, type the following command:

      sn -k AssemblyName.snk

      This command generates and stores a key pair in a file that is named AssemblyName.snk.
    2. Include the following assembly-level attribute in the source code (AssemblyInfo.vb):

      <Assembly: AssemblyKeyFile("AssemblyName.snk")>
  2. Use the Global Assembly Cache Tool (Gacutil.exe) to register the .NET Framework assembly in the global assembly cache. To do this, type the following command at the Visual Studio .NET Command Prompt:

    gacutil /i AssemblyName.dll

For more information about how to work with assemblies and with the global assembly cache, visit the following Microsoft Developer Network (MSDN) Web site:

For more information about how to sign an assembly with a strong name, visit the following MSDN Web site:

Note This method may be difficult and time-consuming if many assemblies exist and if the assemblies have dependencies on Microsoft Component Object Model (COM) objects. Any assembly dependencies must also be discoverable by the CLR. Therefore, if you plan to install your assembly to the global assembly cache, also install the dependencies of the assembly into the global assembly cache.

Method 2: Use an Application.Config file together with the CodeBase tag

By using an application configuration file, you can specify the location at which the CLR should look for dependent assemblies. Specifically, use the Codebase tag. By using this tag, you can put your assemblies in a separate folder. However, this method still requires that you name the library assembly by using a strong name. To use the application configuration file, follow these steps:

  1. Compile your library assembly.
  2. Sign the assembly by using a strong name.
  3. From your main application, add a reference to your library assembly, and then compile the main application.
  4. Obtain the public key token from your strongly named library assembly. To do this, follow these steps:
    1. Click Start, click All Programs, and then click Microsoft Visual Studio .NET 2003.

      Note In Visual Studio 2005, click Start, click All Programs, and then click Microsoft Visual Studio 2005.
    2. Click Visual Studio .NET Tools, and then click Visual Studio .NET 2003 Command Prompt.

      Note In Visual Studio 2005, click Visual Studio 2005 Tools, and then click Visual Studio .NET 2005 Command Prompt.
    3. Change the directory to the location of your library assembly. Typically, the location is the Bin folder of your library assembly project.
    4. Type the following command, and then press ENTER:

      SN -T MyLibrary.dll

      Note Replace MyLibrary with the name of your library assembly. To make sure that the correct value is returned, make sure that you use an uppercase T in the -T switch.
    5. This command returns a hexadecimal value that represents the token for the public key of your library assembly. Make a copy of the hexadecimal value that will be used in the application configuration file.
  5. Obtain the assembly version from your strongly named library assembly. To obtain the assembly version, use one of the following methods:
    • Method A: Windows Explorer file properties
      1. In Windows Explorer, right-click your library assembly, and then click Properties.
      2. In the Properties dialog box, click the Version tab.
      3. Under Other version Information, click Assembly Version. Make a copy of this version value that will be used in the application configuration file.
    • Method B: MSIL Disassembler (ILDASM)
      1. At the Visual Studio .NET 2003 Command Prompt, type ILDASM, and then press ENTER.
      2. On the File menu, click Open.
      3. Click your custom assembly, and then click Open.
      4. In the bottom pane, locate the assembly version (.ver). The following is an example of the assembly version:

        .assembly yourAssemblyName
        {
          .ver 1:0:1969:29451
        }

        Note In this example, the assembly version is 1.0.1969.29541.

  6. Create an application configuration file. To do this, follow these steps:
    1. Paste the following XML code in Notepad:

      <configuration>
         <runtime>
            <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
               <dependentAssembly>
                  <assemblyIdentity name="MyLibrary"
                                    culture="neutral" 
                                    publicKeyToken="fa4e781ae585ee8a"/>
      
                  <codeBase version="1.0.1074.32347"
                      href="FILE://C:/assemblies/myLibrary.dll"/>
               </dependentAssembly>
            </assemblyBinding>
         </runtime>
      </configuration>
    2. Change the following XML element attributes.
      Element attribute Make this change
      assemblyIdentity name Change MyLibrary to the name of your library assembly.
      assemblyIdentity publicKeyToken Change the publicKeyToken attribute to the public key token value that you copied in step 4.
      codeBase version Change the version attribute to the version value that you copied in step 5.
      codeBase href Change the href attribute to point to the full path name and the file name of your library assembly.
    3. Save the file as the main assembly .exe file name. Use .config as the file name extension. For example, if your main assembly is named "MyProject.exe," the application configuration file name is "MyProject.exe.config." You must save this file in the same folder in which your main application assembly is located.

For more information, visit the following MSDN Web sites:

Method 3: Use the System.Reflection.Assembly.LoadFrom method

This method uses the Assembly.LoadFrom method to explicitly load an assembly from a fully qualified path name and from a fully qualified file name. To do this, follow these steps:

  1. Compile your library assembly.
  2. Use code that is similar to the following code example to load your assembly:

    Dim yourAssembly As System.Reflection.Assembly = _
          System.Reflection.Assembly.LoadFrom("c:\yourAssembly.dll")

Note If you have any dependent assemblies, you should locate them in the same path where the main assembly is located.

For more information about the Assembly.LoadFrom method, visit the following MSDN Web site:

Method 4: Use the AssemblyResolve event

The AssemblyResolve event occurs whenever the CLR unsuccessfully tries to bind to an assembly. Use the AddHandler method in the application to add an event handler that returns the correct assembly whenever the AssemblyResolve event occurs.

Note This method does not require that you name the assemblies by using strong names.

The AssemblyResolve event handler must return an [Assembly] object that represents the assembly to which the CLR must bind. Typically you can use the Assembly.LoadFrom method to load the assembly. Then, return the loaded assembly.

Note The event handler must be located in a procedure that does not contain any references to the relocated assemblies. Additionally, the event handler must be called before any code that depends on the relocated assemblies is called.

The following code is an example of an application that loads an assembly by using the AssemblyResolve event:

Module Module1
    Sub Main()
        Dim f As Form1

        'Set up event handler for AssemblyResolve event
        AddHandler AppDomain.CurrentDomain.AssemblyResolve, _
                   AddressOf MyResolveEventHandler

        f = New Form1()
        Application.Run(f)
    End Sub

    Function MyResolveEventHandler(ByVal sender As Object, _
                                   ByVal args As ResolveEventArgs) As [Assembly]

        'Load the assembly from the correct location and return the assembly
        'This handler is only called if we try to bind to the assembly and the attempt fails.
        Dim MyAssembly As [Assembly]
        MyAssembly = [Assembly].LoadFrom("C:\assemblies\MyLibrary.dll")
        Return MyAssembly
    End Function
End Module


'Some sample code in Form1 which depends on the external assembly
Private Sub Button1_Click(ByVal sender As System.Object, _
                          ByVal e As System.EventArgs) Handles Button1.Click

        Dim x As MyLibrary.Application
        x = New MyLibrary.Application()
        x.MyMethod()
    End Sub
End Class

For more information about the AppDomain.AssemblyResolve event, visit the following MSDN Web site:

REFERENCES

For more information, click the following article number to view the article in the Microsoft Knowledge Base:

302340 How to create an assembly with a strong name in .NET Framework SDK



Additional query words: fail GAC

Keywords: kbvs2005swept kbvs2005applies kbprogramming kbhowto kbinfo KB897297