I´m trying to build up an automated check if several 32 bit WPF applications can be opened without problems.
I do not want to use Process.Start as i cannot be sure if each program will return a non-zero exit code in case a problem occurs (and i would have to close those WPF application with further code).
My plan instead: Loading the assemblies at runtime and triggering their start method (connecting to some exception event sinks to get infos about problems and closing the windows opened later on).
This is what i got so far:
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);
}
}
My problem: As soon as i invoke the EntryPoint method, an error screen from the application inside is presented telling me an IOExeption happened (it was not able to find the resource for the splash screen).
Do i have to preload those resources inside other assemblies somehow to get it working?
Update
With Dirks answer i was able to create a new application domain and delegating the call of the entry point to a MarshalByRefObject descendant created by this domain.
I was also able to change the value of Assembly.EntryAssembly thanks to this website (currently not online)
Code snippet doing the work:
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);
}
Now, im getting the splash screen and a login dialog from the called executable, much further now!
There is another problem with an EEntryPointException thrown, but that´s another story for another question... Thanks!