场景:
LUNCHER.exe:WPF应用程序>> Build 32bit,.Net 4.5.1,location= D:\
LOADED.exe:另一个WPF应用程序>> Build 32bit,.Net 4.5.1,location= D:\
我owner of both assembly(申请和thair来源)
现在,我想将LOADED.exe[及其资源,如图像dll和...)作为Byte array内存加载到内存中并执行它,然后LOADED.exe从硬盘中删除它的资源.
在我尝试的第一步just load the LOADED.exe file to memory and execute it(所以我simple EXE without any resource在这一步中使用了a ).
好的,我在这里找到了WinForm程序的方法:
var filePath = @"D:\LOADED.EXE";
if (File.Exists(filePath))
{
try
{
// prepare to load the application into memory (using Assembly.Load)
// read the bytes from the application exe file
var fs = new FileStream(filePath, FileMode.Open);
var br = new BinaryReader(fs);
byte[] bin = br.ReadBytes(Convert.ToInt32(fs.Length));
fs.Close();
br.Close();
// load the bytes into Assembly
var asm = Assembly.Load(bin);
// search for the Entry Point
var method = asm.EntryPoint;
if (method != null)
{
// create an istance of the Startup form Main method
object o = asm.CreateInstance(method.Name);
// invoke the application starting point
Application.Current.ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;
method.Invoke(o, null);
}
else
{
//show message: Impossible to launch the application
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message + "\n\r\n\r" + ex.InnerException + "\n\r\n\r" + "\n\r\n\r" + ex.Source);
// exception throws .. something to do?
}
}
Run Code Online (Sandbox Code Playgroud)
我在一个按钮下面的LUNCHER.exe中尝试了它然后运行...处理异常的结果:
无法在同一AppDomain中创建多个System.Windows.Application实例.

好!
然后,我搜索了一个解决方案,一些人已经说过你必须执行它new [different] AppDomain.
例如,这里有一个答案:动态加载程序集 - 设置和通信
我在下面的另一个按钮下通过以下代码尝试了LUNCHER.exe:
private void Button_Click_1(object sender, RoutedEventArgs e)
{
try
{
var filePath = string.Format("{0}{1}", Utility.ExePath, PART_PATH);
AppDomain newappdomain = getAppDomainForAssembly(filePath, "LOADED.exe.domain");
object loadedexe_object = getInstanceFromAppDomain(ref newappdomain, filePath);
//If you know the method name to call...
executeMethod(loadedexe_object.GetType(), "methodname", ref loadedexe_object, null);
//or get entry point...
executeMethod(loadedexe_object.GetType(),
_asm_resolve(filePath).EntryPoint.Name, ref loadedexe_object, null);
}
catch (Exception ex)
{
var type = "";
if (ex is ArgumentNullException)
{
type = "ArgumentNullException";
}
else if (ex is NotSupportedException)
{
type = "NotSupportedException";
}
else if (ex is AppDomainUnloadedException)
{
type = "AppDomainUnloadedException";
}
else if (ex is TypeLoadException)
{
type = "TypeLoadException";
}
else if (ex is MissingMethodException)
{
type = "MissingMethodException";
}
else if (ex is MethodAccessException)
{
type = "MethodAccessException";
}
else if (ex is BadImageFormatException)
{
type = "BadImageFormatException";
}
else if (ex is FileLoadException)
{
type = "FileLoadException";
}
MessageBox.Show(type + "\n\r\n\r" + ex.Message + "\n\r\n\r" + ex.InnerException + "\n\r\n\r" + ex.Source);
}
}
private AppDomain getAppDomainForAssembly(string assemblypath, string appdomainname)
{
//this._assembly_file = AssemblyFile;
string _assembly_file_name = System.IO.Path.GetFileName(assemblypath);
string _rootpath = System.IO.Path.GetDirectoryName(assemblypath);
//this._assembly_class_name = AssemblyClassNameToInstance;
AppDomainSetup _app_domain_info = new AppDomainSetup();
_app_domain_info.ApplicationBase = _rootpath;
_app_domain_info.PrivateBinPath = _rootpath;
_app_domain_info.PrivateBinPathProbe = _rootpath;
_app_domain_info.ConfigurationFile = _rootpath + @"LOADED.exe.config"; //Here put the path to the correct .assembly .config file
AppDomain _app_domain = AppDomain.CreateDomain(appdomainname, null, _app_domain_info);
return _app_domain;
}
protected System.Reflection.Assembly _asm_resolve(string assemblyFile)
{
return System.Reflection.Assembly.LoadFrom(assemblyFile);
}
private object getInstanceFromAppDomain(ref AppDomain appDomain,
string assemblyPath, string className = null)
{
if (string.IsNullOrEmpty(className))
{
System.Reflection.Assembly assembly = _asm_resolve(assemblyPath);
System.Reflection.MethodInfo method = assembly.EntryPoint;
// Now my ERROR is in this line>>
return appDomain.CreateInstanceFromAndUnwrap(assemblyPath, method.Name);
}
else
{
return appDomain.CreateInstanceFromAndUnwrap(assemblyPath, className);
}
}
Run Code Online (Sandbox Code Playgroud)
现在我的错误在这一行:

好!
我再次搜索并找到了这个(动态加载程序集未加载到新的AppDomain中):
// Provides a means of invoking an assembly in an isolated appdomain
public static class IsolatedInvoker
{
// main Invoke method
public static void Invoke(string assemblyFile, string typeName, string methodName, object[] parameters)
{
// resolve path
assemblyFile = Path.Combine(Environment.CurrentDirectory, assemblyFile);
Debug.Assert(assemblyFile != null);
// get base path
var appBasePath = Path.GetDirectoryName(assemblyFile);
Debug.Assert(appBasePath != null);
// change current directory
var oldDirectory = Environment.CurrentDirectory;
Environment.CurrentDirectory = appBasePath;
try
{
// create new app domain
var domain = AppDomain.CreateDomain(Guid.NewGuid().ToString(), null, appBasePath, null, false);
try
{
// create instance
var invoker = (InvokerHelper) domain.CreateInstanceFromAndUnwrap(Assembly.GetExecutingAssembly().Location, typeof(InvokerHelper).FullName);
// invoke method
var result = invoker.InvokeHelper(assemblyFile, typeName, methodName, parameters);
// process result
Debug.WriteLine(result);
}
finally
{
// unload app domain
AppDomain.Unload(domain);
}
}
finally
{
// revert current directory
Environment.CurrentDirectory = oldDirectory;
}
}
// This helper class is instantiated in an isolated app domain
private class InvokerHelper : MarshalByRefObject
{
// This helper function is executed in an isolated app domain
public object InvokeHelper(string assemblyFile, string typeName, string methodName, object[] parameters)
{
// create an instance of the target object
var handle = Activator.CreateInstanceFrom(assemblyFile, typeName);
// get the instance of the target object
var instance = handle.Unwrap();
// get the type of the target object
var type = instance.GetType();
// invoke the method
var result = type.InvokeMember(methodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, instance, parameters);
// success
return result;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后我通过以下代码在下面的另一个按钮下调用它LUNCHER.exe:
private void Button_Click_2(object sender, RoutedEventArgs e)
{
var filePath = string.Format("{0}{1}", Utility.ExePath, PART_PATH);
IsolatedInvoker.Invoke(filePath, "Main", "Main", new object[] {});
}
Run Code Online (Sandbox Code Playgroud)
但我像以前一样得到同样的错误**B**:
Luncher.exe中发生了未处理的"System.TypeLoadException"类型异常
附加信息:无法从程序集Loaded,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'加载类型'Main'.
另外我在下面的另一个按钮下测试了这种方式LUNCHER.EXE:
private void Button_Click_3(object sender, RoutedEventArgs e)
{
var filePath = @"D:\LOADED.exe";
var dll = File.ReadAllBytes(filePath);
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);
//---- Now my ERROR is in this line >>
assembly.EntryPoint.Invoke(null, new object[] {});
}
Run Code Online (Sandbox Code Playgroud)
并且在运行时的最后一行代码中出现错误:
mscorlib.dll中发生未处理的" System.Reflection.TargetInvocationException " 类型异常
附加信息:调用目标引发了异常.
我糊涂了!
请帮我简单的描述和一些代码,因为我是这个场景的初学者(加载程序集,创建AppDomain和...)但我需要将WPF应用程序加载到内存并显示其窗口,然后从HDD删除它的文件它在内存中运行.
创建共享程序集。这将被加载到两个 AppDomain(“启动器”域、“已加载”域)中,并作为“已加载”AppDomain 的入口点:
添加新项目>类库>名称:ChildDomainLoader
将以下引用添加到新项目:System.Xaml, WindowsBase,PresentationFramework
ChildDomainLoader在您的项目中添加项目参考Launcher。该Loaded项目无需修改。
将一些代码添加到共享程序集中。我们需要一个可以跨域调用并加载我们的子程序集的 MarshalByRefObject。我们称它为Runner:
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows;
namespace ChildDomainLoader
{
public class Runner : MarshalByRefObject
{
public static AppDomain RunInOtherDomain(string assemblyPath)
{
var ownType = typeof (Runner);
string ownAssemblyName = ownType.Assembly.FullName;
// Create a new AppDomain and load our assembly in there.
var childDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString());
childDomain.Load(ownAssemblyName);
// Call Run() in other AppDomain.
var runner = (Runner) childDomain.CreateInstanceAndUnwrap(ownAssemblyName, ownType.FullName);
runner.Run(assemblyPath);
return childDomain;
}
public void Run(string assemblyPath)
{
// We load the assembly as byte array.
var otherAssemblyBytes = File.ReadAllBytes(assemblyPath);
var assembly = AppDomain.CurrentDomain.Load(otherAssemblyBytes);
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
throw new NotImplementedException("Probably need to do some work here if you depend on other assemblies.");
};
// Set the assembly as ResourceAssembly, as WPF will be confused otherwise.
Application.ResourceAssembly = assembly;
// Search for the App class.
var app = assembly
.GetExportedTypes()
.Single(t => typeof(Application).IsAssignableFrom(t));
// Invoke its Main method.
MethodInfo main = app.GetMethod("Main", BindingFlags.Static | BindingFlags.Public);
main.Invoke(null, null);
}
}
}
Run Code Online (Sandbox Code Playgroud)用它。从您的启动器应用程序调用Runner.RunInOtherDomain。
var assemblyPath = "path to your loaded.exe";
ChildDomainLoader.Runner.RunInOtherDomain(assemblyPath);
File.Delete(assemblyPath);
Run Code Online (Sandbox Code Playgroud)