473,245 Members | 1,830 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,245 software developers and data experts.

Assembly.Load(byte[]) - how does it work? I get TargetInvocationException. Source code included...

My problem:

I load an some assemblies (strong named) from a byte array using
Assembly.Load(byte[]). They load fine. But one one of them is actually
accessed, it's referenced assemblies can't be found on disk and I get a
TargetInvocationExeption.

For example, let's say I have a C# win forms application called Prog.

Prog.exe uses Assembly.Load(byte[]) to load two C# class library assemblies,
ClassLib1 and ClassLib2. Both are strong named. ClassLib1.dll and
ClassLib2.dll are NOT on disk. However, they were created in VS.NET in the
same solution, and ClassLib1 has a reference to ClassLib2 in VS.NET.

The problem is that when my Prog.exe calls a static method on a class in
ClassLib1, I get a TargetInvocationException with the details:
Unhandled Exception: System.Reflection.TargetInvocationException: Exception
has been thrown by the target of an invocation. --->
System.IO.FileNotFoundException: File or assembly name ClassLib2, or one of
its dependencies, was not found.

There are additional details that show that the framework is trying to load
ClassLib2.dll from disk, from the debug (or release) directory where
Prog.exe was started.

In fact, if I do put ClassLib2.dll on disk there, then there is no exception
because it finds it and loads it. Which means it has been loaded twice,
once by me with the Assembly.Load, and once due to the reference from
ClassLib1.

WHY? Why oh why? I've already loaded it!

So how do I make the framework "realize" that it is already loaded? I
thought strong naming would have do the trick, but it didn't make a
difference... it still wants to load it from disk because of the reference
from ClassLib1. Argghhh!

Any help would be GREATLY appreciated...

Thanks!

Greg Patrick

Source code is below if you want to try it out. You just make a VS.NET C#
Win Forms app solution and use Form1 from below. Then make two C# class
library projects ClassLibrary1, and ClassLibrary2. Don't reference either
class library from the main application project. Build. Copy
ClassLibrary1\bin\debug\ClassLibrary1.dll to <application>\bin\debug\C1.dll.
Similarly for ClassLibrary2.dll - copy to C2.dll.

----------------------------------------------------------------------------
-------------------------------

ClassLibrary2

using System;
namespace ClassLibrary2
{
public class Class2
{
public Class2()
{
}
}
}

ClassLibrary1 (Note, in VS.NET, has a reference to ClassLibrary2):

using System;
using System.Windows.Forms;
using ClassLibrary2;
namespace ClassLibrary1
{
public class Class1
{
public static Class2 class2 = new Class2();

public Class1()
{
}

public static void Hello()
{
MessageBox.Show("Hello!");
}
}
}

Prog.exe's Form1:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Reflection;
namespace WinApp
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

private Assembly LoadAss(string filename)
{
FileStream fin = new FileStream("c1.dll", FileMode.Open,
FileAccess.Read);
byte[] bin = new byte[16384];
long rdlen = 0;
long total= fin.Length;
int len;
MemoryStream memStream = new MemoryStream((int)total);
rdlen = 0;
while(rdlen < total)
{
len = fin.Read(bin, 0, 16384);
memStream.Write(bin, 0, len);
rdlen = rdlen + len;
}
// done with input file
fin.Close();
return Assembly.Load(memStream.ToArray());
}

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
Assembly c1 = this.LoadAss("c1.dll");
this.LoadAss("c2.dll");
Type t = c1.GetType("ClassLibrary1.Class1");
MethodInfo m = t.GetMethod("Hello");
m.Invoke(null, new object[]{});
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.Size = new System.Drawing.Size(300,300);
this.Text = "Form1";
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
}
}
Nov 16 '05 #1
1 15827
You have to manage AssemblyResolve and make sure to return your dynamic
assembly whenever a request for your second strongly typed assembly is made.
What I would recommend is using Assembly.Load(byte[]), and then inserting
the Assembly references into a Hashtable that you can index later.

I have some information on this on my blog. Note, that because your assemblies
are strong named, you might not want to use basic name resolving and instead use
a more complete resolving based on the full name. That is completely up to your
discretion.

http://weblogs.asp.net/justin_rogers...07/149964.aspx

--
Justin Rogers
DigiTec Web Consultants, LLC.
Blog: http://weblogs.asp.net/justin_rogers

"Greg Patrick" <pr*****@private.com> wrote in message
news:WlJyc.1204$0A.9411@localhost...
My problem:

I load an some assemblies (strong named) from a byte array using
Assembly.Load(byte[]). They load fine. But one one of them is actually
accessed, it's referenced assemblies can't be found on disk and I get a
TargetInvocationExeption.

For example, let's say I have a C# win forms application called Prog.

Prog.exe uses Assembly.Load(byte[]) to load two C# class library assemblies,
ClassLib1 and ClassLib2. Both are strong named. ClassLib1.dll and
ClassLib2.dll are NOT on disk. However, they were created in VS.NET in the
same solution, and ClassLib1 has a reference to ClassLib2 in VS.NET.

The problem is that when my Prog.exe calls a static method on a class in
ClassLib1, I get a TargetInvocationException with the details:
Unhandled Exception: System.Reflection.TargetInvocationException: Exception
has been thrown by the target of an invocation. --->
System.IO.FileNotFoundException: File or assembly name ClassLib2, or one of
its dependencies, was not found.

There are additional details that show that the framework is trying to load
ClassLib2.dll from disk, from the debug (or release) directory where
Prog.exe was started.

In fact, if I do put ClassLib2.dll on disk there, then there is no exception
because it finds it and loads it. Which means it has been loaded twice,
once by me with the Assembly.Load, and once due to the reference from
ClassLib1.

WHY? Why oh why? I've already loaded it!

So how do I make the framework "realize" that it is already loaded? I
thought strong naming would have do the trick, but it didn't make a
difference... it still wants to load it from disk because of the reference
from ClassLib1. Argghhh!

Any help would be GREATLY appreciated...

Thanks!

Greg Patrick

Source code is below if you want to try it out. You just make a VS.NET C#
Win Forms app solution and use Form1 from below. Then make two C# class
library projects ClassLibrary1, and ClassLibrary2. Don't reference either
class library from the main application project. Build. Copy
ClassLibrary1\bin\debug\ClassLibrary1.dll to <application>\bin\debug\C1.dll.
Similarly for ClassLibrary2.dll - copy to C2.dll.

----------------------------------------------------------------------------
-------------------------------

ClassLibrary2

using System;
namespace ClassLibrary2
{
public class Class2
{
public Class2()
{
}
}
}

ClassLibrary1 (Note, in VS.NET, has a reference to ClassLibrary2):

using System;
using System.Windows.Forms;
using ClassLibrary2;
namespace ClassLibrary1
{
public class Class1
{
public static Class2 class2 = new Class2();

public Class1()
{
}

public static void Hello()
{
MessageBox.Show("Hello!");
}
}
}

Prog.exe's Form1:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Reflection;
namespace WinApp
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

private Assembly LoadAss(string filename)
{
FileStream fin = new FileStream("c1.dll", FileMode.Open,
FileAccess.Read);
byte[] bin = new byte[16384];
long rdlen = 0;
long total= fin.Length;
int len;
MemoryStream memStream = new MemoryStream((int)total);
rdlen = 0;
while(rdlen < total)
{
len = fin.Read(bin, 0, 16384);
memStream.Write(bin, 0, len);
rdlen = rdlen + len;
}
// done with input file
fin.Close();
return Assembly.Load(memStream.ToArray());
}

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
Assembly c1 = this.LoadAss("c1.dll");
this.LoadAss("c2.dll");
Type t = c1.GetType("ClassLibrary1.Class1");
MethodInfo m = t.GetMethod("Hello");
m.Invoke(null, new object[]{});
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.Size = new System.Drawing.Size(300,300);
this.Text = "Form1";
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
}
}

Nov 16 '05 #2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Mitchell Vincent | last post by:
I'm sure this has been discussed here plenty of times before (feel free to point me to the thread!) but I want to learn as much as possible about the single most talked about issue with .NET...
8
by: Michael Dekson | last post by:
Hello, Can I exe file made in Microsoft Visual C++ decompile into source code. If it is possibly please tell me how. Thanks
19
by: Martin Oddman | last post by:
Hi, I have a compiling problem. Please take a look at the code below. I have an application that is built upon three tiers: one data tier (Foo.DataManager), one business tier (Foo.Kernel) and...
1
by: mathlec | last post by:
I'm struggling with an odd problem and I want to validate something. What is the right way to load an assembly from bytes? Is this code correct? : .... Private Function loadBytes(filename...
3
by: Peter | last post by:
I have a VB.net exe ----> I want to load in more VB.net Source code into my VB app ---> and then compile a new EXE file from within my original program. Has anyone done this? I'm looking for...
5
by: iamcs1983 | last post by:
Can I load a assembly from memory by Assembly.Load(string) ?
6
by: Steve | last post by:
I'm playing with late binding and trying a very simple test to load an assembly In my "Host" application I have this code: <code> string modulePath =...
0
by: Boni | last post by:
Dear all, the Assembly.load(ByteArray() ) function works very slow for me (sometimes about 10 sec for 1 MB assembly). Is there any chance for speed up? --- Overloads Public Shared Function...
1
by: =?Utf-8?B?QU1lcmNlcg==?= | last post by:
I have a vb.net program that needs to display a few fragments of its source code, typically one to five lines for each fragment, and each line contains one assignment statement. I need to do this...
0
by: abbasky | last post by:
### Vandf component communication method one: data sharing ​ Vandf components can achieve data exchange through data sharing, state sharing, events, and other methods. Vandf's data exchange method...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: marcoviolo | last post by:
Dear all, I would like to implement on my worksheet an vlookup dynamic , that consider a change of pivot excel via win32com, from an external excel (without open it) and save the new file into a...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.