Is it an absolute requirement that the process must appear as itself in the Processes tab of Task Manager? Or can it run contained inside another host process?
If the latter, you could create a stub project containing the following Main
method and then compile two versions of the executable: one as 32-bit (LaunchX86.exe) and the other 64-bit (LaunchX64.exe).
static int Main(string[] args)
{
try
{
foreach (var t in Assembly.LoadFile(args[0]).GetTypes())
{
var methodInfo = t.GetMethod(
"Main",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
if (methodInfo != null)
{
int? retVal = 0;
// See https://mcmap.net/q/371330/-how-to-run-something-in-the-sta-thread#2378077
var thread = new Thread(() =>
{
try
{
// Main() methods may have zero or one parameters
var methodParams = methodInfo.GetParameters().Length == 0
? null
: new object[] {args.Skip(1).ToArray()};
retVal = methodInfo.Invoke(t, methodParams) as int?;
}
catch (Exception e)
{
retVal = 99; // Error 99: The executable itself threw an exception
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
return retVal ?? 0;
}
}
return 98; // Error 98: unable to launch exe because no method "Main" found
}
catch (Exception e)
{
// Can identify exception type here and return appropriate result, e.g.:
// ArgumentNullException - no EXE name provided in first param
// BadImageFormatException - specified file was not a suitable EXE
return 97; // Error 97: unable to load executable for analysis
}
}
Note: to keep things simple, above has very coarse catching of exceptions and maps those to a few fixed return values.
Also, note that in the Invoke()
method, we are not passing any parameters to the Main()
method for WPF applications, because the WPF application automatically receives the same parameters as those of the launcher. This is not ideal but various workarounds are possible, such as setting an environment variable using Environment.SetEnvironmentVariable()
before launching, checking for that variable within the target application using Environment.GetEnvironmentVariable()
and (if present) using its contents in place of the normal method.
Then from your primary application you launch the relevant host executable depending on your current process's bitness:
new Process
{
StartInfo = new ProcessStartInfo(
Environment.Is64BitProcess ? "LaunchX64.exe" : "LaunchX86.exe",
"application_to_be_hosted.exe param1 param2 etc."
)
}.Start();