Download WPF from memory

Thus, you call Main () in applications without WPF:

var entry = assembly.EntryPoint; if (assembly.EntryPoint.GetParameters().Length == 0) entry.Invoke(null, new object[0]); else entry.Invoke(null, new object[] { args }); 

but somehow it doesn’t work at all for WPF applications, I tried (MSDN method):

 Assembly asm = Assembly.LoadFrom(file); Type myType = asm.GetType("WpfApplication1.App"); // Get the method to call. MethodInfo myMethod = myType.GetMethod("Main"); // Create an instance. object obj = Activator.CreateInstance(myType); // Execute the method. myMethod.Invoke(obj, null); 

still no success, the reflector shows Main () as

 [DebuggerNonUserCode, STAThread] public static void Main() { App app = new App(); app.InitializeComponent(); app.Run(); } 

no matter what i do, i get a System.Reflection.TargetInvocationException exception.

Any help?

PS. More debugging showed that it cannot load the mainwindow.xaml resource, originally located in the assembly that I want to load

 {System.IO.IOException: Nie można zlokalizować zasobu „mainwindow.xaml". w MS.Internal.AppModel.ResourcePart.GetStreamCore(FileMode mode, FileAccess access) w System.IO.Packaging.PackagePart.GetStream(FileMode mode, FileAccess access) w System.IO.Packaging.PackagePart.GetStream() w System.Windows.Application.LoadComponent(Uri resourceLocator, Boolean bSkipJournaledProperties) w System.Windows.Application.DoStartup() w System.Windows.Application.<.ctor>b__0(Object unused) w System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter) w System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) w System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) w System.Windows.Threading.DispatcherOperation.InvokeImpl() w System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state) w System.Threading.ExecutionContext.runTryCode(Object userData) w System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) w System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) w System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) w System.Windows.Threading.DispatcherOperation.Invoke() w System.Windows.Threading.Dispatcher.ProcessQueue() w System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) w MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) w MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) w System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter) w System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) w System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) w System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter) w System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg) w MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) w MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg) w System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) w System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame) w System.Windows.Threading.Dispatcher.Run() w System.Windows.Application.RunDispatcher(Object ignore) w System.Windows.Application.RunInternal(Window window) w System.Windows.Application.Run(Window window) w System.Windows.Application.Run() w WpfApplication1.App.Main()} 

so I suspect the problem is that the CLR is trying to find the .xml in the loader application and not in the ACTUAL wpf application.

+4
source share
1 answer

I found a way to do this. You basically have two options.

  • Download exe to a separate AppDomain.
  • Use reflex blende to change the default ResourceAssembly resource.

The option first, while clean, has the disadvantage of slowing down (WPF must be loaded into the new AppDomain):

 //Assembly: WpfLoader.dll [STAThread] class Program { public class Loader : MarshalByRefObject { public void Load() { var dll = File.ReadAllBytes("WpfTest.exe"); var assembly = Assembly.Load(dll); Application.ResourceAssembly = assembly; assembly.EntryPoint.Invoke(null, new object[0]); } } static void Main(string[] args) { var domain = AppDomain.CreateDomain("test"); domain.Load("WpfLoader"); var loader = (Loader)domain.CreateInstanceAndUnwrap("WpfLoader", "WpfLoader.Program+Loader"); loader.Load(); } } 

The second solution uses reflection to modify the ResourceAssembly of the current application. You cannot do this using public APIs, because Application.ResourceAssembly is only read after installing it. You must use reflection to access the private members of the Application and ResourceUriHelper classes.

 var dll = File.ReadAllBytes("WpfTest.exe"); var assembly = Assembly.Load(dll); var app = typeof(Application); var field = app.GetField("_resourceAssembly", BindingFlags.NonPublic | BindingFlags.Static); field.SetValue(null, assembly); //fix urihelper var helper = typeof(BaseUriHelper); var property = helper.GetProperty("ResourceAssembly", BindingFlags.NonPublic | BindingFlags.Static); property.SetValue(null, assembly, null); //load assembly.EntryPoint.Invoke(null, new object[0]); 

There is a caveat in both solutions: you cannot use more than one Wpf application that uses relative resources in one application, so if you want to download more than one application, you need to create several AppDomains .

For these examples, you need to do two things:

  • It must be called from separate application state threads, so be sure to use [STAThread]
  • You need to add PresentationCore.dll, PresentationFramework.dll and WindowsBase.dll links
+3
source

Source: https://habr.com/ru/post/1434273/


All Articles