Microsoft KB Archive/828991

From BetaArchive Wiki

Article ID: 828991

Article Last Modified on 4/19/2007



APPLIES TO

  • Microsoft .NET Framework 1.1
  • Microsoft .NET Framework 1.0
  • Microsoft Common Language Runtime (included with the .NET Framework 1.1)
  • Microsoft Common Language Runtime (included with the .NET Framework) 1.0
  • Microsoft Visual Studio .NET 2003 Enterprise Architect
  • Microsoft Visual Studio .NET 2003 Enterprise Developer
  • Microsoft Visual Studio .NET 2003 Professional Edition
  • Microsoft Visual Studio .NET 2003 Academic Edition
  • Microsoft Visual Studio .NET 2002 Enterprise Architect
  • Microsoft Visual Studio .NET 2002 Enterprise Developer
  • Microsoft Visual Studio .NET 2002 Professional Edition
  • Microsoft Visual Studio .NET 2002 Academic Edition
  • Microsoft Visual C# .NET 2003 Standard Edition
  • Microsoft Visual C# .NET 2002 Standard Edition
  • Microsoft Visual Basic .NET 2003 Standard Edition
  • Microsoft Visual Basic .NET 2002 Standard Edition




SYMPTOMS

When you call the MethodInfo.Invoke method, you may receive the following error message:

An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
Additional information: Exception has been thrown by the target of an invocation.


You may also receive an additional error message that is similar to the following error message:


Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.FileLoadException: 'ClassLibrary1' is not a valid file.
File name: "ClassLibrary1"
at ClassLibrary2.Class1.GetString()

CAUSE

You receive the System.Reflection.TargetInvocationException error because the common language runtime calls the MethodInfo.Invoke method by using reflection.

When you load an assembly by using the Assembly.LoadFrom method, the common language runtime places the loaded assembly in the LoadFrom context of your application. Any probes for the dependencies of the assembly first probe the current application directory. If this probe fails, the common language runtime then probes the LoadFrom context of your application.

You may load an assembly that has a simply-named dependency that has the same file name as a file in the current application directory. When you try to invoke a method in the loaded assembly by using the MethodInfo.Invoke method, and the invoked method uses the dependency, the common language runtime first probes the current directory path. When the common language runtime finds a file that has the same file name as the dependency, the probe stops. However, if this file does not have the same assembly identity as the dependency, the assembly bind fails, and the common language runtime generates a System.IO.FileLoadException error that is passed to the System.Reflection.TargetInvocationException error. Therefore, you may notice the behavior that is mentioned in the "Symptoms" section.

WORKAROUND

To work around this problem, either rename the file that exists in the current application directory so that this file has a different file name from the dependency of the loaded assembly, or install the dependency in the Global Assembly Cache (GAC) that has precedence over the current application directory during probing.

Rename the File That Exists in the Current Application Directory

Note The following procedure is based on the sample that is mentioned in the "More Information" section. Therefore, the code and the file names in this procedure may differ from your code and from your file names.

  1. Locate the ClassLibrary1.dll text file that you created in step 16 of the "More Information" section.
  2. Change the name of the ClassLibrary1.dll file to any name other than ClassLibrary1.dll.


For example, you may rename this file to Renamed_ClassLibrary1.dll.

  1. Run your application from the command prompt.


You notice the following output:

ClassLibrary1.GetString() result: ClassLibrary1.Class1

Install the Dependency in the GAC

Note The following procedure is based on the sample that is mentioned the "More Information" section. Therefore, the code and the file names in this procedure may differ from your code and from your file names.

  1. From a Microsoft Visual Studio .NET command prompt, change the directory path of the location of the ClassLibrary1.dll assembly that you built in step 3 of the "More Information" section.
  2. At the Visual Studio .NET command prompt, run the following command to create a strong name:

    sn -k C:\Key.snk
  3. If you are using Microsoft Visual C# .NET, locate the following code in the AssemblyInfo.cs file of the ClassLibrary1 project:

    [assembly: AssemblyKeyFile("")]

    If you are using Microsoft Visual Basic .NET, locate the following code in the AssemblyInfo.vb file of the ClassLibrary1 project:

    <Assembly: AssemblyVersion("1.0.*")>
  4. If you are using Visual C# .NET, replace the code that you located in the previous step with the following code:

    [assembly: AssemblyKeyFile("C:\\Key.snk")]

    If you are using Visual Basic .NET, add the following code after the code that you located in the previous step:

    <Assembly: AssemblyKeyFile("C:\Key.snk")>
  5. Build the ClassLibrary1 project to re-create the ClassLibrary1.dll assembly.
  6. Run the following command at the Visual Studio .NET command prompt to install the ClassLibrary1.dll assembly in the GAC:

    gacutil -if ClassLibrary1.dll
  7. In the ClassLibrary2 project, delete the existing project reference to the ClassLibrary1.dll assembly.
  8. In the ClassLibrary2 project, add a project reference to the ClassLibrary1.dll assembly that you rebuilt in step 5.
  9. Build the ClassLibrary2 project to re-create the ClassLibrary2.dll assembly.
  10. From the Visual Studio .NET command prompt, run your application.

    You notice the following output:

    ClassLibrary1.GetString() result: ClassLibrary1.Class1


STATUS

This behavior is by design.

MORE INFORMATION

Steps to Reproduce the Behavior

  1. Start Visual Studio .NET.
  2. Use either Visual C# .NET or Visual Basic .NET to create a Class Library project.

    By default, the Class1 class is created.
  3. Build this project to create the ClassLibrary1.dll assembly.
  4. Use either Visual C# .NET or Visual Basic .NET to add a new Class Library project to your solution.

    By default, the Class1 class is created.
  5. In the ClassLibrary2 project, add a project reference to the ClassLibrary1.dll assembly that you built in step 3.
  6. If you are using Visual C# .NET, locate the following code in the Class1.cs file of the ClassLibrary2 project:

    public Class1()
    {
       //
       // TODO: Add constructor logic here
       //
    }

    If you are using Visual Basic .NET, locate the following code in the Class1.vb file of the ClassLibrary2 project:

    Public Class Class1
  7. If you are using Visual C# .NET, add the following code after the code that you located in the previous step:

    public string GetString()
    {
       return new ClassLibrary1.Class1().ToString();
    }

    If you are using Visual Basic .NET, add the following code after the code that you located in the previous step:

    Public Function GetString() As String
       Return New ClassLibrary1.Class1().ToString()
    End Function
  8. Build the ClassLibrary2 project to create the ClassLibrary2.dll assembly.
  9. Use either Visual C# .NET or Visual Basic .NET to add a new Console Application project to your solution.

    By default, the Class1 class is created in Visual C# .NET, and the Module1 module is created in Visual Basic .NET.
  10. If you are using Visual C# .NET, locate the following code in the Class1.cs file of the ConsoleApplication1 project:

    using System;

    If you are using Visual Basic .NET, locate the following code in the Module1.vb file of the ConsoleApplication1 project:

    Module Module1
  11. If you are using Visual C# .NET, add the following code after the code that you located in the previous step:

    using System.Reflection;

    If you are using Visual Basic .NET, add the following code before the code that you located in the previous step:

    Imports System.Reflection
  12. If you are using Visual C# .NET, add the following code to the Main method of the Class1 class:

    Assembly myAssembly;
    myAssembly = Assembly.LoadFrom(@"C:\828991\ClassLibrary2\bin\Debug\ClassLibrary2.dll");
    Type myType = myAssembly.GetTypes()[0];
    MethodInfo myMethod = myType.GetMethod("GetString");
    object obj = myAssembly.CreateInstance(myType.FullName);
    Console.WriteLine("ClassLibrary1.GetString() result: {0}", myMethod.Invoke(obj, null));

    Note In the Assembly.LoadFrom method, use an appropriate path that corresponds to the location of the ClassLibrary2.dll assembly on your computer.

    If you are using Visual Basic .NET, add the following code to the Main method of the Module1 module:

    Dim MyAssembly As [Assembly]
    MyAssembly = [Assembly].LoadFrom("C:\828991\ClassLibrary2\bin\ClassLibrary2.dll")
    Dim MyType As Type = MyAssembly.GetTypes()(0)
    Dim MyMethod As MethodInfo = MyType.GetMethod("GetString")
    Dim Obj As Object = MyAssembly.CreateInstance(myType.FullName)
    Console.WriteLine("ClassLibrary1.GetString() result: {0}", MyMethod.Invoke(obj, Nothing))

    Note In the Assembly.LoadFrom method, use an appropriate path that corresponds to the location of the ClassLibrary2.dll assembly on your computer.

  13. Build the ConsoleApplication1 project to create the ConsoleApplication1.exe file.
  14. Start Notepad.
  15. Type the following text in Notepad:

    This is not an assembly.
  16. Save the Notepad document as ClassLibrary1.dll in the same location as the ConsoleApplication1.exe file that you built in step 13.
  17. From the command prompt, run the ConsoleApplication1.exe file.

    You notice the behavior that is mentioned in the "Symptoms" section.


REFERENCES

For additional information about the TargetInvocationException class, visit the following Microsoft Developer Network (MSDN) Web site:

For additional information about the MethodBase.Invoke method, visit the following MSDN Web site:

For additional information about the FileLoadException class, visit the following MSDN Web site:

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

For additional information, click the following article numbers to view the articles in the Microsoft Knowledge Base:

327435 PRB: Assembly.LoadFrom Does Not Load Dependent Assemblies That Are Located in the Same Directory


315682 How To: Install an Assembly in the Global Assembly Cache in Visual Basic .NET


815808 HOW TO: Install an Assembly into the Global Assembly Cache in Visual C# .NET


Keywords: kbcommandline kbmisctools kbprogramming kbsample kberrmsg kbcode kbprb KB828991