C
C#10mo ago
Tim

✅ Get window handle when it's created

In my WPF app, I want to embed the window from a Process (a Unity player application). I'm extending HwndHost to host it in a control. I create a Process with the executable, and start it. The Unity player obviously takes a bit to load and the window is not created immediately (not even after calling Process.WaitForInputIdle). Is there some way of getting the player window handle immediately when it is created? I tried - Using Process.MainWindowHandle, but that value is not set until it's created, so I'd have to block the thread waiting for it. - Using EnumChildWindows, may be a bit more reliable, but has the same issue as above. Ideally I want to start the player process and when it creates the main window immediately embed it, without it flashing on the screen or showing in the task bar.
5 Replies
JakenVeina
JakenVeina10mo ago
the only way you're getting that level of granularity with inter-process comminication is with APIs that the process itself provides, or with OS-level APIs what you'd need is some kinda API to intercept and redirect the OS CreateWindow call, or an API to monitor or interecept OS event messages being sent to the process maybe this lines up with what you're trying to do?
JakenVeina
JakenVeina10mo ago
Stack Overflow
How can I make a child process window to appear modal in my process?
I have an application that calls some other utility application to set some settings for a particular device. That utility application is called using ShellExecuteEx. So as not to confuse the user...
Tim
Tim10mo ago
alright, thanks for the info! It seems that embedding a separate window is quite difficult to do right. I'm going to try another option that unity gives, by directly calling the player dll in my application. Idk if that makes it possible to embed correctly but we'll see Their documentation shows this dll call extern "C" UNITY_API int UnityMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd); How do I translate that to C#? I have this atm:
[DllImport("UnityPlayer.dll", CharSet = CharSet.Unicode)]
internal static extern int UnityMain(IntPtr hInstance, IntPtr hPrevInstance, [MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, int nShowCmd);
[DllImport("UnityPlayer.dll", CharSet = CharSet.Unicode)]
internal static extern int UnityMain(IntPtr hInstance, IntPtr hPrevInstance, [MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, int nShowCmd);
but it creates an exception Unhandled Exception: System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B) Found it, I thought the player was x86 but it was x64 Oh wait this calls the full application ;-; You have any other ideas on how to embed nicely? I solved this by using a while loop until the process.MainWindowHandle becomes available. To not block the main thread I used an async function that accepted a delegate, and then created a task that, when finished, called the delegate which in turn did all the logic to correctly insert it into my WPF app This feels 'hacky' but it is what it is Any other suggestions are welcome
JakenVeina
JakenVeina10mo ago
I'm not QUITE sure what you're saying about the mechanics, but yeah, that's pretty much the only option you've got, poll until you find the window
Tim
Tim10mo ago
Allright, fair enough, thanks!