I'm trying to learn a bit more about System.Reflection using the official microsoft docs. Specifically I'm trying to run the following example:
// Loads an assembly using its file name.
Assembly a = Assembly.LoadFrom("MyExe.exe");
// Gets the type names from the assembly.
Type[] types2 = a.GetTypes();
foreach (Type t in types2)
{
Console.WriteLine(t.FullName);
}
So I made a new console app using dotnet new console -o=customconsole. I then removed ImplicitUsings from my project file (because I don't like that), and came up with the following code:
using System;
using System.Reflection;
namespace get_type_from_assembly
{
internal class Program
{
static void Main(string[] args)
{
// load assembly using full file name
Assembly a = Assembly.LoadFrom("C:\\Users\\bobmarley\\desktop\\temp\\csharp-reflection\\get-type-from-assembly\\bin\\Debug\\net6.0\\console-custom.exe");
// get type names from assembly
Type[] types2 = a.GetTypes();
foreach (Type t in types2)
{
Console.WriteLine(t.FullName);
}
}
}
}
Then I tried to run the generated executable using dotnet run --project=customconsole. I got the following runtime error:
Unhandled exception. System.BadImageFormatException: Bad IL format. The format of the file 'C:\Users\bobmarley\desktop\temp\csharp-reflection\get-type-from-assembly\bin\Debug\net6.0\console-custom.exe' is invalid.
at System.Runtime.Loader.AssemblyLoadContext.LoadFromPath(IntPtr ptrNativeAssemblyLoadContext, String ilPath, String niPath, ObjectHandleOnStack retAssembly)
at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyPath(String assemblyPath)
at System.Reflection.Assembly.LoadFrom(String assemblyFile)
at get_type_from_assembly.Program.Main(String[] args) in C:\Users\bobmarley\desktop\temp\csharp-reflection\get-type-from-assembly\Program.cs:line 11
make: *** [Makefile:5: run] Error 1
I'm not sure why this occurs, because I checked and the executable does exist in the specified path. What is happening here and how can I fix it?
A likely reason is that the your project and the loaded assembly target different platforms, i.e. x86 vs x64, In my experience that is a common reason for BadImageFormatException. Another possible reasons is that one targets .net core while the other targets .net framework.
Dynamically loading an assembly will require that it is compatible with your project. If you want to read arbitrary assemblies you probably want some tool that can extract whatever information you are after from the CIL code directly, without actually loading it.
I have the following code in my project, this compiles and run (seemingly) properly.
SpeechClient.StreamingRecognizeStream streamingCall;
[...]
while (await streamingCall.ResponseStream.MoveNext(CancellationToken.None))
{
[...]
}
In visual studio, hovering over streamingCall.ResponseStream tells me that it is of type System.Collections.Generic.IAsyncEnumerator<StreamingRecognizeResponse>. However the following code
System.Collections.Generic.IAsyncEnumerator<StreamingRecognizeResponse> responseStream = streamingCall.ResponseStream;
while (await responseStream.MoveNext(CancellationToken.None))
{
[...]
}
does not compile with the error:
CS0433 The type 'IAsyncEnumerator<T>' exists in both
'System.Interactive.Async, Version=3.2.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263'
and
'mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'
Replacing System.Collections.Generic.IAsyncEnumerator<StreamingRecognizeResponse> by var however does fix the error. The following code, compiles and run properly.
var responseStream = streamingCall.ResponseStream;
while (await responseStream.MoveNext(CancellationToken.None))
{
[...]
}
Why is the compiler confused when I use the real type, but not when referring it via either var or via a property?
How do I modify the code in order to be able to use the type directly, e.g. to take it as a function parameter?
If that matters, I am running this code on iOS with Xamarin.Forms.
In the project having this compilation error, try removing a reference to System.Interactive.Async assembly/package and try recompiling...
I am creating nopCommerce plug-in for image compression using Magick.Net library, I make ImageOptimizer object and when calling LosslessCompress method it gives an error like unable to load dll Magick.NET-Q16-x64.Native.dll or one of its dependencies: The specified module could not be found.
I have found Magick.NET-Q16-x64.Native.dll and when I am trying to add a reference for that it gives an error like reference is invalid or unsupported
var file = new FileInfo(filepath);
var optimizer = new ImageOptimizer();
optimizer.LosslessCompress(file);
I expect no error occurs when LosslessCompress method runs and image is successfully compressed.
I'm trying to include a html to pdf converter in my C# program for windows mobile.
I found Pdfizer.
I added a refence to Pdfizer.dll and included it with using Pdfizer;
Also I added a reference to itextsharp that is required for Pdfizer.
Pdfizer is correctly added and I can use many of its functions and classes but I can't use HtmlToPdfConverter.Run()
My code:
FileStream filePDF;
filePDF = File.Create(path + ".pdf"); // path is string
html2pdf.Open(filePDF);
html2pdf.AddChapter(#"Chapter name");
html2pdf.Run(html); // html is a string that contains html code
html2pdf.Close();
Problem is in line html2pdf.Run(html); It says:
Error 1 The type 'System.Uri' is defined in an assembly that is not referenced.
You must add a reference to assembly 'System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
Definition of Run is
public void Run(string html);
public void Run(Uri uri);
I'm trying to use the Run(string html) option, but Uri is defined and visual studio says it is not referenced but yes it is.
I have using System; that contains Uri class, indeed I use it in other functions and works properly.
What is the problem? Should I add a reference to System, Version=1.0.5000.0? Where can I find It? Is there any way to tell Pdfizer Uri is in System.Uri?
Thanks
A public key token of b77a5c561934e089 indicates that you're referencing a desktop assembly, so my bet is that Pdfizer is built only for the desktop. There is no way to make that work in the COmpact Framework. If you can get the source, you can try to compile it for the CF, otehrwise you'll have to ask the owners if they have a CF version.
I have this weird problem that I cannot handle myself. A class in the model of my mvp-project designed as singleton causes an InvalidCastException.
The source of error is found in this code line where the deserialised object is assigned to the instance variable of the class: engineObject = (ENGINE)xSerializer.Deserialize(str);. It occurs whenever I try to add one of my UserControls to a Form or to a different UC. All of my UCs have a special presenter that accesses the above mentioned instance variable of the singleton class.
This is what I get when trying to add a UC somewhere:
'System.TypeInitializationException: The type initializer for 'MVP.Model.EngineData' threw an exception. ---->
System.InvalidCastException: [A]Engine cannot be cast to [B]Engine. Type A originates from 'MVP.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'LoadNeither'
at location '[...]\AppData\Roaming\Microsoft\VisualStudio\9.0\ProjectAssemblies\uankw1hh01\MVP.Model.dll'.
Type B originates from 'MVP.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'LoadNeither'
at location '[...]\AppData\Roaming\Microsoft\VisualStudio\9.0\ProjectAssemblies\u_hge2de01\MVP.Model.dll'
...
So I somehow have two assemblies and they are not accessed from my project folder, but from a VS temp folder? I googled a lot and only found this: IronPython Exception: [A]Person cannot be cast to [B]Person. There is a solution offered, but it concerns IronPhyton and I don't know where to use it within my project.
Types are per-assembly; if you have "the same" assembly loaded twice, then types in each "copy" of the assembly are not considered to be the same type.
These issues normally crop up when the two assemblies are in the Load and LoadFrom contexts. See
Difference between LoadFile and LoadFrom with .NET Assemblies?
and the link to suzcook's blog for details on that issue.
Also, consider using the fusion log viewer to help diagnose the problem.
http://msdn.microsoft.com/en-us/library/e74a18c4%28VS.71%29.aspx
Judging by the context in which the assembly is getting loaded (the context is "LoadNeither"), some developers may be doing something like loading an assembly that has been internally packaged as a resource with your application. If you do this, you will be using the AppDomain.CurrentDomain.AssemblyResolve event handler, so that your application can specify where .NET should get any particular assembly that it needs.
My answer will not explain the machinations of how to do that - but I'm mentioning it because this process led directly to the same exact error encountered by the original poster. As Eric Lippert mentions, types are per-assembly. So if you load an individual assembly more than once, the same defined class will appear as different classes - even though visual inspection shows that they appear to be the same.
We've seen instances in which .NET will call the ResolveEventHandler more than once for the same DLL. I'm not sure why .NET sometimes does this (it happened on some machines, but not all machines). But to resolve the problem, we needed keep a global list of handles to loaded assemblies, so that if .NET wanted to load the assembly again, we returned a handle to the same Assembly that was originally loaded, instead of loading another copy into memory.
I have included the code that caused the issue for us, and notes about how to handle it properly.
public void AppStartup (object sender, StartupEventArgs e)
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
public System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
string dllName = args.Name.Contains(',') ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll", "");
dllName = dllName.Replace(".", "_");
if (dllName.EndsWith("_resources")) return null;
System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());
byte[] bytes = null;
try
{
bytes = (byte[])rm.GetObject(dllName);
}
catch (Exception ex)
{
}
if (bytes != null)
{
// the following call will return a newly loaded assembly
// every time it is called
// if this function is called more than once for the same
// assembly, you'll load more than one copy into memory
// this can cause the InvalidCastException
// instead of doing this, you keep a global list of loaded
// assemblies, and return the previously loaded assembly
// handle, instead of loading it again
return System.Reflection.Assembly.Load(bytes);
}
return null;
}
My situation involved two copies of the same dll. One was in the bin folder and one was in a sub-folder of the same bin folder. Both were loaded, amazingly some things worked fine, but some things didn't and that's when this error message appeared:
System.InvalidOperationException; There was an error generating the XML document.; Source: System.Xml; TargetSite: Void Serialize(System.Xml.XmlWriter, System.Object, System.Xml.Serialization.XmlSerializerNamespaces, System.String, System.String);
Hidden in this was the following inner exception (this was to do with Microsoft Dynamics CRM 4.0, but could relate to anything)
System.InvalidCastException; [A]XXX.CRMCustomCode.YYY.CreateCompanyRequest cannot be cast to [B]XXX.CRMCustomCode.YYY.CreateCompanyRequest. Type A originates from 'XXX.CRMCustomCode, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'LoadFrom' at location 'C:\Program Files\Microsoft CRM\Server\bin\assembly\XXX.CRMCustomCode.dll'. Type B originates from 'XXX.CRMCustomCode, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' at location 'C:\Program Files\Microsoft CRM\Server\bin\XXX.CRMCustomCode.dll'.;
I simply deleted the duplicate dll (in C:\Program Files\Microsoft CRM\Server\bin) and the error went away.
My particular case - class library referenced in web application was renamed and rebuilt. Older version of library was still in bin folder under old name. The framework loads whatever in bin folder (both libraries) and emits this error. So it happens not only when assemblies are loaded explicitly.
The obvious solution in my case is to clean bin folder.
I got it working when I tried changing this cast:
var t = (TeacherWebPages)Session["TeachersAD"];
To this:
var t = Session["TeachersAD"] as TeacherWebPages;
However the assembly/session/memcache was different and no data got back but no error occurred. So later I still had to delete specific temporary files every time source page was changed from the folder it was complaining about which would require me to kill IIS process from task manager. Or in my case I can just logout and it clears the session state.