API関数のEnumWindowsを使うことで、全てのウィンドウのハンドル(HWND)を取得する事ができる。 EnumWindowsを呼び出すと、コールバックメソッドが呼び出され、存在する個々のウィンドウのHWNDが渡される。
以下の例では、EnumWindows()でウィンドウを列挙し、コールバックメソッド内ではIsWindowVisible()を使って可視ウィンドウかどうかを調べている。 また、個々の可視ウィンドウについて、GetWindowText()を使ってウィンドウのキャプションを、GetWindowThreadProcessId()とProcess.GetProcessByIdを使ってプロセス情報を取得・表示している。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
class Sample {
[DllImport("user32")]
private static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, IntPtr lParam);
// EnumWindowsから呼び出されるコールバック関数WNDENUMPROCのデリゲート
private delegate bool WNDENUMPROC(IntPtr hWnd, IntPtr lParam);
[DllImport("user32")]
private static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32")]
private static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
static void Main()
{
// ウィンドウの列挙を開始
EnumWindows(EnumerateWindow, IntPtr.Zero);
}
// ウィンドウを列挙するためのコールバックメソッド
private static bool EnumerateWindow(IntPtr hWnd, IntPtr lParam)
{
// ウィンドウが可視かどうか調べる
if (IsWindowVisible(hWnd))
// 可視の場合
PrintCaptionAndProcess(hWnd);
// ウィンドウの列挙を継続するにはtrueを返す必要がある
return true;
}
// ウィンドウのキャプションとプロセス名を表示する
private static void PrintCaptionAndProcess(IntPtr hWnd)
{
// ウィンドウのキャプションを取得・表示
StringBuilder caption = new StringBuilder(0x1000);
GetWindowText(hWnd, caption, caption.Capacity);
Console.Write("'{0}' ", caption);
// ウィンドウハンドルからプロセスIDを取得
int processId;
GetWindowThreadProcessId(hWnd, out processId);
// プロセスIDからProcessクラスのインスタンスを取得
Process p = Process.GetProcessById(processId);
// プロセス名を表示
Console.WriteLine("({0})", p.ProcessName);
}
}
Imports System
Imports System.Diagnostics
Imports System.Runtime.InteropServices
Imports System.Text
Class Sample
<DllImport("user32")> _
Private Shared Function EnumWindows(ByVal lpEnumFunc As WNDENUMPROC, ByVal lParam As IntPtr) As Boolean
End Function
' EnumWindowsから呼び出されるコールバック関数WNDENUMPROCのデリゲート
Private Delegate Function WNDENUMPROC(ByVal hWnd As IntPtr, ByVal lParam As IntPtr) As Boolean
<DllImport("user32")> _
Private Shared Function IsWindowVisible(ByVal hWnd As IntPtr) As Boolean
End Function
<DllImport("user32", CharSet := CharSet.Auto)> _
Private Shared Function GetWindowText(ByVal hWnd As IntPtr, ByVal lpString As StringBuilder, ByVal nMaxCount As Integer) As Integer
End Function
<DllImport("user32")> _
Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, <Out> ByRef lpdwProcessId As Integer) As Integer
End Function
Public Shared Sub Main()
' ウィンドウの列挙を開始
EnumWindows(AddressOf EnumerateWindow, IntPtr.Zero)
End Sub
' ウィンドウを列挙するためのコールバックメソッド
Private Shared Function EnumerateWindow(ByVal hWnd As IntPtr, ByVal lParam As IntPtr) As Boolean
' ウィンドウが可視かどうか調べる
If IsWindowVisible(hWnd) Then
' 可視の場合
PrintCaptionAndProcess(hWnd)
End If
' ウィンドウの列挙を継続するにはTrueを返す必要がある
Return True
End Function
' ウィンドウのキャプションとプロセス名を表示する
Private Shared Sub PrintCaptionAndProcess(ByVal hWnd As IntPtr)
' ウィンドウのキャプションを取得・表示
Dim caption As New StringBuilder(&h1000)
GetWindowText(hWnd, caption, caption.Capacity)
Console.Write("'{0}' ", caption)
' ウィンドウハンドルからプロセスIDを取得
Dim processId As Integer
GetWindowThreadProcessId(hWnd, processId)
' プロセスIDからProcessクラスのインスタンスを取得
Dim p As Process = Process.GetProcessById(processId)
' プロセス名を表示
Console.WriteLine("({0})", p.ProcessName)
End Sub
End Class
出力例
'Windows タスク マネージャ' (taskmgr) 'スタート' (explorer) '' (explorer) 'C:\Windows\system32\cmd.exe - test.exe ' (cmd) 'test.vb - メモ帳' (notepad) 'test.cs - メモ帳' (notepad) 'D:\' (explorer) 'Program Manager' (explorer)
なお、可視でないウィンドウも列挙するには、IsWindowVisible()の部分を削除すればよい。