【发布时间】: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 的值
代码 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