TargetInvocationException.InnerException missing line numbers - c#

I'm executing some code from dynamically loaded assembly using Invoke. Out of curiosity I've thrown an exception in the method I invoke. It works and I can read the exception but it's missing line numbers.
var assemblyBytes = File.ReadAllBytes(scriptPath);
// I'm using this overload to avoid blocking the dll.
var assembly = Assembly.Load(assemblyBytes); // allows to pass pdb bytes in the second argument.
var myMethod = ...
try
{
myMethod.Invoke(null, parameters);
}
catch (TargetInvocationException e)
{
MessageBox.Show(e.InnerException); // missing line numbers
}
Dynamically loaded assembly was built in debug mode.
Any idea why that happens, and how can I get it to show line numbers?
In this case I'm using .NET Framework 4.0

passing pdb bytes to Assembly.Load worked

Related

How to trigger "BadImageFormatException'?

I need to create a "BadimageFormatException" in my local to test some cacheing issue. How to create "BadImageFormatException"?
As already specified in the comments, you can just create and throw this exception:
throw new BadImageFormatException();
If you want to cause this exception naturally, then as per MSDN documentation,
This exception is thrown when the file format of a dynamic link library (.dll file) or an executable (.exe file) doesn't conform to the format that the common language runtime expects
It means that you can cause it by trying to load an invalid assembly file:
string tempPath = Path.GetTempFileName();
using (var file = File.OpenWrite(tempPath))
using (var sw = new StreamWriter(file))
{
sw.WriteLine("I am not an assembly");
}
Assembly.LoadFile(tempPath);
Thanks to #Xiaoy312 for the advice. There is a much simpler way to do this using Assembly.Load:
Assembly.Load(new byte[] { 0 });
If new to this, then one way also is to load an unmanaged assembly for example notepad.exe.
try
{
// path to notepad.exe.
string path = Environment.ExpandEnvironmentVariables("%windir%") + #"\System32\notepad.exe";
Assembly assembly = Assembly.LoadFile(path);
}
catch (System.BadImageFormatException exception)
{
// catch an exception.
}
As Notepad is unmanaged and not compiled with .Net, .net isnt very happy and throws the exception.
For interesting trivia, BadImageFormatException has nothing to do with bad image format like gifs or jpegs but its an exception when .Net attempts to load a DLL or exe which isnt compatible with CLR.
Also, all exceptions are derived from System.Exception. BadImageFormatException is just inherited from System.Exception.

C# Reflection not Working 100%

I have a program with a Managed Executable as a resource,
when I try to load the exe using reflection with the following code:
byte[] file = Properties.Resources.ExeName;
Assembly assembly = Assembly.Load(file);
// search for the Entry Point
MethodInfo method = assembly.EntryPoint;
if (method != null)
{
// create an instance of the Startup form Main method
object handle = assembly.CreateInstance(method.Name);
// invoke the application starting point
method.Invoke(handle, null);
}
The assembly I try to load is a valid Managed assembly compiled against .NET Framework 2.0 having the following instruction:
MessageBox.Show("Some Text");
//other stuff goes here
The problem is when I run the application I don't get any MessageBox.Show ("Message") dialog, I tried putting breakpoints in the code everything works fine until it reaches the instruction:
method.Invoke(handle, null);
Once I Step Over here, nothing happens, it neither give any error or exception not it freezes the Editor (VS 2017 Community Edition).
I tried loading other Managed Assemblies, it works fine (provided the assemblies are complied against the same .NET Framework Version (2.0)).
Can anyone point out what possible could be the reason why is the desired exe not executed as expected.
Assembly.EntryPoint is the method that is the entry point for an assembly which will be, even in a Windows Forms project be the Main method. Because this is returning a method, you cannot call Assembly.CreateInstance on it as this is used to create an instance of a Type (which in the case of the Main method is probably called Namespace.For.Project.Program.
You also need to ensure that you're passing the correct number of parameters to the method you're calling, in the second parameter to the call to method.Invoke. In a simple console application, the Main method has a signature of:
static void Main(string[] args)
This means that you need to pass one parameter in, an array of strings. Putting this all together you get:
byte[] file = Properties.Resources.ExeName;
Assembly assembly = Assembly.Load(file);
// search for the Entry Point
MethodInfo method = assembly.EntryPoint;
if (method != null)
{
// Get the type that implements the EntryPoint method
var implementingType = method.DeclaringType;
// Call the EntryPoint method, passing in an empty array of strings as its parameters
method.Invoke(implementingType, new object[] { new string[] { } });
}
When I've created the assembly that is referenced by Properties.Resources.Exename as a "simple" console application (targeting .net Framework 2.0) with the following for the Main method:
static void Main(string[] args)
{
MessageBox.Show("Message " + args == null ? "NULL" : "NOT NULL " + args.Length);
}
Running the program pops a message box with the text "NOT NULL 0" in it, indicating that the parameter has been passed through and is an empty array, which is what I was expecting to see.

Trouble with "Assembly.EntryPoint.Invoke" [C#]

I have the following problem:
I am compiling C#-code at runtime using the CSharpCodeProvider in Microsoft.CSharp. The created application runs perfectly, if I double-click on the generated file.
If, however, I am loading my created assembly with Assembly.Load and invoking the entrypoint-method with Assembly.Load("...").EntryPoint.Invoke(null, null), I get a NullReferenceException.
The NullReferenceException is referring to the value of the .EntryPoint-Property.
When I debug the variable containing the loaded Assembly, VisualStudio shows the following:
Larger image
The error is in German and means The value of "local" or argument "asm" is not available in this instruction pointer and can therefore not be determined. It may have been removed during optimization.
I want to add at this point that my generated assembly is not optimized (I also added the compiler argument /optimize-, which prevents optimization.)
I performed an other test to determine the error source by trying this Code:
Assembly asm = Assembly.LoadFile(Assembly.GetExecutingAssembly().Location);
asm.EntryPoint.Invoke(null, argv);
This code is also throwing a NullReferenceException at the line containing the Invoke-call.
Does someone here know, where this error is coming from and I can solve it?
Thank you very much :)
EDIT:
The entrypoint-method is defined as follows:
namespace tmp
{
public static class Program
{
[STAThread]
public static void Main(string[] argv)
{ ... }
}
}
I also tried to invoke it with .EntryPoint.Invoke(null, new string[]{"test", "argument"}), but it didn't solve the problem :/
EDIT #2: I found my error - please look at the comment from #Hans Passant and myself for the soulution
~closed~
Copy and paste from Hans Passant's comment:
// Get your assembly.
Assembly asm = Assembly.LoadFile(Assembly.GetExecutingAssembly().Location);
// Get your point of entry.
MethodInfo entryPoint = asm.EntryPoint;
// Invoke point of entry with arguments.
entryPoint.Invoke(null, new object[] { new string[] { "arg1", "arg2", "etc" } } );
If you want to access an assembly from an embedded resource, use this snippet:
byte[] yourResource = Properties.Resources.YourResourceName;
Assembly asm = Assembly.Load(yourResource);
what if you try something like this will it work?
Assembly asm = Assembly.LoadFile(Assembly.GetExecutingAssembly().Location);
MethodInfo myMethod = asm.EntryPoint;
myMethod.Invoke(null, args);
assuming that that you know the method you want to invoke

C# exception not being thrown/caught

I am trying to load dlls into my program at runtime that match a specific assembly attribute that I have set. In order to make sure that the dll is loadable before I check its flag I have written the following method:
private bool IsValidDll(string dll) {
try {
System.Reflection.Assembly.LoadFrom(dll);
return true;
} catch (Exception ex) { return false; }
}
I can loop through dlls in my current directory and call this method to see if it will be safe to load the dll and check its assembly attributes. However, I am hitting a dll that is not throwing/catching an Exception and is still just directly crashing the program. The relevant output window information is as follows:
LoaderException: System.IO.FileLoadException: Mixed mode assembly is built against
version 'v2.0.50727' of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information. - Adapters.Spryware.SprywareAdapter
System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
I have tried catching the specific Exception (System.IO.FileLoadException) but the catch block is still skipped over and I still crash. Any thoughts?
Also, I find that this is a pretty heavy handed way of checking for my assembly attribute. Is there a way to check for my flag without having to load the dll with Reflection first?
Have to confess, I dont see why your code doesnt work either:
I made a .net 4 thing and ran and mine did catch it:
private void button1_Click(object sender, EventArgs e)
{
// foreach (String file in Directory.GetFiles("c:\\windows", "*.dll"))
String file = #"C:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.Data.dll";
{
try
{
//System.Reflection.Assembly.ReflectionOnlyLoadFrom(file);
System.Reflection.Assembly.LoadFrom(file);
}
catch (Exception ee)
{
textBox1.Text += ee.Message + Environment.NewLine;
}
}
}
On clicking the text box reads:
Could not load file or assembly 'file:///C:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.Data.dll' or one of its dependencies. An attempt was made to load a program with an incorrect format.
You can probably solve this problem and be less heavy handed by loading the assemblies into the reflection-only context.
Basically, instead of fully loading the assembly, this gives you the ability to reflect over the assembly without the ability to do things like instantiate objects. This expressly allows you to look at assemblies that are built against different .NET framework versions than the one on which your application is running.
A thorough treatment is available on MSDN: http://msdn.microsoft.com/en-us/library/ms172331.aspx

Load an assembly from an embedded resource

I would like to load a dll file (Test.dll) as an assembly. I am able to do this using both direct Visual Studio references (ie. loading the dll as a reference to my C# application) as well as loading the dll using the Assembly.LoadFile(filename) method. Now, I would like to add my dll file as an embedded resource to my Visual Studio application, and load the dll file as an assembly. I know how to load this resource as a byte array, is there some correlation between the byte array and the assembly that I could use? Furthermore, I need to be able to call a method located within the dll file. See the code below - it will further explain what I am doing.
Assembly SampleAssembly = Assembly.LoadFrom("WindowsFormsApplication2.ThisisaTESTDLL.dll");
Type myType = SampleAssembly.GetTypes()[0];
MethodInfo Method = myType.GetMethod("myVoid");
object myInstance = Activator.CreateInstance(myType,null);
Method.Invoke(myInstance,new object[] { "param1", "param1"});
If I am missing anything here, please respectfully let me know and I will edit the original post.
Assembly.GetExecutingAssembly().GetManifestResourceStream(...)
That should get you a Stream object. You can read a byte array from that.
You can load that using Assembly.Load
I embedded AxInterop.WMPLib.dll and Interop.WMPLib.dll into my exe and got them loaded by using the following code. The code is placed just at the beginning of static void Main() in Program.cs file. Target framework is .NET 3.5 in my case. This code helped me bundle the dlls into the exe itself without having to deploy them through installers. I have hardcoded my names. In the code below "res" is the name of my resource "res.resx" that contains the two embedded dlls.
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(
(s, a) =>
{
if (a.Name.Substring(0, a.Name.IndexOf(",")) == "AxInterop.WMPLib")
{
return Assembly.Load(res.AxInterop_WMPLib);
}
if (a.Name.Substring(0, a.Name.IndexOf(",")) == "Interop.WMPLib")
{
return Assembly.Load(res.Interop_WMPLib);
}
return null;
});

Categories

Resources