.NET reflection on system assemblies fails on System.Data.dll - c#

I have a language compiler that I've just updated to target .NET 4.0 and the metadata generator for framework assemblies now fails on System.Data.dll, while all others work fine (mscorlib, System, etc.)
The metadata generator simply loads assemblies, reflects over all the types and memberinfo and generates a stub class for the language.
I'm using Assembly.Load() and/or Assembly.ReflectionOnlyLoad()
Could not load file or assembly 'file:///c:\windows\Microsoft.NET\framework\v4.0.30319\System.Data.dll'
or one of its dependencies. An attempt was made to load a program with
an incorrect format.
It is built for "AnyCPU". I'm running Windows 7/x64 with .NET 4.5 update installed.

If you use corflags tool to analyze the assemblies, you should see that ILONLY: 0 for System.Data.dll while the others (mscorlib, System) ILONLY: 1. More information regarding ILONLY can be found at here.
Thus, the assemblies were built differently and you should not expect reflection to work for all. System.Data.dll seems to be a mixed-mode assembly, which is always bitness dependent.
If you cannot run your app as 32 bit so as to load the 32 bit assemblies, you might consider Mono.Cecil as #xmojmr said, as it supports reading mixed-mode assemblies.

Related

Wixsharp - Could not load file or assembly

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!

Can't load a specific 32-bit assembly through Reflection

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.

Using dll at runtime in Unity

I want to use my dll at runtime by code.(Not putting the dll at Plugin asset)
So I write this code below:
Assembly dll = Assembly.LoadFrom("D:\HaoranZhu\workspace\UnityProjects\ViveDRMSDKTest\Assets\Plugins\x86_64\vita_api.dll");
But it shows the error here in Unity console:
BadImageFormatException: Could not load file or assembly 'D:\HaoranZhu\workspace\UnityProjects\ViveDRMSDKTest\Assets\Plugins\x86_64\vita_api.dll' or one of its dependencies. An attempt was made to load a program with an incorrect format.
System.Reflection.Assembly.LoadFrom (System.String assemblyFile) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/Assembly.cs:520)
loadExternalDll.Start () (at Assets/TestScripts/loadExternalDll.cs:16)
what's the problem here?
You are getting this error because (according to https://msdn.microsoft.com/en-us/library/1009fa28(v=vs.110).aspx):
----BadImageFormatException----
assemblyFile is not a valid assembly; for example, a 32-bit assembly in a 64-bit process. See the exception topic for more information.
-or-
Version 2.0 or later of the common language runtime is currently loaded and assemblyFile was compiled with a later version.
---
This means that either a you are using a 32-bit assembly when the process is 64 bit, (just get a 64-bit version).
Or if you downloaded a library for a later version of the common language runtime.

Unable to load assembly when referencing BindingFlags type in Windows 10 Universal Windows library

When running unit tests, calling any method in my portable runtime library DLL that references the "System.Reflection.TypeExtensions" generates a FileNotFound exception, searching for "System.Reflection.TypeExtensions". The error does not occur when the same code is executed in a Windows 10 Universal app.
The project is a C# portable runtime library, configured to support .net Framework 4.6 and Windows Universal 10.0. The Test project is configured to use .net Framework 4.6.
Whenever I attempt to call a method that uses the System.Reflection.BindingFlags type, I get the following exception. The exception occurs as the call starts (presumably while jit-ing the function).
Test method Sfx.Test.SignalExpressionTest.TestAddExpressions threw exception:
System.IO.FileNotFoundException: Could not load file or assembly 'System.Reflection.TypeExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.=== Pre-bind state information ===
LOG: DisplayName = System.Reflection.TypeExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
(Fully-specified)
Adding those packages is the right thing to do. Here is why you see this behavior:
BindingFlags is currently [1] exposed in System.Reflection.TypeExtensions.
When you compile a .NET Core class library, the compiler records the type reference as System.Reflection.TypeExtensions!System.Reflection.BindingFlags.
When you consume the class library from a .NET Framework application, you need to add a reference to System.Reflection.TypeExtensions otherwise the compiler cannot resolve the type. The same is true for a unit testing project which has to deploy all the code in order to run.
At runtime, the CLR will resolve the type, find a type forward that points to mscorlib!System.Reflection.BindingFlags and happily run your code.
As a general rule of thumb: .NET Core is designed to deploy the framework in an app-local fashion, in other words, when your application is deployed to a folder, the closure of all your dependencies need to be deployed too. Although unit test projects are conceptually class libraries, the same applies because they are executed like applications.
Of course, we don't expect folks to manually tweak the references and hunt down dependencies. What you currently see are pre-release bits where not all pieces in our tooling experiences do the right thing.
Two questions from my side:
Which unit testing framework do you use? I assume it's MSTest (Microsoft.VisualStudio.TestTools.UnitTesting), as opposed to xUnit or NUnit?
Which runner are you using? I assume it's the built-in Visual Studio Test Explorer (as opposed to ReSharper or TestDriven.NET)?
[1] I say currently because based on customer feedback we decided to move it back into System.Reflection, together with the APIs that take BindingFlags.
add reference to nuget packages:
System.Reflection
System.Reflection.Extensions
System.Reflection.Primitives

Dynamic Assembly Loading in .Net 4.0

My problem begins with moving a .Net 2.0 application to .Net 4.0. The reason I had to do this was that Windows 8 does not enable the earlier .Net versions by default and my application cannot ask the user to enable it.
The application is a NPAPI plugin which uses .Net components via UnmanagedExports. I designed it as a low integrity application and therefore it has to reside in the users 'LocalLow' directory.
In my application I used a dynamic assembly loading mechanism to load several assemblies at runtime. I used the following method to load an assembly,
MyInterface Instance;
Assembly assembly = Assembly.LoadFrom(AssemblyFile);
Type type = assembly.GetType(Identifier); // Identifier is implementing the MyInterface
Instance = Activator.CreateInstance(type) as MyInterface;
// Do something with the Instance
After modifying the project to .Net 4.0, I noticed that the plugin crashes when the binaries are placed inside the LocalLow directory (It works in other places). My next step was to create a minimalistic plugin with least possible code to figure out the issue. I noticed that the dynamic assembly loading failed with the following exception,
System.IO.FileLoadException: Could not load file or assembly '<assemblyPath>' or one of its dependencies. Operation is not supported. (Exception from HRESULT: 0x80131515 (COR_E_NOTSUPPORTED)) --->
System.NotSupportedException: An attempt was made to load an assembly from a network location which would have caused the assembly to be sandboxed in previous versions of the .NET Framework. This release of the .NET Framework does not enable CAS policy by default, so this load may be dangerous. If this load is not intended to sandbox the assembly, please enable the loadFromRemoteSources switch. See http://go.microsoft.com/fwlink/?LinkId=131738 for more information.
I tried the following approaches to create a separate domain and load the assemblies but with no luck,
http://blogs.msdn.com/b/shawnfa/archive/2009/06/08/more-implicit-uses-of-cas-policy-loadfromremotesources.aspx
http://www.west-wind.com/weblog/posts/2009/Jan/19/Assembly-Loading-across-AppDomains
Adding the configuration 'loadFromRemoteSources' did not work either. It seems that the .Net component does not load .dll.config files. (Could be because of UnmanagedExporting)
My questions are,
Is it possible to dynamically load an assembly from LocalLow?
Does the new CAS policy in CLR 4.0 apply to LocalLow as well? From what I understood so far it should affect only assemblies loaded over the network
Is there any other way to overcome this issue?
While it doesn't address your LocalLow issue specifically, if you are able to "read a file" from the directory, you might be able to use the "work around" detailed here:
How can I get LabView to stop locking my .NET DLL?

Categories