How to load assembly into memory and execute it - c#

This is what im doing:
byte[] bytes = File.ReadAllBytes(#Application.StartupPath+"/UpdateMainProgaramApp.exe");
Assembly assembly = Assembly.Load(bytes);
// load the assemly
//Assembly assembly = Assembly.LoadFrom(AssemblyName);
// Walk through each type in the assembly looking for our class
MethodInfo method = assembly.EntryPoint;
if (method != null)
{
// create an istance of the Startup form Main method
object o = assembly.CreateInstance(method.Name);
// invoke the application starting point
try
{
method.Invoke(o, null);
}
catch (TargetInvocationException e)
{
Console.WriteLine(e.ToString());
}
}
The problem is that it throws that TargetInvocationException - it finds that the method is main, but it throws this exception since on this line:
object o = assembly.CreateInstance(method.Name);
o is remaining null. So I dug a bit into that stacktrace and the actual error is this:
InnerException = {"SetCompatibleTextRenderingDefault should be called before creating firstfirst IWin32Window object in the program"} (this is my translation since it gives me the stacktrace in half hebrew half english since my windows is in hebrew.)
What am i doing wrong?

The entry point method is static, so it should be invoked using a null value for the "instance" parameter. Try replacing everything after your Assembly.Load line with the following:
assembly.EntryPoint.Invoke(null, new object[0]);
If the entry point method is not public, you should use the Invoke overload that allows you to specify BindingFlags.

if you check any WinForm application Program.cs file you'll see there always these 2 lines
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
you need to call as well them in your assembly. At least this is what your exception says.

How about calling it in it's own process?

Related

Unable to cast object of type 'System.__ComObject' to type 'Windows.ApplicationModel.Background.ILocationTriggerFactory

I'm building simple win phone 8.1 app which using geofence api and background tasks for controlling, when user enter/leaves some area.
To register background task i implement RegisterBackgroundTask method in App class
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.Suspending += this.OnSuspending;
this.RegisterBackgroundTask();
}
private async void RegisterBackgroundTask()
{
const string name = "GeofenceBackgroundTask";
if (BackgroundTaskRegistration.AllTasks.Any(task => task.Value.Name == name))
{
return;
}
var loc = await new Geolocator().GetGeopositionAsync(
TimeSpan.FromMinutes(2),
TimeSpan.FromSeconds(5)); //needed to trig user acceptance
var backgroundAccessStatus =
await BackgroundExecutionManager.RequestAccessAsync();
if (backgroundAccessStatus != BackgroundAccessStatus.Denied)
{
var geofenceTaskBuilder = new BackgroundTaskBuilder()
{
Name = name,
TaskEntryPoint = "RingtoneManager.Background.GeofenceBackgroundTask"
};
geofenceTaskBuilder.SetTrigger(new LocationTrigger(LocationTriggerType.Geofence));
geofenceTaskBuilder.Register();
}
}
And this is the part, which raise the exception
new LocationTrigger(LocationTriggerType.Geofence)
Exception details:
System.InvalidCastException was unhandled by user code
HResult=-2147467262
Message=Unable to cast object of type 'System.__ComObject' to type 'Windows.ApplicationModel.Background.ILocationTriggerFactory'.
Source=mscorlib
StackTrace:
at System.StubHelpers.StubHelpers.GetCOMIPFromRCW_WinRT(Object objSrc, IntPtr pCPCMD, IntPtr& ppTarget)
at Windows.ApplicationModel.Background.LocationTrigger..ctor(LocationTriggerType triggerType)
at RingtoneManager3.App.<RegisterBackgroundTask>d__2.MoveNext()
What i have figure out so far:
Exception code is 80004002 (E_NOINTERFACE)
I've investigate what is this interface and found, that it declared in C:\Program Files (x86)\Windows Phone Kits\8.1\References\CommonConfiguration\Neutral\Windows.winmd and its actually there
And its referenced from visual studio project
Every other triggers (SystemTrigger, MaintenanceTrigger e.t.c) are instantiating fine
What i have already tried:
Reinstall VS
Clean/Rebuild solution
Annotating method RegisterBackgroundTask with [STAThread]
This is my first app on windows phone and on c#, so i may do some stupid mistakes in common place. I'm also dont understand how visual studio process those references from solution and how interfaces, that coded in referenced .winmd files, became available to code in project. Maybe there is where something goes wrong. So i need help in searching the root of problem and finding the solution.
Thank you in advance
It could be that "LocationTrigger" is a singleton? (sorry, don't know phone) and has (already) been activated elsewhere with a generic System.__ComObject RCW. If this is the case it cannot be cast. Try using Activator.CreateInstance instead.
Type t = Type.GetTypeFromProgID("WhateverTheProgIdIsHere");
System.Object obj = Activator.CreateInstance(t);
ILocationTriggerFactory tf = obj as ILocationTriggerFactory;

retrieving all forms from my project

I know this question has been asked before. I have the code to do this but i am getting an error and I think I know why but I am just really getting into .Net Reflection so I wish to get confirmation on whether I am correct or not.
Here is the code. I want to retrieve all the forms from my project that have a basetype of "BaseEditForm" and then all of those that end with "EditForm" I want to put in a List to populate a ListBox.
public void LoadAllEditForms()
{
formsList = new List<string>();
try
{
Assembly project = Assembly.Load("UnionAdministrator");
foreach (Type t in project.GetTypes())
{
if (t.BaseType == typeof (BaseEditForm))
{
var emptyCtor = t.GetConstructor(Type.EmptyTypes);
if (emptyCtor != null)
{
var f = (Form) emptyCtor.Invoke(new object[] {});
if (f.Name.EndsWith("EditForm"))
formsList.Add(f.Name);
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I am getting the error message "Object reference not set to an instance of an object." on the line
var f = (Form) emptyCtor.Invoke(new object[] {});
emptyCtor is not null and besides there is no way for emptyCtor to get to this point if it is null. So I am confused about the error message. So here is my question. For this to work properly do all my forms have to have a default constructor? Almost all my forms have a constructor that takes one or more parameters. Is that my problem?
Your code works fine.
It must be one of your constructors that throw the exception.
Check all of your derived Forms to see if any of them (those that does not take any ctor parameters) could throw a NullReferenceException if invoked.
I'm not sure why you're going through the trouble of trying to execute the constructor of every form. You could simplify your code (and avoid the whole issue) by just looking at the type names.
public void LoadAllEditForms()
{
Assembly project = Assembly.Load("UnionAdministrator");
var formsList = project.GetTypes()
.Where (t => t.BaseType == typeof(BaseEditForm) && t.Name.EndsWith("EditForm"))
.ToList();
}

get assembly of method

Imagine the following situation:
Assembly A is starting the program. (it has a main method)
it loads Assembly B via reflection and instantiates a class of Assembly B.
in this instance a method is called where i would like to get to the Assembly B.
i have already tried
System.Reflection.Assembly.GetCallingAssembly();
System.Reflection.Assembly.GetExecutingAssembly();
but they always give me Assembly A instead of B.
Try getting type of class contain the method you are going for and get its assembly.
string assemblyName = this.GetType().Assembly.FullName;
The Assembly.GetExecutingAssembly() is the proper method to use.
You leave preciously few breadcrumbs to diagnose the cause of having trouble with it. There are however strings attached to this. An important job performed by the jitter is to make methods disappear. This is an optimization called "inlining". In effect, the call to the method is replaced by the code of the method. It is a very important optimization, it for example makes properties as cheap as using public fields. But a consequence it that you'll get the assembly of the calling method. In your case Main(). So you'll see assembly A and not B.
This is not something you ought to tinker with, avoid having a need for this. A method shouldn't be puzzled about what assembly it lives in, you could for example use the typeof(T).Assembly property where T is the class in which the method lives.
You can disable the inlining optimization, you do so with an attribute:
using System.Runtime.CompilerServices;
...
[MethodImpl(MethodImplOptions.NoInlining)]
public void Foo() { }
try this sample ,
public static object ExecuteAssemblyMethod(string methodName,Type assemblyObj, object[] arguments)
{
object result = null;
try
{
object ibaseObject = Activator.CreateInstance(assemblyObj);
result = assemblyObj.InvokeMember(methodName, BindingFlags.Default | BindingFlags.InvokeMethod, null, ibaseObject, arguments);
}
catch (ReflectionTypeLoadException emx)
{
result = null;
return result;
}
catch (Exception ex)
{
result = null;
return result;
}
return result;
}
Usage:-
Assembly assemb = Assembly.LoadFile(#"D:\TEMP\TestClassLibrary_new.dll");
Type testType = assemb.GetType("TestClassLibrary.Class1");
object[] param = new object[] {"akshay" };
object result = LoadAssembly.ExecuteAssemblyMethod("GetName", testType, param);

Reflection.Assembly.CreateInstance(string)

In .NET 4.0, if I have the following code:
....
T instantiatedClass;
try
{
instantiatedClass = (T)assembly.CreateInstance(classFullName);
}
catch (Exception ex)
{
errMsg = string.Format("Error creating an instance of type \"{0}\".", classes.First().FullName);
throw new ApplicationException(errMsg, ex);
}
Assuming that classFullName is a correct type in the assembly, and that the type "T" implements a public interface, is there any circumstance where 1) No exception would be thrown, and 2) instantiatedClass would be null?
Thanks for any help.
Based on your assumptions and if your type T is always an interface then a direct cast to T will throw an exception if the interface in question is not implemented by the created instance or if the type does not have a default constructor that can be called.
A better approach that avoids throwing an exception would be...
T interfaceVar = assembly.CreateInstance(classFullName) as T;
if (interfaceVar == null)
{
// oops, does not implement interface T
}
else
{
// yippee, it does implement interface T
}
You could use reflection on the target assembly to check if the required type exists, if it has a default constructor and if it implements the interface you are interested in. In that case you would avoid creating an instance at all, if all you want to know is if it has the specified interface.
If there is no default constructor or the assumption that classFullName is valid in the assembly is incorrect or anything prevents the CreateInstance call from calling a constructor an exception is thrown.
So the only way that this could fail for you is if the called constructor returns a null value. But this can't happen since if no exception is raised during construction, then the constructor call will return a reference to the new object, and if an exception is raised you catch it.

Different behavior of reflected generic delegates with and without debugger

We have encountered some strange things while calling reflected generic delegates. In some cases with attatched debuger we can make impossible call, while without debugger we cannot catch any exception and application fastfails.
Here is the code:
using System;
using System.Windows.Forms;
using System.Reflection;
namespace GenericDelegate
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private delegate Class2 Delegate1();
private void button1_Click(object sender, EventArgs e)
{
MethodInfo mi = typeof (Class1<>).GetMethod("GetClass", BindingFlags.NonPublic | BindingFlags.Static);
if (mi != null)
{
Delegate1 del = (Delegate1) Delegate.CreateDelegate(typeof (Delegate1), mi);
MessageBox.Show("1");
try
{
del();
}
catch (Exception)
{
MessageBox.Show("No, I can`t catch it");
}
MessageBox.Show("2");
mi.Invoke(null, new object[] {});//It's Ok, we'll get exception here
MessageBox.Show("3");
}
}
class Class2
{
}
class Class1<T> : Class2
{
internal static Class2 GetClass()
{
Type type = typeof(T);
MessageBox.Show("Type name " + type.FullName +" Type: " + type + " Assembly " + type.Assembly);
return new Class1<T>();
}
}
}
}
There are two problems:
Behavior differs with debugger and without
You cannot catch this error without debugger by clr tricks. It's just not the clr exception. There are memory acces vialation, reading zero pointer inside of internal code.
Use case:
You develop something like plugins system for your app. You read external assembly, find suitable method in some type, and execute it. And we just forgot about that we need to check up is the type generic or not. Under VS (and .net from 2.0 to 4.0) everything works fine. Called function does not uses static context of generic type and type parameters. But without VS application fails with no sound. We even cannot identify call stack attaching debuger.
Tested with .net 4.0
The question is why VS catches but runtime do not?
Well, yes, that doesn't behave very gracefully. It is partly fixed in .NET 4.0, the CreateDelegate() method returns null. That still doesn't behave gracefully when the JIT optimizer is enabled though, it assumes that CreateDelegate cannot return null and doesn't perform a null check. You'll get a FatalExecutionEngineError instead of NRE, an exception that is no longer catchable in 4.0
I'd recommend you report the defect to connect.microsoft.com. Not so sure they'll take you seriously, I don't know what their policy is when you intentionally bypass the safeguards. It could well be that they consider the FEEE good enough. The workaround is obvious, only call methods of concrete types.
I'm not sure I follow exactly what you want to do, but if you put your code in a try/catch block there certainly is an exception thrown.
Just tested under VS 2008
VS does not catch exception at all.
Here is modified test case
static class Program
{
private delegate Foo Delegate1();
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MethodInfo mi = typeof(Bar<>).GetMethod("GetClass", BindingFlags.NonPublic | BindingFlags.Static);
if (mi != null)
{
var del = (Delegate1)Delegate.CreateDelegate(typeof(Delegate1), mi);
MessageBox.Show("1");
try
{
del();
//mi.Invoke(null, BindingFlags.NonPublic | BindingFlags.Static, null, null,CultureInfo.InvariantCulture);
}
catch (Exception)
{
MessageBox.Show("No, I can`t catch it");
}
MessageBox.Show("2");
mi.Invoke(null, new object[] { });//It's Ok, we'll get exception here
MessageBox.Show("3");
}
}
class Foo
{
}
class Bar<T> : Foo
{
internal static Foo GetClass()
{
Type type = typeof(T);
MessageBox.Show("Type name " + type.FullName + " Type: " + type + " Assembly " + type.Assembly);
return new Bar<T>();
}
}
}
but if you comment del() und uncomment mi.Invoke() you will get nice exception
true.
Late bound operations cannot be
performed on types or methods for
which ContainsGenericParameters is
true
I don't think that the code you posted actually works under the .net framework vers. 2.0 to 4.0. Static methods can be called AFAIK only on closed generic types, not on opened generic types. So you'll have to provide a type parameter. As for the debugger, try to launch your process outside Visual Studio and then attach the VS-Debugger. This time you'll get the expected exception right away.

Categories

Resources