/// <summary>Part of PopulateFromWindows only</summary> private bool EnumWindowsIntoProgramsList(IntPtr hWnd, int lParam) { if (Windows.IsWindowVisible(hWnd)) // Store the window only if the window is visible { string name = GetWindowText(hWnd); if (string.IsNullOrEmpty(name)) { return(true); // we get a load of empty window names - usually followed by another for same app with title - don't really want multiple per app anyway } uint processId; Windows.GetWindowThreadProcessId(hWnd, out processId); if (processId == Process.GetCurrentProcess().Id) // this window is ours! { return(true); } string path = null; int length = 1024; StringBuilder pathBuilder = new StringBuilder(length); // requires Vista or later: (we no longer have the fall back that was in SAW6) IntPtr processHandle = Windows.OpenProcess(Windows.ProcessAccessFlags.QueryLimitedInformation, false, (int)processId); if (!processHandle.IsZero()) // will fail for a few (eg System process is protected), but they're not going to be of any interest { if (Windows.QueryFullProcessImageName(processHandle, 0, pathBuilder, ref length)) { path = pathBuilder.ToString(); } Windows.CloseHandle(processHandle); } Windows.RECT bounds; Windows.GetWindowRect(hWnd, out bounds); if (!string.IsNullOrEmpty(path)) { Programs.Add(new Program() { Name = name, Path = path, Bounds = bounds }); } else { Debug.WriteLine($"Could not find path for window: {name}\r\n"); } } return(true); }