/// <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); }
/// <summary>Iterates all processes in Windows, running the given function. This is based on processes, NOT windows. Some may be hidden/background</summary> public static void IterateRunningProcesses(ProcessFunction procFunction) { Windows.PROCESSENTRY32 pe32 = new Windows.PROCESSENTRY32(); // Take a snapshot of all processes in the system. var hProcessSnap = Windows.CreateToolhelp32Snapshot(Windows.SnapshotFlags.Process, 0); if (hProcessSnap.IsInvalid()) { return; } // Fill in the size of the structure before using it. pe32.dwSize = (uint)Marshal.SizeOf(typeof(Windows.PROCESSENTRY32)); // Walk the snapshot of the processes, and for each process, display information. if (Windows.Process32First(hProcessSnap, ref pe32)) { do { int nLength = 1024; StringBuilder szPath = new StringBuilder(nLength); // requires Vista or later: (we no longer have the fall back that was in SAW6) IntPtr hProcess = Windows.OpenProcess(Windows.ProcessAccessFlags.QueryLimitedInformation, false, (int)pe32.th32ProcessID); if (!hProcess.IsZero()) // will fail for a few (eg System process is protected), but they're not going to be the process we're looking for. { if (Windows.QueryFullProcessImageName(hProcess, 0, szPath, ref nLength)) { if (!procFunction(pe32, szPath.ToString(0, nLength))) { Windows.CloseHandle(hProcessSnap); Windows.CloseHandle(hProcess); return; } } Windows.CloseHandle(hProcess); } } while (Windows.Process32Next(hProcessSnap, ref pe32)); } Windows.CloseHandle(hProcessSnap); }
private bool OpenProgram(Program program) { Windows.PROCESS_INFORMATION processInfo = new Windows.PROCESS_INFORMATION(); Windows.STARTUPINFO startupInfo = new Windows.STARTUPINFO { cb = Marshal.SizeOf(typeof(Windows.STARTUPINFO)), dwFlags = Windows.STARTF_USEPOSITION | Windows.STARTF_USESIZE, dwX = program.Bounds.Left, dwY = program.Bounds.Top, dwXSize = program.Bounds.Width, dwYSize = program.Bounds.Height }; if (!Windows.CreateProcess(program.Path, null, IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, null, ref startupInfo, out processInfo)) { return(false); } //Wait until process has started its main message loop Windows.WaitForInputIdle(processInfo.hProcess, Windows.INFINITE); //Close process and thread handles Windows.CloseHandle(processInfo.hThread); Windows.CloseHandle(processInfo.hProcess); return(true); }