I solved this by getting the Parent-Handle using the answer from @Simon Mourier to get the parent
and changing the code that way:
private void OpenUrl(string url)
{
var oldProcessIds = Process.GetProcesses().Select(pr => pr.Id);
IntPtr handle = OpenApplication(url);
if (handle==IntPtr.Zero)
{
// Find out what Process is new
var processes = Process.GetProcesses();
var newProcess = processes.Where(pr => !oldProcessIds.Contains(pr.Id));
var parent = ParentProcessUtilities.GetParentProcess(newProcess.First().Handle);
Program.MoveWindow(parent.MainWindowHandle, 0, 500, 500, 300, true);
}
else
{
Program.MoveWindow(handle, 0, 0, 1500, 100, true);
}
}
private IntPtr OpenApplication(string application)
{
var externalApplication = new Process();
externalApplication.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
externalApplication.StartInfo.FileName = "http://www.example.com";
externalApplication.Start();
externalApplication.Refresh();
try
{
externalApplication.WaitForInputIdle();
return externalApplication.MainWindowHandle;
} catch
{
// Cannot get Handle. Application managaes multiple Threads
return IntPtr.Zero;
}
}
Code to retrieve the parent:
[StructLayout(LayoutKind.Sequential)]
public struct ParentProcessUtilities
{
// These members must match PROCESS_BASIC_INFORMATION
internal IntPtr Reserved1;
internal IntPtr PebBaseAddress;
internal IntPtr Reserved2_0;
internal IntPtr Reserved2_1;
internal IntPtr UniqueProcessId;
internal IntPtr InheritedFromUniqueProcessId;
[DllImport("ntdll.dll")]
private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength);
/// <summary>
/// Gets the parent process of the current process.
/// </summary>
/// <returns>An instance of the Process class.</returns>
public static Process GetParentProcess()
{
return GetParentProcess(Process.GetCurrentProcess().Handle);
}
/// <summary>
/// Gets the parent process of specified process.
/// </summary>
/// <param name="id">The process id.</param>
/// <returns>An instance of the Process class.</returns>
public static Process GetParentProcess(int id)
{
Process process = Process.GetProcessById(id);
return GetParentProcess(process.Handle);
}
/// <summary>
/// Gets the parent process of a specified process.
/// </summary>
/// <param name="handle">The process handle.</param>
/// <returns>An instance of the Process class or null if an error occurred.</returns>
public static Process GetParentProcess(IntPtr handle)
{
ParentProcessUtilities pbi = new ParentProcessUtilities();
int returnLength;
int status = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength);
if (status != 0)
return null;
try
{
return Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32());
}
catch (ArgumentException)
{
// not found
return null;
}
}
Explanation:
Before opening the URL the program remembers what processes existed before. So after creation the new process can be grabbed. From the Process the parent will be searched, which should be the main Browser process. The MainWindowHandle of that Process then is taken to move the window.
Note:
This is a "rough" first solution (more like a POC) until now. There are missing error handling routines and it optimistically assumes that no other process gets started in the same time.