I'm using the library SharpShell to develop a simple shell extension (a property sheet) to display some information for .NET assemblies, see:
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
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.
Related
I am trying to include some reference files in Wix# managed project using DefaultRefAssemblies.Add method:
ManagedProject project = new ManagedProject();
project.DefaultRefAssemblies.Add("FontAwesome.Sharp.dll");
project.DefaultRefAssemblies.Add("protobuf-net.dll");
project.DefaultRefAssemblies.Add("Newtonsoft.Json.dll");
project.DefaultRefAssemblies.Add("ManagedOpenSsl.dll");
project.DefaultRefAssemblies.Add("ssleay32.dll");
When I try to build a MSI I get an error. The problem happens to be in loading of ssleay32 assembly (part of OpenSSL). When I exclude this file, the build succeeds. Can you please help me understand the exception? The target framework of the Wix# project is .NET Framework 4.8.
Unhandled Exception: System.BadImageFormatException: Could not load file or assembly '361984 bytes loaded from WixSharp, Version=1.15.0.0, Culture=neutral, PublicKeyToken=3775edd25acc43c2' or one of its dependencies. An attempt was made to load a program with an incorrect format. ---> System.BadImageFormatException: Bad IL format.
Wixsharp supports .net assemblies compiled for:
Platform x86
Managed assemblies (Not native)
Target framework 3.5
So, make sure "ssleay32.dll" has 3 requirements above. Every ssleay32 assembly i have found was native (unmanaged).
Workaround in case of no luck with:
You can try to save ssleay32.dll to embedding resource file and before "ManagedOpenSsl.dll" types usage you should load dll in the memory. Load unmanaged assembly
Good luck!
How do I determine if the Native images are being used without the Loader verifing the signature of the assembly at runtime, or even using the GAC'ed assembly?
I have complex system that we're experimenting with NGen but currently we're running the exe from the folder where all the DLL's are located due to a lot of late binding dependencies, looking at Process Explorer, it looks like the Native images are being used, but how can I be sure I'm getting the full benefit and eliminating the Loader Verification step?
Cheers,
Graeme.
Update:
I'm getting lots of this sort of thing from the Assembly Binding Log viewer:
LOG: [Level 1]Start validating IL dependency MyCompany.Entities, Version=2.0.0.0, Culture=neutral, PublicKeyToken=7cd8595f4671c5dd.
LOG: Dependency evaluation succeeded.
and at the end
LOG: Validation of dependencies succeeded.
LOG: Start loading all the dependencies into load context.
LOG: Loading of dependencies succeeded.
LOG: Bind to native image succeeded.
Native image has correct version information.
Attempting to use native image C:\Windows\assembly\NativeImages_v2.0.50727_32\MyCompany.Mylibrary#\4710bb8309419d707681bd360088181f\MyCompany.MyLibrary.MyClass.ni.dll.
ZAP: Native image has been relocated.
Native image successfully used.
So it's using the Native images but still verifying them, i.e. not using the GAC version even though that's where I created the Native image from, Like so:
ngen install "MyCompany.Entites, Version=2.0.0.0, Culture=neutral, PublicKeyToken=7cd8595f4671c5dd, processorArchitecture=MSIL"
Footnote:
This articles seems to imply that if the assemblies are not loaded from the GAC then the verification process will offset the NGen advantages?
CLR Inside Out - Improving Application Startup Performance (MSDN)
Update - As Nobugz has pointed out in a comment below, the verification step mentioned above is not performed since 3.5 SP1 see:MSDN Docs on NGen
You can easily see it from the Fuslogvw.exe tool. Start it from the Visual Studio Command Prompt. Configure it with Log Categories = Native Images, Settings + Log all binds to disk. Run your program. Back to fuslogvw, Refresh. It will show you a list of all assemblies that got loaded.
Double-click an entry to see how the assembly got loaded. If it came from the GAC, you'll see:
LOG: IL assembly loaded from C:\Windows\assembly\GAC_MSIL\blahblah
If the Ngen-ed images was used, you'll see:
LOG: Bind to native image succeeded.
You can see if the assembly came from the GAC pretty easily:
Assembly assembly = Assembly.GetExecutingAssembly();
if (assembly.GlobalAssemblyCache)
{
Console.WriteLine("I'm in the GAC!");
}
EDIT: found a way...
In order to see if it is NGEN'd, you have to read the assembly directly and see if the Precompile Header field has data as per this page. I'm a bit rusty on getting to that value, but that should do it. I don't see a way to figure it out via the reflection methods.
You can use the VMMAP. There, all the .dll (assembly) have location details
In details if your assembly is being loaded from "C:\Windows\assembly\NativeImages(version)..." so your application are using the native image.
I am now dealing with a existing solution in VS2012.
Now I can execute it in debug mode but cannot trigger some of the function with the error
"Exceptions: System.Exception: Could not load file or assembly
'Interop.Score, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=5ce8a8a190705d24' or one of its dependencies. The
located assembly's manifest definition does not match the assembly
reference. (Exception from HRESULT: 0x80131040)"
After finding some of the suggestion, some of that suggest me to compile the solution in 32-bit (x86).
However, when I tried to rebuild with the target platform x86, another type of error occur and I even cannot run in debug mode, the error:
Referenced assembly 'GenCode128.dll' is not a valid assembly C#
P.S. GenCode128.dll is one of the error .dll, there is at least 2 of this kind of error.
I cannot search any successful way to solve this problem, appreciate for any help.
You can use a decompiler such as DotPeek (https://www.jetbrains.com/decompiler) to look inside your DLL and see if it is a valid .NET DLL -- and which version of .NET it is. It could be an x64-compiled assembly; in that case you cannot use it on a 32-bit system or from a 32-bit-compiled .NET assembly.
You can try installing it from NuGet.
I've created a NuGet package for GenCode128.dll here: https://www.nuget.org/packages/GenCode128/
Also the source can be found in GitHub: https://github.com/SourceCodeBackup/GenCode128
Hey guys (and gals) I'm having a problem using Assembly GetExportedTypes() in .NET 4.0. The same code is working perfectly in a project targeted at an older .NET version.
NOTE: *The code works for local assemblies but when trying to open them off a network drive it does not work, that is my problem... It looks to be loading the assembly, but it claims it can't find it when using GetExportedTypes(). Again if I open a dll off my machine it works, this error only occurs with dlls located on network drives *
EDIT: The error is thrown on GetExportedTypes
The Code:
Assembly assembly;
Type[] t;
assembly = Assembly.LoadFrom(dllPathOpenFileDialog.FileName.ToString());
t = assembly.GetExportedTypes();
The Error:
Could not load file or assembly '*..***.***.****, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
(I used asterisks to hide personal information - the file name)
The way certain security policies are handled was changed in .NET 4.0. This article should provide some background.
I have a C# application which is built with platform target as ANY CPU. It references a managed C++ application which is built with the platform target as Win32. However the loading of the C++ dll fails at runtime with the following error. "Could not load file or assembly 'abc_Debug, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. Attempt to access invalid address. (Exception from HRESULT: 0x800701E7)"
Can anyone give me some pointers as to what could be wrong?
If you are running the application at a x64 architecture then your app is starting as x64 and then it can't load the c++ reference. You cannot build an application as AnyCpu if you don't have all the dependences available for AnyCpu, otherwise set x86 as the target.
in general for any loading problem of managed dlls, it's better to use fuslogvw it can gives you more details.