By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,290 Members | 1,671 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,290 IT Pros & Developers. It's quick & easy.

Re: HowTo: dynamically load an assembly from the GAC

P: n/a
"parez" wrote:
On Jun 3, 5:02 pm, Thomas W. Brown
<thomas_w_br...@countrywide.NOSPAM.comwrote:
Unfortunately this doesn't quite do the trick... I have a string name,
"System.Runtime.Remoting" that I need to use to load the underlying assembly.
I cannot rely on always knowing a type that would reside in that assembly
(in this case, it's a namespace, so the supplied code in that article fails).

Regards,
-- TB

"qglyirnyf...@mailinator.com" wrote:
Checkout:
>http://msdn.microsoft.com/en-us/library/2exyydhb.aspx
On Jun 3, 3:34 pm, Thomas W. Brown
<thomas_w_br...@countrywide.NOSPAM.comwrote:
[snip]
>
I am not really sure but try using Assembly.LoadWithPartialName.
It mite have worked for me...
Assembly.LoadWithPartialName does indeed work!!

Now, why is this incredibly useful routine deprecated and we are instructed
to use Assembly.Load instead which does not provide the same functionality?!?

I'll check now, but maybe someone knows... Is this deprecated routine still
available in Visual Studio 2008 and .NET 3.5?

Regards,
-- TB
Jun 27 '08 #1
Share this Question
Share on Google+
9 Replies


P: n/a
Assembly.LoadWithPartialName does indeed work!!
>
Now, why is this incredibly useful routine deprecated and we are instructed
to use Assembly.Load instead which does not provide the same functionality?!?
It was deprecated because it not a good idea to use it. This is
because it is critical that you load exactly the assembly version that
you need rather than just throw an assembly name and hope that the
right assembly version gets loaded. This was known as dll hell (and
you can still run into that problem even now in certain
circumstances).

For example, what would you expect the framework to load if you
specify assembly name “System.Runtime.Remoting”? Would you expect to
load version 1.0? 1.1? 2.0?.

You are just asking for trouble by using this method.
I'll check now, but maybe someone knows... Is this deprecated routine still
available in Visual Studio 2008 and .NET 3.5?
Yes the method will be there because .Net 3.5 is .Net 2.0 and .Net 3.0
wrapped into one so those dlls weren’t changed….. It may however not
be there in future versions.
Jun 27 '08 #2

P: n/a
"qg**********@mailinator.com" wrote:
Assembly.LoadWithPartialName does indeed work!!

Now, why is this incredibly useful routine deprecated and we are instructed
to use Assembly.Load instead which does not provide the same functionality?!?

It was deprecated because it not a good idea to use it. This is
because it is critical that you load exactly the assembly version that
you need rather than just throw an assembly name and hope that the
right assembly version gets loaded. This was known as dll hell (and
you can still run into that problem even now in certain
circumstances).
Yeah, well, now I'm in GAC hell -- hardly better.
>
For example, what would you expect the framework to load if you
specify assembly name “System.Runtime.Remoting”? Would you expect to
load version 1.0? 1.1? 2.0?.
Most recent, of course, that's what LoadWithPartialName did.
>
You are just asking for trouble by using this method.
I'll check now, but maybe someone knows... Is this deprecated routine still
available in Visual Studio 2008 and .NET 3.5?

Yes the method will be there because .Net 3.5 is .Net 2.0 and .Net 3.0
wrapped into one so those dlls weren’t changed….. It may however not
be there in future versions.
But what about a situation where I want exactly the functionality that used
to exist... Someone has "told" me that they want to reference
System.Runtime.Remoting but that someone isn't in Visual Studio and doesn't
necessary have any access to gacutil or other means to determine the other
components of an AssemblyName. They are simply creating a list (in SQL, but
that's irrelevent) that I need to process at runtime.

I want to find the most recent version of the assembly in the GAC. This is
exactly what LoadWithPartialName did. Why should I have to roll my own
implementation, examining the file system to recursively descend through all
subfolders underneath %WINDOWS%\Assembly looking for the desired assembly
filename, extract the version from the folder name, track the highest
version, and then assemble my location? That seems like a WOT when the
functionality was already provided.

Perhaps the information is in the registry somewhere???

Regards,
-- TB

Jun 27 '08 #3

P: n/a
>For example, what would you expect the framework to load if you
>specify assembly name “System.Runtime.Remoting”? Would you expect to
load version 1.0? 1.1? 2.0?.

Most recent, of course, that's what LoadWithPartialName did.
And where in the documentation does it specify that the version being loaded
is guaranteed to the most recent version? **and** what if company XYZ
creates an assembly called “System.Runtime.Remoting” and drops it in the GAC
too? Now what? What do you expect the .Net framework to load? The Microsoft
one or the XYZ one?
Someone has "told" me that they want to reference
System.Runtime.Remoting but that someone isn't in Visual Studio and
doesn't
necessary have any access to gacutil or other means to determine the other
components of an AssemblyName. They are simply creating a list (in SQL,
but
that's irrelevent) that I need to process at runtime.
This “someone” needs to tell you *exactly* the assembly that needs to be
loaded (name/version/culture/token/social security number etc). *specially*
if it’s an assembly located in the GAC.

Jun 27 '08 #4

P: n/a
"Rene" wrote:
For example, what would you expect the framework to load if you
specify assembly name “System.Runtime.Remoting”? Would you expect to
load version 1.0? 1.1? 2.0?.
Most recent, of course, that's what LoadWithPartialName did.

And where in the documentation does it specify that the version being loaded
is guaranteed to the most recent version? **and** what if company XYZ
creates an assembly called “System.Runtime.Remoting” and drops it in the GAC
too? Now what? What do you expect the .Net framework to load? The Microsoft
one or the XYZ one?
Ummm... in the MSDN docs for LoadWithPartialName. :-)

Then company XYZ should be taken out and shot, of course. I'm willing to
cross that bridge when I come to it. Keep in mind that I'm writing internal
applications, not shrink wrap for mass distribution -- I'm willing to make
certain assumptions that may not hold true in general.
>
Someone has "told" me that they want to reference
System.Runtime.Remoting but that someone isn't in Visual Studio and
doesn't
necessary have any access to gacutil or other means to determine the other
components of an AssemblyName. They are simply creating a list (in SQL,
but
that's irrelevent) that I need to process at runtime.

This “someone” needs to tell you *exactly* the assembly that needs to be
loaded (name/version/culture/token/social security number etc). *specially*
if it’s an assembly located in the GAC.
Unrealistic, especially since the dynamic generation happens on multiple
workstations and, hypothetically, some may have .NET 2.0 installed, and some
only .NET 1.1. It would be a mistake to effectively bind the yet-to-be
generated and compiled code to a particular version (at least a mistake in my
mind). It would prevent the dynamic creation of code that was able to
examine the system the app was running on and generating code to use the most
recent version of what was there.

Regards,
-- TB

Jun 27 '08 #5

P: n/a
Thomas,
I'm willing to cross that bridge when I come to it. Keep in mind that I'm
writing internal
applications, not shrink wrap for mass distribution -- I'm willing to make
certain assumptions that may not hold true in general.
You have 2 additional possibilities:

1. Add references to all assemblies referenced by your generating
application.
Newer CSScripting implements this. So you can call this engine to run your
scripts.

http://www.members.optusnet.com.au/~olegshilo
http://www.codeproject.com/KB/cs/cs-script_for_cp.aspx

2. Use the code below to resolve.

// http://www.thescripts.com/forum/thread496844.html

// static string FullReference(string relativeReference) {
// // First, get the path for this executing assembly.
// Assembly a = Assembly.GetExecutingAssembly();
// string path = Path.GetDirectoryName(a.Location);

// // if the file exists in this Path - prepend the path
// string fullReference = Path.Combine(path, relativeReference);
// if (File.Exists(fullReference))
// return fullReference;
// else {
// // Strip off any trailing ".dll" if present.
// if
(string.Compare(relativeReference.Substring(relati veReference.Length - 4),
".dll", true) == 0)
// fullReference = relativeReference.Substring(0,
relativeReference.Length - 4);
// else
// fullReference = relativeReference;

// // See if the required assembly is already present in our
currentAppDomain
// foreach (Assembly currAssembly in
AppDomain.CurrentDomain.GetAssemblies()) {
// if (string.Compare(currAssembly.GetName().Name,
fullReference, true) == 0) {
// // Found it, return the location as the full reference.
// return currAssembly.Location;
// }
// }

// // The assembly isn't present in our current application, so
attempt to
// // load it from the GAC, using the partial name.
// try {
// Assembly tempAssembly = Assembly.Load(fullReference);
//.LoadWithPartialName(fullReference);
// return tempAssembly.Location;
// } catch {
// // If we cannot load or otherwise access the assembly from
the GAC then just
// // return the relative reference and hope for the best.
// return relativeReference;
// }
// }
// }

Andrus.

Jun 27 '08 #6

P: n/a
The first is possible, but my generating application may not reference all
assemblies that generated code may need or want to references.

As to the second..., well..., this is my code :-) From back when I was
using LoadWithPartialName and dropped it when migrating to .NET 2.0 (after
getting the warning about it being deprecated). As you can see, this has
been a nagging thorn in my side for some time now :-D

Regards,
-- TB

"Andrus" wrote:
Thomas,
I'm willing to cross that bridge when I come to it. Keep in mind that I'm
writing internal
applications, not shrink wrap for mass distribution -- I'm willing to make
certain assumptions that may not hold true in general.

You have 2 additional possibilities:

1. Add references to all assemblies referenced by your generating
application.
Newer CSScripting implements this. So you can call this engine to run your
scripts.

http://www.members.optusnet.com.au/~olegshilo
http://www.codeproject.com/KB/cs/cs-script_for_cp.aspx

2. Use the code below to resolve.

// http://www.thescripts.com/forum/thread496844.html

// static string FullReference(string relativeReference) {
// // First, get the path for this executing assembly.
// Assembly a = Assembly.GetExecutingAssembly();
// string path = Path.GetDirectoryName(a.Location);

// // if the file exists in this Path - prepend the path
// string fullReference = Path.Combine(path, relativeReference);
// if (File.Exists(fullReference))
// return fullReference;
// else {
// // Strip off any trailing ".dll" if present.
// if
(string.Compare(relativeReference.Substring(relati veReference.Length - 4),
".dll", true) == 0)
// fullReference = relativeReference.Substring(0,
relativeReference.Length - 4);
// else
// fullReference = relativeReference;

// // See if the required assembly is already present in our
currentAppDomain
// foreach (Assembly currAssembly in
AppDomain.CurrentDomain.GetAssemblies()) {
// if (string.Compare(currAssembly.GetName().Name,
fullReference, true) == 0) {
// // Found it, return the location as the full reference.
// return currAssembly.Location;
// }
// }

// // The assembly isn't present in our current application, so
attempt to
// // load it from the GAC, using the partial name.
// try {
// Assembly tempAssembly = Assembly.Load(fullReference);
//.LoadWithPartialName(fullReference);
// return tempAssembly.Location;
// } catch {
// // If we cannot load or otherwise access the assembly from
the GAC then just
// // return the relative reference and hope for the best.
// return relativeReference;
// }
// }
// }

Andrus.

Jun 27 '08 #7

P: n/a
The first is possible, but my generating application may not reference all
assemblies that generated code may need or want to references.
You can you //css_reference or using command in script code.
CScript uses fusion.dll assembly to resolve partial references in this case.

http://www.members.optusnet.com.au/~...ssemblies.html

public static string QueryAssemblyInfo(string assemblyName)
{

AssemblyInfo aInfo = new AssemblyInfo();
aInfo.cchBuf = 1024;
aInfo.currentAssemblyPath = "Path".PadLeft(aInfo.cchBuf);

IAssemblyCache ac = null;
COM.CheckHR(CreateAssemblyCache(out ac, 0));
COM.CheckHR(ac.QueryAssemblyInfo(0, assemblyName, ref aInfo));

return aInfo.currentAssemblyPath;
}

[DllImport("fusion.dll")]
internal static extern int CreateAssemblyCache(out IAssemblyCache
ppAsmCache, int reserved);
}
Andrus.

Jun 27 '08 #8

P: n/a
"Andrus" wrote:
The first is possible, but my generating application may not reference all
assemblies that generated code may need or want to references.

You can you //css_reference or using command in script code.
CScript uses fusion.dll assembly to resolve partial references in this case.

http://www.members.optusnet.com.au/~...ssemblies.html

public static string QueryAssemblyInfo(string assemblyName)
{

AssemblyInfo aInfo = new AssemblyInfo();
aInfo.cchBuf = 1024;
aInfo.currentAssemblyPath = "Path".PadLeft(aInfo.cchBuf);

IAssemblyCache ac = null;
COM.CheckHR(CreateAssemblyCache(out ac, 0));
COM.CheckHR(ac.QueryAssemblyInfo(0, assemblyName, ref aInfo));

return aInfo.currentAssemblyPath;
}

[DllImport("fusion.dll")]
internal static extern int CreateAssemblyCache(out IAssemblyCache
ppAsmCache, int reserved);
}
Andrus.

Well, I'm not using CS scripting, I'm writing a full on C#/.NET application,
but I'm sure I could leverage the information here.

However, I've just rolled my own version of what is probably happening in
LoadWithPartialName as well as the AssemblyCache stuff you've referenced
here. Basically, I scan the GAC at the file system level (yes, the process
will require read access to the GAC), looking for all DLLs that are in a
folder that follows the <version>__<publickeytokenpattern and builds a
static dictionary that maps the assembly filename to the version and
location. If multiple versions are encountered, I keep the highest version.
When I need to add a reference to "System.Runtime.Remoting", I simply look it
up in my dictionary and get the full location.

This way I'm not using a deprecated routine (gasp), and still am able to get
the functionality I require. The downside, of course, is that I am now
tightly coupled to the directory and file structure of the GAC -- something
that I'm sure will come back to haunt me in the not-too-distant future.

Regards,
-- TB
Jun 27 '08 #9

P: n/a
Well, I'm not using CS scripting, I'm writing a full on C#/.NET
application,
but I'm sure I could leverage the information here.
CSScripting can also be used from C# appl just like any other class.
However, I've just rolled my own version of what is probably happening in
LoadWithPartialName as well as the AssemblyCache stuff you've referenced
here. Basically, I scan the GAC at the file system level (yes, the
process
will require read access to the GAC), looking for all DLLs that are in a
folder that follows the <version>__<publickeytokenpattern and builds a
static dictionary that maps the assembly filename to the version and
location. If multiple versions are encountered, I keep the highest
version.
When I need to add a reference to "System.Runtime.Remoting", I simply look
it
up in my dictionary and get the full location.
For .NET assemblies better solution would be to distribute GAC assembly
table with your scripting routine.
Scripting engine can use this table to translate partial names to full
names. Or add references to all .net assemblies to your solution.

For other assemblies you can requite to put them into application directory.
In Windows you can call fusion.dll insted of requiring read access to GAC
directories.

Andrus.

Jun 27 '08 #10

This discussion thread is closed

Replies have been disabled for this discussion.