0

How can i get hWnd of a hidden window? With my configuration it returns 0.

This is what i have tried:

ProcessStartInfo startInfo = new ProcessStartInfo(path);
startInfo.WindowStyle = ProcessWindowStyle.Hidden;

Process process = Process.Start(startInfo);
process.WaitForInputIdle();

MessageBox.Show(process.MainWindowHandle.ToString());
Gangsteri
  • 21
  • 1
  • 3
  • Correct me if I'm wrong, but doesn't it make sense that it returns 0? As a hidden window doesn't exist, and as such there is no handle to it? – MindSwipe Apr 12 '21 at 13:20
  • 1
    It does exist. The system just doesnt draw it. It works fine if i launch the process then make the window style hidden. You can find more information about window styles here: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.processwindowstyle?view=net-5.0 – Gangsteri Apr 12 '21 at 13:23
  • Ok, then, are you setting `UseShellExecute` to `true` as required by the `ProcessWindowStyle.Hidden`? – MindSwipe Apr 12 '21 at 13:26
  • I think the default value is true. But i tried it and it doesnt make a difference. – Gangsteri Apr 12 '21 at 13:30
  • Does this answer your question? [C# Process.MainWindowHandle always returns IntPtr Zero](https://stackoverflow.com/questions/16185217/c-sharp-process-mainwindowhandle-always-returns-intptr-zero) Specifically this answer https://stackoverflow.com/a/25152035/14868997 – Charlieface Apr 12 '21 at 13:50
  • Im testing it out right now. – Gangsteri Apr 12 '21 at 13:58
  • It returns a value, but it doesnt seem to be valid because it doesnt work with ShowWindowAsync. – Gangsteri Apr 12 '21 at 14:15
  • Okay i got it to work with a foreach loop, but how do i know which of the hWnds is the right one? – Gangsteri Apr 12 '21 at 14:29

1 Answers1

2

This worked for me:

delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);

[DllImport("user32.dll")]
static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn,
    IntPtr lParam);

static IEnumerable<IntPtr> EnumerateProcessWindowHandles(int processId)
{
    var handles = new List<IntPtr>();

    foreach (ProcessThread thread in Process.GetProcessById(processId).Threads)
        EnumThreadWindows(thread.Id, 
            (hWnd, lParam) => { handles.Add(hWnd); return true; }, IntPtr.Zero);

    return handles;
}

Usage:

ProcessStartInfo startInfo = new ProcessStartInfo(path);
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process process = Process.Start(startInfo);
process.WaitForInputIdle();

IntPtr WindowHandle = EnumerateProcessWindowHandles(process.Id).First();
Gangsteri
  • 21
  • 1
  • 3
  • Work for me too, but the secondary exe seems to no be draw correctly. it is all black. There is a way to force a redraw or something? – Tyler Sep 11 '22 at 14:04