publicclassProcess : Component { public IntPtr MainWindowHandle { [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] get { if (!haveMainWindow) { EnsureState(State.IsLocal | State.HaveId); mainWindowHandle = ProcessManager.GetMainWindowHandle(processId);
if (mainWindowHandle != (IntPtr)0) { haveMainWindow = true; } else { // We do the following only for the side-effect that it will throw when if the process no longer exists on the system. In Whidbey // we always did this check but have now changed it to just require a ProcessId. In the case where someone has called Refresh() // and the process has exited this call will throw an exception where as the above code would return 0 as the handle. EnsureState(State.HaveProcessInfo); } } return mainWindowHandle; } } }
internalstaticclassProcessManager { publicstatic IntPtr GetMainWindowHandle(int processId) { MainWindowFinder finder = new MainWindowFinder(); return finder.FindMainWindow(processId); } }
internalclassMainWindowFinder { public IntPtr FindMainWindow(int processId) { bestHandle = (IntPtr)0; this.processId = processId; NativeMethods.EnumThreadWindowsCallback callback = new NativeMethods.EnumThreadWindowsCallback(this.EnumWindowsCallback); NativeMethods.EnumWindows(callback, IntPtr.Zero);
GC.KeepAlive(callback); return bestHandle; } boolEnumWindowsCallback(IntPtr handle, IntPtr extraParameter) { int processId; NativeMethods.GetWindowThreadProcessId(new HandleRef(this, handle), out processId); if (processId == this.processId) { if (IsMainWindow(handle)) { bestHandle = handle; returnfalse; } } returntrue; } boolIsMainWindow(IntPtr handle) { if (NativeMethods.GetWindow(new HandleRef(this, handle), NativeMethods.GW_OWNER) != (IntPtr)0 || !NativeMethods.IsWindowVisible(new HandleRef(this, handle))) returnfalse; // [....]: should we use no window title to mean not a main window? (task man does) /* int length = NativeMethods.GetWindowTextLength(handle) * 2; StringBuilder builder = new StringBuilder(length); if (NativeMethods.GetWindowText(handle, builder, builder.Capacity) == 0) return false; if (builder.ToString() == string.Empty) return false; */