Подтвердить что ты не робот

.NET(С#): Получение дочерних окон, когда у вас есть только дескриптор процесса или PID?

Вид проблемы конкретного случая:

  • Я начинаю процесс с System.Diagnostics.Process.Start(..)
  • Процесс открывает всплывающий экран - этот экран заставки становится основным окном.
  • Экран заставки закрывается, и отображается "реальный" интерфейс. Главное окно (заставка) теперь недействительно.
  • У меня все еще есть объект Process, и я могу запросить его дескриптор, модуль и т.д. Но главный дескриптор окна теперь недействителен.

Мне нужно получить интерфейс UI процесса (или UI-дескриптор) в этот момент. Предположим, что я не могу изменить поведение процесса, чтобы сделать это легче (или saner).

Я посмотрел в Интернете, но я признаю, что не смотрел больше часа. Казалось, что это должно быть несколько тривиально: - (

4b9b3361

Ответ 1

Если вы не против использования Windows API, вы можете использовать EnumWindowsProc и проверить каждую ручку, которая появляется используя GetWindowThreadProcessId (чтобы увидеть это в вашем процессе), а затем, возможно, IsWindowVisible, GetWindowCaption и GetWindowTextLength, чтобы определить, какие hWnd в вашем процессе - тот, который вы хотите.

Хотя, если вы не использовали эти функции до того, как этот подход станет подходящей болью, так, надеюсь, есть более простой способ.

Ответ 2

@ageektrapped находится на правильном пути, однако FindWindow не будет искать дочерние окна.

Для этого вам нужно будет использовать FindWindowEx

Ответ 3

Спасибо за ваши ответы. Благодаря вам здесь я выяснил, как узнать, находится ли главное окно процесса или нет:

N.B: конечно, для этого нужны System.Diagnostic и System.Runtime.Interrop

public bool IsWindowActive(Int32 PID)
{
  return IsWindowActive(Process.GetProcessById(PID));
}

[DllImport("user32.dll")]
private static extern
IntPtr GetForegroundWindow();

public bool IsWindowActive(Process proc)
{
  proc.Refresh();
  return proc.MainWindowHandle.Equals(GetForegroundWindow());
}

Ответ 4

Вы можете обнаружить, что если вы вызываете .Refresh(), вы получаете новое окно верхнего уровня.

Ответ 5

Если вы знаете заголовок окна, вы можете использовать вызов Win32, FindWindow, через P/Invoke.

Вы можете найти подпись здесь на pinvoke.net

Ответ 6

Из того, что я понимаю <свойство MainWindowHandle запускаемого процесса, недействительно. В этом случае вы можете использовать FindWindow функцию (из Win32 SDK), которая возвращает требуемый дескриптор окна. Все, что вам нужно - это имя главного окна целевого приложения. Вы можете получить его с помощью Spy ++ или Winspector. Вы также должны убедиться, что у вас есть правильное окно, проверяя этот идентификатор процесса окна с помощью GetWindowThreadProcessId.

Наконец, я должен сказать, что я не специалист по Win32, и может быть лучшее решение для вашего дела.

Ответ 7

Использовать Process.GetProcessById(proc.Id); где proc был вашим заставкой. Работает для меня.

Теперь, как вы попадаете в свойства основного окна в System.Windows.Forms, чтобы дать ему фокус без использования win32? В конце концов .net должен быть универсальным решением - не так ли?

Ответ 8

Где-то в коде создается "реальное" главное окно. Вы можете просто сохранить дескриптор окна в это время, а затем после закрытия заставки вы можете установить Application.MainWindow в реальное окно.

Ответ 9

Свойство MainWindowHandle кэшируется после его первого доступа, поэтому вы не видите его изменения даже после того, как дескриптор становится недействительным. Информация GregUzelac верна. Вызов Proces.Refresh заставит следующий вызов Process.MainWindowHandle повторить логику, чтобы найти новый дескриптор главного окна. Майкл также работает, потому что новый процесс не имеет кэшированной версии MainWindowHandle.