【问题标题】:Executing a c# WPF application inside an already running c# process在已经运行的 c# 进程中执行 c# WPF 应用程序
【发布时间】:2017-04-14 19:48:38
【问题描述】:

我正在尝试建立一个自动检查是否可以毫无问题地打开多个 32 位 WPF 应用程序。

我不想使用 Process.Start,因为我无法确定每个程序是否会在出现问题时返回非零退出代码(并且我必须使用更多代码关闭这些 WPF 应用程序)。

我的计划是:在运行时加载程序集并触发它们的启动方法(连接到一些异常事件接收器以获取有关问题的信息并关闭稍后打开的窗口)。

这是我目前得到的:

public void Check(string executablePath)
  {
     try
     {
        Assembly assembly;
        try
        {
           assembly = Assembly.LoadFrom(executablePath);
        }
        catch (BadImageFormatException e)
        {
           Logger.InfoFormat("Not a 32 bit .NET application : {0}", Path.GetFileName(executablePath));
           return;
        }           
        assembly.EntryPoint.Invoke(null, new object[] { });

        Logger.InfoFormat("OK : {0}", Path.GetFileName(executablePath));
     }
     catch (Exception e)
     {
        Logger.Error(e);
     }
}

我的问题:我一调用 EntryPoint 方法,就会出现来自应用程序内部的错误屏幕,告诉我发生了 IOExeption(它无法找到启动屏幕的资源) .

我是否必须以某种方式在其他程序集中预加载这些资源才能使其正常工作?

更新

有了 Dirks 的回答,我能够创建一个新的应用程序域并将入口点的调用委托给由该域创建的 MarshalByRefObject 后代。

感谢这个网站(目前不在线),我还能够更改 Assembly.EntryAssembly 的值

http://webcache.googleusercontent.com/search?q=cache:6POIVfrxbAcJ:dejanstojanovic.net/aspnet/2015/january/set-entry-assembly-in-unit-testing-methods/+&cd=8&hl=en&ct=clnk&gl=de

代码 sn-p 做这项工作:

  private void ModifyEntryAssembly(Assembly assembly)
  {
     AppDomainManager manager = new AppDomainManager();
     FieldInfo entryAssemblyfield = manager.GetType().GetField("m_entryAssembly", BindingFlags.Instance | BindingFlags.NonPublic);
     if (entryAssemblyfield == null)
     {
        throw new Exception("Could not retrieve entryAssemblyField.");
     }
     entryAssemblyfield.SetValue(manager, assembly);

     AppDomain domain = AppDomain.CurrentDomain;
     FieldInfo domainManagerField = domain.GetType().GetField("_domainManager", BindingFlags.Instance | BindingFlags.NonPublic);
     if (domainManagerField == null)
     {
        throw new Exception("Could not retrieve domainManagerField.");
     }
     domainManagerField.SetValue(domain, manager);  
  }

现在,我从被调用的可执行文件中获取启动画面和登录对话框,现在更进一步!

还有一个抛出 EEntryPointException 的问题,但这是另一个问题的另一个故事......谢谢!

【问题讨论】:

    标签: c# wpf reflection resources assemblies


    【解决方案1】:

    entry 程序集1 中搜索 WPF 初始屏幕,在您的情况下,它是您的主要可执行文件,而不是您尝试检查的可执行文件。

    您可以通过在自己的应用程序域中启动被测应用程序来解决此问题,然后该应用程序将获得自己的入口程序集:

    class Test 
    {
        public static void Main() 
        {
            var otherDomain = AppDomain.CreateDomain("otherDomain");
    
            otherDomain.ExecuteAssembly("MyExecutable.exe");
        }
    }
    

    但是,您应该知道,您的方法会给您带来误报,因为被测应用程序在另一个环境中运行。例如,调用Assembly.GetExecutingAssembly() 将在被测应用程序中给出不同的结果。而且您的方法将无法同时测试 32 位和 64 位应用程序。

    1reference source可以看出,SplashScreen构造函数的下面重载调用Assembly.GetEntryAssembly()

    public SplashScreen(string resourceName) 
        : this(Assembly.GetEntryAssembly(), resourceName)
    {
    }
    

    【讨论】:

    • 谢谢!我能够解决入口程序集的问题,请参阅我的问题更新。 :-)
    猜你喜欢
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多