/// <summary> /// Initializes a new instance of the <see cref="Window"/> class. /// Initializes a new Window representation /// </summary> /// <param name="hwnd">the handle to the window we are representing</param> internal Window(IntPtr hwnd) { // TODO: Add verification as to whether the window handle is valid this.hwnd = hwnd; processInfo = CreateWindowProcessInstance(hwnd); desktopInfo = Main.VirtualDesktopHelperInstance.GetWindowDesktop(hwnd); }
/// <summary> /// Gets an instance of <see cref="WindowProcess"/> form process cache or creates a new one. A new one will be added to the cache. /// </summary> /// <param name="hWindow">The handle to the window</param> /// <returns>A new Instance of type <see cref="WindowProcess"/></returns> private static WindowProcess CreateWindowProcessInstance(IntPtr hWindow) { lock (_handlesToProcessCache) { if (_handlesToProcessCache.Count > 7000) { Debug.Print("Clearing Process Cache because it's size is " + _handlesToProcessCache.Count); _handlesToProcessCache.Clear(); } // Add window's process to cache if missing if (!_handlesToProcessCache.ContainsKey(hWindow)) { // Get process ID and name var processId = WindowProcess.GetProcessIDFromWindowHandle(hWindow); var threadId = WindowProcess.GetThreadIDFromWindowHandle(hWindow); var processName = WindowProcess.GetProcessNameFromProcessID(processId); if (processName.Length != 0) { _handlesToProcessCache.Add(hWindow, new WindowProcess(processId, threadId, processName)); } else { // For the dwm process we can not receive the name. This is no problem because the window isn't part of result list. Log.Debug($"Invalid process {processId} ({processName}) for window handle {hWindow}.", typeof(Window)); _handlesToProcessCache.Add(hWindow, new WindowProcess(0, 0, string.Empty)); } } // Correct the process data if the window belongs to a uwp app hosted by 'ApplicationFrameHost.exe' // (This only works if the window isn't minimized. For minimized windows the required child window isn't assigned.) if (_handlesToProcessCache[hWindow].Name.ToUpperInvariant() == "APPLICATIONFRAMEHOST.EXE") { new Task(() => { NativeMethods.CallBackPtr callbackptr = new NativeMethods.CallBackPtr((IntPtr hwnd, IntPtr lParam) => { // Every uwp app main window has at least three child windows. Only the one we are interested in has a class starting with "Windows.UI.Core." and is assigned to the real app process. // (The other ones have a class name that begins with the string "ApplicationFrame".) if (GetWindowClassName(hwnd).StartsWith("Windows.UI.Core.", StringComparison.OrdinalIgnoreCase)) { var childProcessId = WindowProcess.GetProcessIDFromWindowHandle(hwnd); var childThreadId = WindowProcess.GetThreadIDFromWindowHandle(hwnd); var childProcessName = WindowProcess.GetProcessNameFromProcessID(childProcessId); // Update process info in cache _handlesToProcessCache[hWindow].UpdateProcessInfo(childProcessId, childThreadId, childProcessName); return(false); } else { return(true); } }); _ = NativeMethods.EnumChildWindows(hWindow, callbackptr, 0); }).Start(); } return(_handlesToProcessCache[hWindow]); } }
/// <summary> /// Initializes a new instance of the <see cref="Window"/> class. /// Initializes a new Window representation /// </summary> /// <param name="hwnd">the handle to the window we are representing</param> public Window(IntPtr hwnd) { // TODO: Add verification as to whether the window handle is valid this.hwnd = hwnd; processInfo = CreateWindowProcessInstance(hwnd); }