1

I'm using the library SharpShell to develop a simple shell extension (a property sheet) to display some information for .NET assemblies, see:

enter image description here

This shell extension and SharpShell itself is not relevant to this question, but to explain my scenario so you can understand better my question.


My project is compiled as Any CPU mode, then, to manage the loading of x86, x64 an Any CPU assemblies in my program I'm using the overload of the function Assembly.Load() that takes the bytes of a raw assembly as unique argument:

Assembly asm = Assembly.Load( File.ReadAllBytes(filepath) );

I tested it with dlls and executables of both x86 and x64 architectures, and Any CPU, it works fine... except for the problem I'll explain.

The problem is that for some reason that I ignore it is not working for some x86 assemblies, for example when I try to load the x86 assembly: System.Web.dll ( System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ), the Assembly.Load() function throws an exception. It is NOT a BadImageException, its a FileLoadException with this error message:

Could not load file or assembly 'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)

( note that Assembly.ReflectionOnlyLoad() will also throw the same exception. )

However, I can load the x64 version of the same assembly with success. Please note that as I said, I can load most of the 32-bit assemblies in my program.

If I compile my project as x86, then I can load this assembly with sucess. But my project must compile as Any CPU (to be able handle the loading of both x86 and x64 assemblies ...since I'm not aware of a better approach).

I would like to know why I can't load that specific assembly, and a viable approach to solve this issue.

Here you can download the dlls if you want to test it:

http://www.mediafire.com/file/8h9256w02b2j3dj/System.Web.dll.zip/file

ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
  • 1
    Have you tried using `Assembly.ReflectionOnlyLoadFrom()` instead of `Assembly.Load()`? – NineBerry Sep 09 '18 at 01:25
  • 1
    @NineBerry Yes, I commented it in the question... – ElektroStudios Sep 09 '18 at 02:06
  • I cannot reproduce this as you explain it. When I use Assembly.Load(File.ReadAllBytes()), I get the exception in a 64bit process. When I use Assembly.ReflectionOnlyLoadFrom() instead, everything works. – NineBerry Sep 09 '18 at 02:16

1 Answers1

0

It is not possible to load Assemblies for a different processor architecture than the current process using Assembly.Load().

Use Assembly.ReflectionOnlyLoadFrom() instead.

In a simple demo application that is run as 64 bit, I see the following behaviour:

var lAss = Assembly.Load(File.ReadAllBytes(@"C:\Windows\Microsoft.NET\assembly\GAC_32\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll"));
MessageBox.Show(lAss.Location);

This throws the exception as described in the question.

var lAss = Assembly.ReflectionOnlyLoadFrom((@"C:\Windows\Microsoft.NET\assembly\GAC_32\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll"));
MessageBox.Show(lAss.Location);

This throws no exception and shows the message box.

NineBerry
  • 26,306
  • 3
  • 62
  • 93
  • It is possible. It is not possible using Assembly.Load passing a filepath, but it is possible using the overload that takes the raw assembly bytes, or else using Assembly.ReflectionOnlyLoadFrom function. I already commented in my question that ReflectionOnlyLoadFrom throws the same exception and I also commented that compiling to Any CPU (or to x64) I don't have any problem to load both x86 and x64 assemblies, except for some x86 assemblies like System.web.dll, please read the question... – ElektroStudios Sep 09 '18 at 02:14
  • @ElektroStudios Can you reproduce the same behaviour as me in a simple demo application? – NineBerry Sep 09 '18 at 02:18
  • Yes I can reproduce it coding on the fly in a empty project (compiling to x86, x64 and any cpu), not sure why in my app I can't load the same assembly as "only-reflection", its too late here in my country, I will test it tomorrow and I'll comment here. Thank you. – ElektroStudios Sep 09 '18 at 02:27
  • 1
    @ElektroStudios When coding shell extensions, it is easy to get confused which version of code one is actually testing. One has to make sure to kill the Explorer processes between different tests. In order to find detailed information on why loading an assembly does not work, use [Fuslogvw.exe](https://learn.microsoft.com/en-us/previous-versions/dotnet/netframework-1.1/e74a18c4(v=vs.71)) – NineBerry Sep 09 '18 at 02:33