|
■No86310 (tacos さん) に返信 > 該当アプリを逆コンパイルしてみて分からないなりに眺めてみたところ、 > 確かにウィンドウらしきモノが確認出来たので、 > 逆コンパイルが上手く行っていないだけなのか疑問でした。
もしかして、対象のアプリは .NET Framework 向けのものでしょうか。
>> WM_QUERYENDSESSION あるいは WM_ENDSESSION を受信するための >> 不可視ウィンドウが存在しているのではないでしょうか。
.NET のマネージアプリの場合、それらをカプセル化した [Microsoft.Win32.SystemEvents] クラスの SessionEnding / SessionEnded イベントが 使われている可能性があります。
この場合、『.NET-BroadcastEventWindow.』で始まる名前のクラス名を持った 不可視ウィンドウが用意され、そこでメッセージが受信されるようになっています。 コンソールアプリの場合は、SetConsoleCtrlHandler API 経由ですけれども。
Windows のシャットダウン時やログオフ時に、稀に 「プログラムの終了 - .NET-BroadcastEventWindow…」 と表示されることがありますが、それの正体がコレのようです。 https://support.microsoft.com/ja-jp/help/841073
ちなみに VB6 アプリの場合は "ThunderRT6Main" クラスというウィンドウが使われていました。 こちらは不可視ではなく、サイズ 0 の可視ウィンドウでした。 (開発環境で実行した場合は "ThunderMain" というクラス名です)
参考までに、先のサンプルでクラス名も拾うように改修してみました。 また、今回は対象アプリのプロセス ID も事前に分かっているようなので、 呼び出し時に検索対象のプロセスID を指定できるようにしています。
# 全部のプロセスを列挙する場合 [Win32.Wankuma86294]::Execute() | Format-Table
# 列挙対象の Process.Id を指定する場合 [Win32.Wankuma86294]::Execute($ps.Id) | Format-Table
$TypeDef = @" using System; using System.Text; using System.Collections.Generic; using System.Runtime.InteropServices; namespace Win32 { public class WinInfo { public int ProcessId { get; set; } public IntPtr Handle { get; set; } public bool Visible { get; set; } public string Class { get; set; } public string Title { get; set; } } public class Wankuma86294 { public static List<WinInfo> Execute() { return Execute(0); } public static List<WinInfo> Execute(int targetProcessId) { var proc = new Wankuma86294() { TargetProcessId = targetProcessId }; EnumWindows(proc.EnumFunc, IntPtr.Zero); return proc.WinList; } private Wankuma86294() { } private int TargetProcessId; private delegate bool WNDENUMPROC(IntPtr hwnd, IntPtr lParam); private List<WinInfo> WinList = new List<WinInfo>(); [DllImport("User32.dll")][return: MarshalAs(UnmanagedType.Bool)] private static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, IntPtr lParam); [DllImport("User32.dll")][return: MarshalAs(UnmanagedType.Bool)] private static extern bool IsWindowVisible(IntPtr hWnd); [DllImport("User32.dll")] private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); private bool EnumFunc(IntPtr hWnd, IntPtr lParam) { int processId = 0; if (hWnd != IntPtr.Zero) { GetWindowThreadProcessId(hWnd, out processId); } if (TargetProcessId == 0 || processId == TargetProcessId) { var bufText = new StringBuilder(512); int lenText = GetWindowText((IntPtr)hWnd, bufText , 512); var bufClass = new StringBuilder(512); int lenClass = GetClassName((IntPtr)hWnd, bufClass, 512); WinList.Add(new WinInfo() { ProcessId = processId, Handle = hWnd, Visible = IsWindowVisible(hWnd), Class = bufClass.ToString(0, lenClass), Title = bufText.ToString(0, lenText), }); } return true; } } } "@ Add-Type -TypeDefinition $TypeDef -Language CSharpVersion3
|