HighTechTalks DotNet Forums  

Loading an assembly from byte stream

Dotnet Framework (CLR) microsoft.public.dotnet.framework.clr


Discuss Loading an assembly from byte stream in the Dotnet Framework (CLR) forum.



Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old   
Graven
 
Posts: n/a

Default Loading an assembly from byte stream - 08-05-2006 , 06:38 AM






Hello guys,

Recently I've tried to load an assembly from a byte stream using the
method Load(Byte[] rawAssembly). The test assembly was a single-module
assembly that referenced nothing but mscorlib. I've renamed the
assembly to someting messy, and then got its contents to a byte array
using File.ReadAllBytes.

The actual problem comes here.

When I'm using Assembly.Load(byte[] rawAssembly), it loads ok. But when
the same byte array is used with AppDomain.Load(byte[] rawAssembly),
I'm getting FileIOException with the message "Assembly [the original
name of my assembly] was not found". What surprised me the most is the
fact that both these methods internally use Assembly.nLoadImage
(figured it out with Reflector).

Anyone has an explanation for this weird behavior?

Many thanks, Stan.


Reply With Quote
  #2  
Old   
Vadym Stetsyak
 
Posts: n/a

Default Re: Loading an assembly from byte stream - 08-05-2006 , 07:59 AM






Hello, Graven!
You wrote on 5 Aug 2006 03:38:09 -0700:

G> Recently I've tried to load an assembly from a byte stream using the
G> method Load(Byte[] rawAssembly). The test assembly was a single-module
G> assembly that referenced nothing but mscorlib. I've renamed the
G> assembly to someting messy, and then got its contents to a byte array
G> using File.ReadAllBytes.

G> The actual problem comes here.

G> When I'm using Assembly.Load(byte[] rawAssembly), it loads ok. But when
G> the same byte array is used with AppDomain.Load(byte[] rawAssembly),
G> I'm getting FileIOException with the message "Assembly [the original
G> name of my assembly] was not found". What surprised me the most is the
G> fact that both these methods internally use Assembly.nLoadImage
G> (figured it out with Reflector).

G> Anyone has an explanation for this weird behavior?

I couldn't repeat your situation with mere loading.
This code works fine:

string appBase;
object obj;
Assembly loadedAssembly;
MethodInfo mInfo;
object result;

string path = Assembly.GetExecutingAssembly().Location;
path = Path.GetDirectoryName(path);
path = Path.Combine(path, "ClassLibrary1.dll");
byte[] assembly = File.ReadAllBytes(path);

//app domain load
AppDomain appDomain = AppDomain.CreateDomain("Test Domain");
loadedAssembly = appDomain.Load(assembly);
obj = loadedAssembly.CreateInstance("ClassLibrary1.Class 1");
mInfo = obj.GetType().GetMethod("SayHello");
result = mInfo.Invoke(obj, null);
Console.WriteLine("Result: {0}", result.ToString());

//Assembly load sample
loadedAssembly = Assembly.Load(assembly);
obj = loadedAssembly.CreateInstance("ClassLibrary1.Class 1");
mInfo = obj.GetType().GetMethod("SayHello");
result = mInfo.Invoke(obj, null);
Console.WriteLine("Result: {0}", result.ToString());

The code for SayHello is
return "Hello from " + AppDomain.CurrentDomain.Id.ToString();

Return values are:
Hello from 1
Hello from 1

Soo, we were executing on the same app domain that is why everything went
smooth.

However, if I'll try to create ClassLibrary1 instance on our new domain
then I'll receive FileNotFound exception.
( calling ObjectHandle objHandle =
appDomain.CreateInstance("ClassLibraray1.dll", "ClassLibrary1.Class1"); )

--
Regards, Vadym Stetsyak.
Blog: http://vadmyst.blogspot.com



Reply With Quote
  #3  
Old   
Michael Nemtsev
 
Posts: n/a

Default Re: Loading an assembly from byte stream - 08-05-2006 , 08:21 AM



Hello Vadym,

That's probably due to appDomain trying to load the asm from the new domain.
AppDomain was created especially to manipulate with asms into domains others
than the current one

VS> However, if I'll try to create ClassLibrary1 instance on our new
VS> domain
VS> then I'll receive FileNotFound exception.
VS> ( calling ObjectHandle objHandle =
VS> appDomain.CreateInstance("ClassLibraray1.dll",
VS> "ClassLibrary1.Class1"); )
---
WBR,
Michael Nemtsev :: blog: http://spaces.msn.com/laflour

"At times one remains faithful to a cause only because its opponents do not
cease to be insipid." (c) Friedrich Nietzsche



Reply With Quote
  #4  
Old   
Graven
 
Posts: n/a

Default Re: Loading an assembly from byte stream - 08-05-2006 , 09:16 AM



I've played a while with assembly loading and it seems you're perfectly
right. I was getting the same error as yours - looks like I've forgot
the exact case. The difference wasn't in loading the assembly, but in
the type instantiating. It doesn't matter if an assembly resides in the
current appdomain or in another one - fusion just can't bind to
assembly loaded with LoadFile or Load(Byte[]). When trying to
instantiate an assembly by AppDomain.Load(Byte[]).CreateIntance("..."),
clr will be looking for the type in a newly loaded assembly and type
instantiates ok. But if you ask the domain, not the loaded assembly, to
instantiate the type, it will not find the newly loaded assembly,
trying to hot-load it by meand of Assembly.Load(AssemblyName).

This behavior is a result of clr having three different contexts - one
for Load(AssemblyName), one for LoadFile and the third for
Load(Byte[]). Fusion can't find types that do not belong to the first
context - we need to handle AssemblyResolve event and return the right
assembly manually.

Best wishes, Stan.

Vadym Stetsyak wrote:
Quote:
Hello, Graven!
You wrote on 5 Aug 2006 03:38:09 -0700:

G> Recently I've tried to load an assembly from a byte stream using the
G> method Load(Byte[] rawAssembly). The test assembly was a single-module
G> assembly that referenced nothing but mscorlib. I've renamed the
G> assembly to someting messy, and then got its contents to a byte array
G> using File.ReadAllBytes.

G> The actual problem comes here.

G> When I'm using Assembly.Load(byte[] rawAssembly), it loads ok. But when
G> the same byte array is used with AppDomain.Load(byte[] rawAssembly),
G> I'm getting FileIOException with the message "Assembly [the original
G> name of my assembly] was not found". What surprised me the most is the
G> fact that both these methods internally use Assembly.nLoadImage
G> (figured it out with Reflector).

G> Anyone has an explanation for this weird behavior?

I couldn't repeat your situation with mere loading.
This code works fine:

string appBase;
object obj;
Assembly loadedAssembly;
MethodInfo mInfo;
object result;

string path = Assembly.GetExecutingAssembly().Location;
path = Path.GetDirectoryName(path);
path = Path.Combine(path, "ClassLibrary1.dll");
byte[] assembly = File.ReadAllBytes(path);

//app domain load
AppDomain appDomain = AppDomain.CreateDomain("Test Domain");
loadedAssembly = appDomain.Load(assembly);
obj = loadedAssembly.CreateInstance("ClassLibrary1.Class 1");
mInfo = obj.GetType().GetMethod("SayHello");
result = mInfo.Invoke(obj, null);
Console.WriteLine("Result: {0}", result.ToString());

//Assembly load sample
loadedAssembly = Assembly.Load(assembly);
obj = loadedAssembly.CreateInstance("ClassLibrary1.Class 1");
mInfo = obj.GetType().GetMethod("SayHello");
result = mInfo.Invoke(obj, null);
Console.WriteLine("Result: {0}", result.ToString());

The code for SayHello is
return "Hello from " + AppDomain.CurrentDomain.Id.ToString();

Return values are:
Hello from 1
Hello from 1

Soo, we were executing on the same app domain that is why everything went
smooth.

However, if I'll try to create ClassLibrary1 instance on our new domain
then I'll receive FileNotFound exception.
( calling ObjectHandle objHandle =
appDomain.CreateInstance("ClassLibraray1.dll", "ClassLibrary1.Class1"); )

--
Regards, Vadym Stetsyak.
Blog: http://vadmyst.blogspot.com


Reply With Quote
Reply




Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.4
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.