dynamically adding assembly reference to executing assembly

C

chage

Hi,
I have been searching around to try adding reference assembly to
another assembly during runtime, programatically. Is this possible
in .Net?

The reason for this is because i am having trouble using a library
that creates an instance of a Type that i specified, and it failed the
locate the Type during runtime, if i do not reference it during
compile time.

Thanks,
chage
 
L

Lasse Vågsæther Karlsen

chage said:
Hi,
I have been searching around to try adding reference assembly to
another assembly during runtime, programatically. Is this possible
in .Net?

The reason for this is because i am having trouble using a library
that creates an instance of a Type that i specified, and it failed the
locate the Type during runtime, if i do not reference it during
compile time.

Thanks,
chage

You can load an assembly at runtime either by specifically calling Load
methods on the Assembly class, or you can just reference a type in it
before the library needs it.

Type t = typeof(SomeTypeInThatAssembly);

should work.
 
M

Marc Gravell

Well, you can't add a reference - but you can just use Assembly.Load /
Assembly.LoadFrom to force loading a certain assembly. Alternatively,
you can handle AppDomain.AssemblyResolve or AppDomain.TypeResolve to
do a few things...

But first I'd try to figure out why resolution is failing... if the
dll isn't in the GAC, it must be part of the overall application "bin"
output.

Marc
 
C

chage

Well, you can't add a reference - but you can just use Assembly.Load /
Assembly.LoadFrom to force loading a certain assembly. Alternatively,
you can handle AppDomain.AssemblyResolve or AppDomain.TypeResolve to
do a few things...

But first I'd try to figure out why resolution is failing... if the
dll isn't in the GAC, it must be part of the overall application "bin"
output.

Marc

Hi Marc,
My use case here will be .Net remoting, where the server is unable to
load assembly that wasnt reference during compile time.

the dll isnt in GAC, it is resided somewhere else, and i use
Assembly.Load to load it into the executing app domain. The assembly
loaded without issue.
Assembly someDllAsm = System.Reflection.Assembly.LoadFile(@"C:\SomePath
\SomeDll.dll");
AppDomain.CurrentDomain.Load(someDllAsm.GetName());

But when I have a client that call a method to the server using
remoting, exception was thrown with below stack:
System.IO.FileNotFoundException: Could not load file or assembly
'SomeDll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or
one of its dependencies. The system cannot find the file specified.
File name: 'SomeDll, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null'

Server stack trace:
at System.Reflection.Assembly._nLoad(AssemblyName fileName, String
codeBase, Evidence assemblySecurity, Assembly locationHint,
StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean
forIntrospection)
at System.Reflection.Assembly.nLoad(AssemblyName fileName, String
codeBase, Evidence assemblySecurity, Assembly locationHint,
StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean
forIntrospection)
at System.Reflection.Assembly.InternalLoad(AssemblyName
assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark,
Boolean forIntrospection)
at System.Reflection.Assembly.InternalLoad(String assemblyString,
Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean
forIntrospection)
at System.Reflection.Assembly.Load(String assemblyString)
at System.UnitySerializationHolder.GetRealObject(StreamingContext
context)
at
System.Runtime.Serialization.ObjectManager.ResolveObjectReference(ObjectHolder
holder)
at System.Runtime.Serialization.ObjectManager.DoFixups()
at
System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler
handler, __BinaryParser serParser, Boolean fCheck, Boolean
isCrossAppDomain, IMethodCallMessage methodCallMessage)
at
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream
serializationStream, HeaderHandler handler, Boolean fCheck, Boolean
isCrossAppDomain, IMethodCallMessage methodCallMessage)
at
System.Runtime.Remoting.Channels.CoreChannel.DeserializeBinaryRequestMessage(String
objectUri, Stream inputStream, Boolean bStrictBinding, TypeFilterLevel
securityLevel)
at
System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(IServerChannelSinkStack
sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders,
Stream requestStream, IMessage& responseMsg, ITransportHeaders&
responseHeaders, Stream& responseStream)

Exception rethrown at [0]:
at
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage
reqMsg, IMessage retMsg)
at
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&
msgData, Int32 type)


I am not too sure how AppDomain.TypeResolve works, I will try to look
into that after this. If you have any other thoughts, do let me know.
Thanks!

-chage
 
C

chage

You can load an assembly at runtime either by specifically calling Load
methods on the Assembly class, or you can just reference a type in it
before the library needs it.

Type t = typeof(SomeTypeInThatAssembly);

should work.

Hi Lasse,
thanks for your reply. Yes, that will work if I have control over how
the type can be locate (I use this method in my client side code,
please refer to my previous post about the use case).
But the problem occurs when i use remoting, where the Type being
serialized and deserialized by .Net framework, which i do not have
control over how they locate the Type, other than i have the dll
referenced during compile time.

I might be missing something, as I have just started to make use of
Remoting. Any other suggestions will be appreciated. Thanks.

-chage
 
R

Rene

Hi Chage,

Just guessing here (nowhere near being an expert on this).

First thing I notice is that you are using the "LoadFile()" method passing
the "C:\SomePath\SomeDll.dll" path to get a reference to the assembly and
*then* you use the "Load()" method of the AppDomain to actually load the
assembly into the AppDomain. The key point here of course, is that the
assembly that you are searching for is not on the application base path but
under "C:\SomePath" path which I assume is not the application base path.

I am quite surprised that this actually loads the assembly correctly because
I don't believe that the AppDomain.Load() method searches the "C:\SomePath"
path looking for the assembly. My guess would be that you have a copy of the
"SomeDll.dll" file on the application base path and that is the reason the
assembly will load there but maybe that is not the case on the server and
that why is fails???

I google "Fussion Log" and came up with the following link:

http://blogs.msdn.com/suzcook/archive/2003/05/29/57120.aspx

I just took a quick glance at this so I am not sure it will help you but it
looks like something that would help you solve your problem.

Sorry I can't do any better!!! Good luck solving your problem and if you do
find an answer please post back so we can all see the what going on!!

Cheers.
 
C

chage

Hi Marc,
you are right, i got it work by handling the AssemblyResolve myself to
load the dll i wanted. Now i can really work on dynamically loading
the external dll without having to rebuild my server and client code.
Thanks!

To Rene,
thanks for your offering, appreciate it. I did read thru the link you
provides, it is a good one. Regarding your comment on the dll path, I
got it work because when we do AppDomain.Load, we specify the full
path to the assembly we intended to load, so it should be find.

with this, i got my case close for now, thanks to all who offered
their help.

-chage


Well, you can't add a reference - but you can just use Assembly.Load /
Assembly.LoadFrom to force loading a certain assembly. Alternatively,
you can handle AppDomain.AssemblyResolve or AppDomain.TypeResolve to
do a few things...
But first I'd try to figure out why resolution is failing... if the
dll isn't in the GAC, it must be part of the overall application "bin"
output.

Hi Marc,
My use case here will be .Net remoting, where the server is unable to
load assembly that wasnt reference during compile time.

the dll isnt in GAC, it is resided somewhere else, and i use
Assembly.Load to load it into the executing app domain. The assembly
loaded without issue.
Assembly someDllAsm = System.Reflection.Assembly.LoadFile(@"C:\SomePath
\SomeDll.dll");
AppDomain.CurrentDomain.Load(someDllAsm.GetName());

But when I have a client that call a method to the server using
remoting, exception was thrown with below stack:
System.IO.FileNotFoundException: Could not load file or assembly
'SomeDll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or
one of its dependencies. The system cannot find the file specified.
File name: 'SomeDll, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null'

Server stack trace:
   at System.Reflection.Assembly._nLoad(AssemblyName fileName, String
codeBase, Evidence assemblySecurity, Assembly locationHint,
StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean
forIntrospection)
   at System.Reflection.Assembly.nLoad(AssemblyName fileName, String
codeBase, Evidence assemblySecurity, Assembly locationHint,
StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean
forIntrospection)
   at System.Reflection.Assembly.InternalLoad(AssemblyName
assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark,
Boolean forIntrospection)
   at System.Reflection.Assembly.InternalLoad(String assemblyString,
Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean
forIntrospection)
   at System.Reflection.Assembly.Load(String assemblyString)
   at System.UnitySerializationHolder.GetRealObject(StreamingContext
context)
   at
System.Runtime.Serialization.ObjectManager.ResolveObjectReference(ObjectHol­der
holder)
   at System.Runtime.Serialization.ObjectManager.DoFixups()
   at
System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(Hea­derHandler
handler, __BinaryParser serParser, Boolean fCheck, Boolean
isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(­Stream
serializationStream, HeaderHandler handler, Boolean fCheck, Boolean
isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at
System.Runtime.Remoting.Channels.CoreChannel.DeserializeBinaryRequestMessag­e(String
objectUri, Stream inputStream, Boolean bStrictBinding, TypeFilterLevel
securityLevel)
   at
System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(I­ServerChannelSinkStack
sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders,
Stream requestStream, IMessage& responseMsg, ITransportHeaders&
responseHeaders, Stream& responseStream)

Exception rethrown at [0]:
   at
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage
reqMsg, IMessage retMsg)
   at
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&
msgData, Int32 type)

I am not too sure how AppDomain.TypeResolve works, I will try to look
into that after this. If you have any other thoughts, do let me know.
Thanks!

-chage
 
M

Marc Gravell

Good to hear it is sorted! Actually, I have to admit that this event
is one of those things I've heard about but never used... glad it
worked ;-p

Marc
 
T

Thomas W. Brown

Marc Gravell said:
Well, you can't add a reference - but you can just use Assembly.Load /
Assembly.LoadFrom to force loading a certain assembly. Alternatively,
you can handle AppDomain.AssemblyResolve or AppDomain.TypeResolve to
do a few things...

I have a similar case, I need to dynamically addref a system assembly at
runtime (for dynamically generated code), but Assembly.Load is failing (I'm
just specifying the assembly name but no other components of the full name).

In particular,
Assembly.Load("System.Runtime.Remoting")

fails for me with an "Could not load file or assembly
'System.Runtime.Remoting' or one of its dependencies. The system cannot find
the file specified." error.

I suspect this is because, according to the Assembly.Load documentation,

"You can also make a dynamic reference to an assembly by providing the
calling method with only partial information about the assembly, such as
specifying only the assembly name. In this case, only the application
directory is searched for the assembly, and no other checking occurs. You
make a partial reference using any of the various methods for loading
assemblies such as System.Reflection.Assembly.Load or System.AppDomain.Load."

So, I need the long name of the assembly in order to load from the GAC.
Which brings me to the operative question...

What is the best (easiest) way to determine the proper long name components
for an assembly in the GAC so that I can dynamically load said assembly?

Regards,
-- TB
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top