Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Assembly.Load(byte[] rawAssembly)

281 views
Skip to first unread message

Keijo

unread,
Feb 10, 2003, 3:54:55 AM2/10/03
to
I'm trying to use assemblies which I have read as byte
arrays (since I try to avoid reading from file system with
these assemblies). You can do this with "Assembly.Load(byte
[] rawAssembly)". It works fine. I can execute the code
using reflection "Invoke". BUT. When I call Invoke and the
assembly "x.dll" has a reference to another
assembly "y.dll" then the CLR tries to find the "y.dll"
from the file system (which I do not want).

I tried to load both assemblies to memory (with
Assembly.Load(byte[] rawAssembly)). So that CLR would use
the assembly which is already in memory but that did not
help. (GetReferencedAssemblies() info of "x.dll" shows
reference to "y.dll" and
AppDomain.CurrentDomain.GetAssemblies() shows exactly same
version already in memory).

So in this case CLR does not use/find/accept the assembly
which is already in memory. Why? Any ideas?

Dave

unread,
Feb 10, 2003, 6:35:23 AM2/10/03
to
"Keijo" <nos...@nospam.com> wrote in message
news:052701c2d0e2$14d7f9c0$a101...@phx.gbl...

This might apply to your situation.
http://www.gotdotnet.com/team/clr/LoadFromIsolation.aspx
I don't know if that form of Load causes the assembly to be added to the
path-based cache or the static cache, but it might be part of what you are
seeing.

Are the assemblies signed with a strong name? This affects how the runtime
determines if an assembly satisfies the static binding requirement.

You can add a AssemblyResolve event handler and manually tell the system
which assembly to use.

If the assemblies are stored in the application base directory or a
subdirectory below there, you can add the relative path to that location to
the appdomain's private bin path by calling

AppDomain.CurrentDomain.AppendPrivatePath(RelativePath);

This provides another location to be checked when the runtime tries to
resolve the static reference assembly A has for B. The assembly must be
located below the Application's base directory for this to work.

I load assemblies using Load rather then LoadFrom similar to you, but rather
then use the byte array method I use
Assembly.Load( AssemblyName.GetAssemblyName(pathToAssemblyFile).FullName);
This causes the runtime to resolve the assembly using the full 4-part name
of the assembly (assuming it is signed with a strongname).

Keijo

unread,
Feb 10, 2003, 8:20:53 AM2/10/03
to
Excellent! Thanks Dave!

Nice tips & link. I did not know that statically
referenced assemblies are isolated from path-based
assemblies.

I'm now using AssemblyResolve event handler which seems to
work Ok in my situation.

Radha

unread,
Feb 10, 2003, 9:26:40 AM2/10/03
to
I am facing the same problem but my problem is that the referenced dlls are
not in the same path as that of the main dll and its completly in a new
folder..so i write in my Assemblyresolvehandler..code "return
Assembly.LoadFrom(path of the referenced dll) but still it says "file or one
of its dependencies not found"..What shld i exactly do in my handler...

rgds


"Keijo" <nos...@nospam.com> wrote in message

news:065b01c2d107$3cea4ec0$d4f82ecf@TK2MSFTNGXA11...

Suzanne Cook [MS]

unread,
Mar 3, 2003, 7:04:55 PM3/3/03
to
Yes, that's true for LoadFrom context assemblies. But Load(byte[]) doesn't
put that assembly in either the Load or the LoadFrom context (it's not in a
Fusion context at all). So, when the byte[]'s static dependencies are
loaded, the Load context is checked for that assembly (meaning the GAC,
application base, and private bin paths). If the dependency isn't found
there, then the AssemblyResolve event is raised.

Note that I didn't say that the loaded assemblies are checked. (Well, there
is some caching done, but that's an implementation detail, and won't help
you unless that reference can be resolved otherwise, anyway.) So,
pre-loading the dependencies of a byte[]-loaded assembly will not help you
resolve those references.

So, I recommend subscribing to the AssemblyResolve event to resolve non-GAC
byte[] dependencies. Your callback can then load the assembly by
Load(byte[]), LoadFrom(), etc.

Suzanne Cook
--
Please do not respond directly to this alias. This alias is for newsgroup
purposes only. This posting is provided "AS IS" with no warranties, and
confers no rights.

"Dave" <kdle...@wi.rr.com> wrote in message
news:#l7wwhP0CHA.2600@TK2MSFTNGP11...

Suzanne Cook [MS]

unread,
Mar 3, 2003, 7:09:36 PM3/3/03
to
To debug this, try getting the Fusion log. It will describe the binding
failure (if this is due to an assembly binding failure, instead of a loading
failure after the file is found). Usually, the exception will include a
Fusion log. If not, to get the log: run fuslogvw.exe, click on 'Log Failures
'. If this is an ASP.NET or .NET Windows service app, select the "Custom"
option, and in regedit, set [HKLM\Software\Microsoft\Fusion\LogPath] to
point to some directory (like c:\mylogs, not c:\). Then, re-run the
process. Next, click 'Refresh' in fuslogvw, and a line should appear for
each binding failure. Double-click on the line for this exception, and a
web page should come up with the Fusion log.

For FileNotFoundException:

At the bottom of the log will be the paths that Fusion tried probing for
this assembly. Your assembly will need to be on one of those or in the GAC
if it's to be found.

You may also get this exception if an unmanaged dependency or internal
module of the assembly failed to load. Try running depends.exe on the file
to verify that unmanaged dependencies can be loaded. Note that if you're
using ASP.NET, the PATH environment variable it's using may differ from the
one the command line uses. If all of them could be loaded, try ildasm.exe on
the file, double-click on "MANIFEST", and look for ".file" entries. Each of
those files will need to be in the same directory as the manifest-containing
file.


Suzanne Cook
--
Please do not respond directly to this alias. This alias is for newsgroup
purposes only. This posting is provided "AS IS" with no warranties, and
confers no rights.

"Radha" <sudha...@honeywell.com> wrote in message
news:#SWP8CR0CHA.1752@TK2MSFTNGP10...

Dave

unread,
Mar 3, 2003, 9:04:53 PM3/3/03
to

"Suzanne Cook [MS]" <suz...@online.microsoft.com> wrote in message
news:eQDS0Ge4...@TK2MSFTNGP11.phx.gbl...

> Yes, that's true for LoadFrom context assemblies. But Load(byte[])
doesn't
> put that assembly in either the Load or the LoadFrom context (it's not in
a
> Fusion context at all). So, when the byte[]'s static dependencies are
> loaded, the Load context is checked for that assembly (meaning the GAC,
> application base, and private bin paths). If the dependency isn't found
> there, then the AssemblyResolve event is raised.

So there's a third cache/context of assemblies maintained in the runtime?
omigawd. Is there an article somewhere which describes all these isolated
caches besides the article at
http://www.gotdotnet.com/team/clr/LoadFromIsolation.aspx. and go into more
detail?


Is this an appropriate forum to request a design change be made to the
runtime?

Suzanne Cook [MS]

unread,
Mar 4, 2003, 6:51:10 PM3/4/03
to
It's not really a context (Fusion doesn't know anything about these
assemblies). They're just assemblies that don't know about each other.
Their dependencies are attempted to be loaded in the Load context first
(like all other assemblies, regardless of context).

Design suggestions can be given to microsoft newsgroups, like this one.
But, since a version of the Frameworks has already shipped, that limits the
design changes that can be made (they have to be backwards compatible,
except when a security hole is involved, or some other extremely important
change needs to be made). In this case, although it may not be obvious to
you, considering your needs, there were certain scenarios in mind, requiring
binding to be designed this way. However, suggestions are always helpful.

Suzanne Cook
--
Please do not respond directly to this alias. This alias is for newsgroup
purposes only. This posting is provided "AS IS" with no warranties, and
confers no rights.

"Dave" <kdle...@wi.rr.com> wrote in message

news:#6WF6Kf4...@TK2MSFTNGP12.phx.gbl...

Dave

unread,
Mar 4, 2003, 11:14:34 PM3/4/03
to
I am trying to determine the extent that assemblies loaded using different
forms of Loadxxx are aware about each other. I know that assemblies loaded
using LoadFrom are in a different cache then those loaded using Load(name),
but I am not at all sure if assemblies loaded using Load(byte[]) are in a
third cache or in the same cache (or context, or whatever term we want to
give it) as either the Load(name) or LoadFrom caches. From what I've
observed static dependencies are only satisfied automatically by the runtime
from the Load(name) list - but I was unsure of those assemblies loaded using
Load(byte[]).

I also wanted to know if AppDomain.CurrentDomain.GetAssemblies() returned
the summation of all the caches or a partial list.

I've read about the scenarios they had in mind and IMO they made some poor
choices. They could have made the distinction between assemblies signed with
a strong name and those that are not. As it is currently implemented it is
possible to load an assembly that has been signed with a strong name more
then once into the same appdomain - this creates enormous problems.

Dave

"Suzanne Cook [MS]" <suz...@online.microsoft.com> wrote in message

news:eJyOzjq4...@TK2MSFTNGP11.phx.gbl...

Suzanne Cook [MS]

unread,
Mar 30, 2003, 8:05:51 PM3/30/03
to
Assemblies loaded through Load(byte[]) and LoadFile(), in effect, can only
be resolved to by the AssemblyResolve event. Assemblies in the LoadFrom
context can only be resolved to through the LoadFrom context. Assemblies in
the Load context can be resolved to from anything.

AppDomain.CurrentDomain.GetAssemblies() returns all of the Assembly objects
in the appdomain, regardless of how they were loaded.

Actually, it's possible to load any assembly multiple times into the same
appdomain, whether it's strongly-named or not (Load(byte[]), LoadFile(),
etc.). This was a required feature for certain scenarios.

As for the 'enormous problems,' there is always a tradeoff between
implementing a powerful feature, and one that's simple to use. In this
case, being able to load the assembly one needs is extremely important,
tipping the scale to making it less simple to use in the LoadFrom() case.
That is why I routinely recommend against its use unless you know what
you're doing. Besides, most people do not need, and ought not load by path,
anyway - their app is better off using the Load context for its versioning
features, etc.

Suzanne Cook

--
Please do not respond directly to this alias. This alias is for newsgroup
purposes only. This posting is provided "AS IS" with no warranties, and
confers no rights.

"Dave" <kdle...@wi.rr.com> wrote in message

news:OPf7B4s4...@TK2MSFTNGP12.phx.gbl...

Dave

unread,
Mar 31, 2003, 7:07:15 AM3/31/03
to
Thanks for replying...


"Suzanne Cook [MS]" <suz...@online.microsoft.com> wrote in message

news:O$gQsGy9C...@TK2MSFTNGP12.phx.gbl...


> Assemblies loaded through Load(byte[]) and LoadFile(), in effect, can only
> be resolved to by the AssemblyResolve event. Assemblies in the LoadFrom
> context can only be resolved to through the LoadFrom context. Assemblies
in
> the Load context can be resolved to from anything.
>
> AppDomain.CurrentDomain.GetAssemblies() returns all of the Assembly
objects
> in the appdomain, regardless of how they were loaded.
>
> Actually, it's possible to load any assembly multiple times into the same
> appdomain, whether it's strongly-named or not (Load(byte[]), LoadFile(),
> etc.). This was a required feature for certain scenarios.
>

The documentation states that an assembly is loaded only once per appdomain
(it actually is that it only gets loaded once per caching mechanism per
appdomain), and that additional attempts to load the same assembly returns a
reference to the already loaded assembly. Are you stating that this is not
the way it works? How would you go about deliberately loading the same
assembly into the same appdomain multiple times so that it shows up more
then once in the list of loaded asssemblies for that appdomain?

Also, you use LoadFile several times...is this a typo for LoadFrom?

> As for the 'enormous problems,' there is always a tradeoff between
> implementing a powerful feature, and one that's simple to use. In this
> case, being able to load the assembly one needs is extremely important,
> tipping the scale to making it less simple to use in the LoadFrom() case.
> That is why I routinely recommend against its use unless you know what
> you're doing. Besides, most people do not need, and ought not load by
path,
> anyway - their app is better off using the Load context for its versioning
> features, etc.
>

Plugin architectures routinely require the ability to load by path, but
instead of just loading by path one must create an appdomain, set its base
directory to the path, and then Load the assembly within the context of that
appdomain. Even if conceptually it is still just another means of loading by
path on a practical basis the differences are huge. One difference is that
all plugins loaded in this manner must now be remoted between appdomains.
This is more then just an API that is not simple to use, it is a completely
different approach with a different set of cascading side-effects that must
be dealt with.

IMO, the reason why the Load method is more suitable then the LoadFrom is
because of the way MSFT implemented the resolution mechanism - multiple
caches used to store the references to assemblies based on the loading
mechanism and Fusion automatically resolving only those that used Load. As I
previously stated this is fine for unsigned assemblies but for signed
assemblies it was a poor choice. I have yet to hear an argument that
convinced me otherwise. As for whether or not I know what I am doing...I
think I do.

0 new messages