diff --git a/wv2util/HostAppList.cs b/wv2util/HostAppList.cs index 3469922..8da56a5 100644 --- a/wv2util/HostAppList.cs +++ b/wv2util/HostAppList.cs @@ -50,7 +50,8 @@ public HostAppEntry( string runtimePath, // Path to the WebView2 client DLL string userDataPath, // Path to the user data folder string[] interestingLoadedDllPaths, // a list of full paths of DLLs that are related to WebView2 in some way - int browserProcessPid) // PID of the browser process + int browserProcessPid, + IntPtr[] hwnds) // PID of the browser process { Kind = kind; ExecutablePath = exePath == null ? "Unknown" : exePath; @@ -61,6 +62,7 @@ public HostAppEntry( UserDataPath = userDataPath == null ? "Unknown" : userDataPath; InterestingLoadedDllPaths = interestingLoadedDllPaths; BrowserProcessPID = browserProcessPid; + Hwnds = hwnds == null ? new IntPtr[0] : hwnds; } public string DisplayLabel @@ -98,6 +100,7 @@ public string DisplayLabel public string UserDataPath { get; private set; } public string[] InterestingLoadedDllPaths { get; private set; } public int BrowserProcessPID { get; private set; } = 0; + public IntPtr[] Hwnds { get; private set; } public string IntegrityLevel { get @@ -401,7 +404,8 @@ private static IEnumerable AddRuntimeProcessInfoToHostAppEntriesBy msedgewebview2Process.MainModule.FileName, userDataPathAndProcessType.Item1, null, - 0); + 0, + null); } if (parentProcess != null) @@ -426,7 +430,8 @@ private static IEnumerable AddRuntimeProcessInfoToHostAppEntriesBy hostAppEntry.Runtime.ExePath, userDataFolder, hostAppEntry.InterestingLoadedDllPaths, - msedgewebview2Process.Id); + msedgewebview2Process.Id, + hostAppEntry.Hwnds); newHostAppEntry.Children.AddRange(hostAppEntry.Children); newHostAppEntry.Children.Add(currentProcessEntry); @@ -470,7 +475,8 @@ private static IEnumerable GetHostAppEntriesFromMachineByProcessMo ClientDllPathToRuntimePath(interestingDllPaths.Item1), null, interestingDllPaths.Item3, - 0)); + 0, + null)); } } return results; @@ -531,7 +537,8 @@ public static IEnumerable GetHostAppEntriesFromMachineByPipeEnumer ClientDllPathToRuntimePath(clientDllPath), null, interestingDllPaths, - 0)); + 0, + null)); } } }; @@ -566,6 +573,7 @@ private static IEnumerable AddRuntimeProcessInfoToHostAppEntriesBy if (hostAppEntry.BrowserProcessPID == 0) { HashSet runtimePids = new HashSet(); + Dictionary> runtimePidToHwndMap = new Dictionary>(); // And find corresponding top level windows for just this PID. if (pidToTopLevelHwndsMap.TryGetValue(hostAppEntry.PID, out var topLevelHwnds)) @@ -584,9 +592,17 @@ private static IEnumerable AddRuntimeProcessInfoToHostAppEntriesBy { childHwnd = PInvoke.User32.GetProp(hostAppLeafHwnd, "CrossProcessChildHWND"); } + if (childHwnd != IntPtr.Zero) { - runtimePids.Add(HwndUtil.GetWindowProcessId(childHwnd)); + int runtimePid = HwndUtil.GetWindowProcessId(childHwnd); + runtimePids.Add(runtimePid); + + if (!runtimePidToHwndMap.TryGetValue(runtimePid, out HashSet runtimeHwnds)) + { + runtimePidToHwndMap[runtimePid] = runtimeHwnds = new HashSet(); + } + runtimeHwnds.Add(childHwnd); } } } @@ -602,6 +618,8 @@ private static IEnumerable AddRuntimeProcessInfoToHostAppEntriesBy var userDataPathAndProcessType = GetUserDataPathAndProcessTypeFromProcessViaCommandLine(runtimeProcess); userDataFolder = userDataPathAndProcessType.Item1; + runtimePidToHwndMap.TryGetValue(runtimePid, out HashSet runtimeHwnds); + var runtimeEntry = new HostAppEntry( "host", hostAppEntry.ExecutablePath, @@ -611,7 +629,8 @@ private static IEnumerable AddRuntimeProcessInfoToHostAppEntriesBy hostAppEntry.Runtime.ExePath, userDataFolder, hostAppEntry.InterestingLoadedDllPaths, - runtimePid); + runtimePid, + runtimeHwnds?.ToArray()); runtimeEntry.Children.AddRange(hostAppEntry.Children); runtimeEntry.Children.Add(new HostAppEntry( userDataPathAndProcessType.Item2, @@ -622,7 +641,8 @@ private static IEnumerable AddRuntimeProcessInfoToHostAppEntriesBy runtimeProcess.MainModule.FileName, userDataFolder, null, - 0)); + 0, + runtimeEntry.Hwnds)); hostAppEntriesWithRuntimePID.Add(runtimeEntry); added = true; } @@ -653,6 +673,7 @@ private static IEnumerable AddRuntimeProcessInfoToHostAppEntriesBy List hostAppEntriesResults = new List(); Dictionary> parentPidToChildPidsMap = new Dictionary>(); var topLevelHwnds = HwndUtil.GetTopLevelHwnds(null, true); + Dictionary> childPidToHwnd = new Dictionary>(); // Then find all child (and child of child of...) windows that have appropriate class name foreach (var topLevelHwnd in topLevelHwnds) @@ -681,6 +702,12 @@ private static IEnumerable AddRuntimeProcessInfoToHostAppEntriesBy } childPids.Add(childPid); } + + if (!childPidToHwnd.TryGetValue(childPid, out HashSet childHwnds)) + { + childPidToHwnd[childPid] = childHwnds = new HashSet(); + } + childHwnds.Add(childHwnd); } } } @@ -702,6 +729,7 @@ private static IEnumerable AddRuntimeProcessInfoToHostAppEntriesBy { var userDataPathAndProcessType = GetUserDataPathAndProcessTypeFromProcessViaCommandLine(runtimeProcess); string userDataFolder = userDataPathAndProcessType.Item1; + childPidToHwnd.TryGetValue(childPid, out HashSet runtimeHwnds); var runtimeEntry = new HostAppEntry( "host", @@ -712,7 +740,8 @@ private static IEnumerable AddRuntimeProcessInfoToHostAppEntriesBy hostAppEntry.Runtime.ExePath, userDataFolder, hostAppEntry.InterestingLoadedDllPaths, - childPid); + childPid, + runtimeHwnds?.ToArray()); runtimeEntry.Children.Add(new HostAppEntry( userDataPathAndProcessType.Item2, runtimeProcess.MainModule.FileName, @@ -722,7 +751,8 @@ private static IEnumerable AddRuntimeProcessInfoToHostAppEntriesBy runtimeProcess.MainModule.FileName, userDataFolder, null, - 0)); + 0, + runtimeEntry.Hwnds)); runtimeEntry.Children.AddRange(hostAppEntry.Children); hostAppEntriesResults.Add(runtimeEntry); added = true; diff --git a/wv2util/HwndUtil.cs b/wv2util/HwndUtil.cs index d22d497..b935a95 100644 --- a/wv2util/HwndUtil.cs +++ b/wv2util/HwndUtil.cs @@ -175,5 +175,23 @@ public static string GetClassName(IntPtr hwnd) } return className; } + + public static System.Windows.Rect ToSystemWindowsRect(this PInvoke.RECT rectAsPInvokeRect) + { + System.Windows.Rect rectAsSystemWindowsRect = new System.Windows.Rect(); + rectAsSystemWindowsRect.X = rectAsPInvokeRect.left; + rectAsSystemWindowsRect.Y = rectAsPInvokeRect.top; + rectAsSystemWindowsRect.Width = rectAsPInvokeRect.right - rectAsPInvokeRect.left; + rectAsSystemWindowsRect.Height = rectAsPInvokeRect.bottom - rectAsPInvokeRect.top; + return rectAsSystemWindowsRect; + } + public static System.Windows.Rect GetWindowRect(IntPtr hwnd) + { + if (!PInvoke.User32.GetWindowRect(hwnd, out var rect)) + { + throw new PInvoke.Win32Exception(PInvoke.Kernel32.GetLastError()); + } + return rect.ToSystemWindowsRect(); + } } } diff --git a/wv2util/MainWindow.xaml b/wv2util/MainWindow.xaml index 432f1d1..63e700e 100644 --- a/wv2util/MainWindow.xaml +++ b/wv2util/MainWindow.xaml @@ -65,7 +65,8 @@ - + +