web-dev-qa-db-ja.com

.NET(C#):プロセスハンドルまたはPIDしかない場合に子ウィンドウを取得しますか?

特別な場合の問題の種類:

  • System.Diagnostics.Process.Start(..)でプロセスを開始します
  • プロセスはスプラッシュ画面を開きます-このスプラッシュ画面がメインウィンドウになります。
  • スプラッシュ画面が閉じ、「実際の」UIが表示されます。メインウィンドウ(スプラッシュ画面)が無効になりました。
  • まだProcessオブジェクトがあり、そのハンドルやモジュールなどをクエリできます。しかし、メインウィンドウのハンドルが無効になりました。

この時点で、プロセスのUI(またはUIハンドル)を取得する必要があります。プロセスの動作を変更して、これを簡単に(または賢く)することはできないと仮定します。

私はオンラインで見回しましたが、1時間以上探していなかったことを認めます。やや些細なことのようです:-(

22
shea241

Windows APIを使用してもかまわない場合は、 EnumWindowsProc を使用して、使用して表示される各ハンドルを確認できます。 GetWindowThreadProcessId (プロセス内にあることを確認するため)、そしておそらくIsWindowVisibleGetWindowCaptionGetWindowTextLengthを使用して、プロセス内のどのhWndが必要かを判断します。

ただし、その前にこれらの関数を使用したことがない場合、そのアプローチは非常に苦痛になります。したがって、もっと簡単な方法があることを願っています。

11
MB.

@ageektrappedは正しい方向に進んでいますが、FindWindowは子ウィンドウを検索しません。

そのためには、 FindWindowEx を使用する必要があります

7
Ash

ご回答ありがとうございます。ここでのおかげで、プロセスのメインウィンドウが前面にあるかどうかを知る方法がわかりました。

注:もちろん、これには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());
}
3
Giova

.Refresh()を呼び出すと、新しいトップレベルウィンドウが表示される場合があります。

2
GregUzelac

Process.GetProcessById(proc.Id);を使用します。ここで、procはスプラッシュ画面でした。私のために働きます。

では、どのようにしてSystem.Windows.Formsのメインウィンドウのプロパティにアクセスして、win32を使用せずにフォーカスを与えるのでしょうか。結局のところ、.netはワンストップソリューションであるはずです-そうではありませんか?

1

ウィンドウのタイトルがわかっている場合は、P/Invokeを介してWin32呼び出しのFindWindowを使用できます。

署名はpinvoke.netで見つけることができます ここ

1
ageektrapped

私が理解していることから、開始しているプロセスのMainWindowHandleプロパティは無効です。その場合は、必要なウィンドウハンドルを返す FindWindow 関数(Win32 SDKから)を使用できます。必要なのは、ターゲットアプリケーションのメインウィンドウのクラス名だけです。 Spy ++または Winspector を使用して取得できます。また、 GetWindowThreadProcessId を使用してウィンドウのプロセスIDを確認し、正しいウィンドウがあることを確認する必要があります。

最後に、私はWin32の専門家ではないので、あなたのケースにはもっと良い解決策があるかもしれません。

1
blackwing

MainWindowHandleプロパティは、最初にアクセスされた後にキャッシュされるため、ハンドルが無効になっても変更されません。 GregUzelacの情報は正しいです。 Proces.Refreshを呼び出すと、次のProcess.MainWindowHandleの呼び出しでロジックが再実行され、新しいメインウィンドウハンドルが検索されます。新しいプロセスにはキャッシュされたバージョンのMainWindowHandleがないため、Michaelのロジックも機能します。

0
Matt Ellis

コードのどこかに、「実際の」メインウィンドウが作成されます。その時点でウィンドウハンドルを保存するだけで、スプラッシュ画面が閉じた後、Application.MainWindowを実際のウィンドウに設定できます。

0
Marcus Erickson