Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从另一个WPF应用程序加载WPF应用程序集,获取错误:无法在同一AppDomain中创建多个System.Windows.application实例_C#_Wpf_Appdomain - Fatal编程技术网

C# 从另一个WPF应用程序加载WPF应用程序集,获取错误:无法在同一AppDomain中创建多个System.Windows.application实例

C# 从另一个WPF应用程序加载WPF应用程序集,获取错误:无法在同一AppDomain中创建多个System.Windows.application实例,c#,wpf,appdomain,C#,Wpf,Appdomain,情景: leunter.exe:WPF应用程序>构建32位,.Net 4.5.1,location=D:\ LOADED.exe:另一个WPF应用程序>构建32位,.Net 4.5.1,location=D:\ 我是两个程序集的所有者(应用程序和thair源) 现在,我想将LOADED.exe[及其资源,如图像DLL和…)作为字节数组加载到内存中并执行它,然后从硬盘中删除LOADED.exe及其资源 在第一步中,我尝试将加载的.exe文件加载到内存中并执行它(因此在这一步中,我使用了一个简单的e

情景:

leunter.exe:WPF应用程序>
构建32位
.Net 4.5.1
location=D:\

LOADED.exe:另一个WPF应用程序>
构建32位
,.Net 4.5.1,
location=D:\

我是两个程序集的所有者(应用程序和thair源)

现在,我想将
LOADED.exe
[及其资源,如图像DLL和…)作为
字节数组加载到内存中并执行它,然后从硬盘中删除
LOADED.exe
及其资源

在第一步中,我尝试
将加载的.exe文件加载到内存中并执行它
(因此在这一步中,我使用了一个
简单的exe,没有任何资源

A) 好的,我发现WinForm程序是这样的:

我在一个按钮下尝试了它,然后运行…处理异常的结果:

无法在同一AppDomain中创建多个System.Windows.Application实例。

好的


B) 然后,我搜索了一个解决方案,有人说你必须在一个新的[不同的]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);
    }
}
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[] {});
}
现在我的错误在这一行:

好的


C) 我又搜索了一遍,找到了这个():

然后,我通过
午餐程序.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);
    }
}
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[] {});
}
但我得到了与前面方法相同的错误
**B**

中发生类型为“System.TypeLoadException”的未处理异常 午餐程序

其他信息:无法从程序集加载类型“Main” 已加载,版本=1.0.0.0,区域性=中性, PublicKeyToken=null'


D) 我还在
午餐程序.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[] {});
}
在运行时的最后一行代码中出现错误:

类型的未处理异常 mscorlib.dll中发生了“System.Reflection.TargetInvocationException

其他信息:异常已由的目标引发 调用。


最后: 我糊涂了

  • 以上所有方法中我的错误是什么
  • 为什么所有的方法都以错误告终
请帮助我简单描述和一些代码,因为我是这个场景的初学者(加载程序集、创建
AppDomain
和…),但我需要将WPF应用程序加载到内存并显示其窗口,然后在内存中运行时从H.D.D删除其文件

  • 创建共享程序集。这将加载到两个AppDomain(“启动器”域、“加载”域)中,并作为“加载”AppDomain的入口点:

    添加新项目>类库>名称:
    ChildDomainLoader

    向新项目添加以下引用:
    System.Xaml
    WindowsBase
    PresentationFramework

    启动器
    项目中为
    ChildDomainLoader
    添加项目引用。不必修改
    加载的
    项目

  • 向共享程序集添加一些代码。我们需要一个可以跨域调用并加载子程序集的MarshallByRefObject。我们将其称为
    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);
            }
        }
    }
    
  • 使用它。从启动程序应用程序调用
    Runner.RunInOtherDomain

    var assemblyPath = "path to your loaded.exe";
    ChildDomainLoader.Runner.RunInOtherDomain(assemblyPath);
    File.Delete(assemblyPath);
    

  • 我建议您缩小问题(目前它看起来更像是一个应用程序开发的请求),并指定代码的主要部分导致问题。诚挚的问候,您也可以考虑使用Surrun.St.(启动)启动启动程序的另一个应用程序。这里描述的方法:我知道process.start,但我想在运行后删除exe文件!!!这个问题有一些示例,而且很长,但我的要求很简单,答案不会很大!非常感谢:D…您的说明非常有效!当然,在我关闭
    LOADED.exe
    后会删除文件,因为午餐者加载程序等待加载结束以继续。因此,我向RunInOtherDomain和Run方法添加了一个bool参数,以检测是否也必须删除程序集,然后我添加了以下代码以在加载程序集后运行:
    if(forceDeleteAssembly&&File.Exists(assemblyPath))File.delete(assemblyPath);
    现在一切正常:)