Листинг 7.25
public static Window[] EnumerateTopWindows() {
ArrayList windowList = new ArrayList();
IntPtr hWnd = IntPtr.Zero;
Window window = null;
// Получим первое окно
hWnd = GetActiveWindow();
hWnd = GetWindow(hWnd, GW_HWNDFIRST);
while(hWnd != IntPtr.Zero) {
if (IsWindow(hWnd) && IsWindowVisible(hWnd)) {
IntPtr parentWin = GetParent(hWnd);
if ((parentWin == IntPtr.Zero)) {
int length = GetWindowTextLength(hWnd);
if (length > 0) {
string s = new string('\0', length + 1);
GetWindowText(hWnd, s.length + 1);
s = s.Substring(0, s.IndexOf('\0'));
if (s != "Tray" && s != "Start" && s != "Task Manager") {
window = new Window();
window.Handle = hWnd;
window.Text = s;
windowList.Add(window);
}
}
}
}
hWnd = GetWindow(hWnd, GW_HWNDNEXT);
}
return (Window[])windowList.ToArray(typeof(Window));
}
В этом методе вызываются функции Windows API, с помощью которых можно получить список всех открытых окон. Все обнаруженные окна добавляются в список, если они удовлетворяют некоторым условиям. Добавляемые окна не должны иметь родительских окон, они должны быть видимыми и иметь заголовок. При этом сам Диспетчер задач не должен попасть в этот список. Все остальные окна записываются в массив.
Активация и закрытие приложения
Для активации запущенного приложения вызывается функция Windows API SetForegroundWindow, которая использует дескриптор окна. Для закрытия приложения используется функция SendMessageс соответствующим сообщением закрытия WM_CLOSE. Для закрытия сразу всех окон можно использовать функцию Windows API SHCloseApps, которая закрывает все запущенные программы, кроме самого Диспетчера задач. Код, выполняющий эти действия, приведен в листинге 7.26.
Листинг 7.26
public static void ActivateWindow(IntPtr hWnd) {
// Активируем приложение
SetForegroundWindow(hWnd);
}
public static void CloseWindow(IntPtr hWnd) {
// Закрываем приложение
SendMessage(hWnd, WM_CLOSE, 0, 0);
}
public static void CloseApps() {
// Закрываем все приложения
SHCloseApps(int.MaxValue);
}
Для отображения списка процессов используется функция, код которой приведен в листинге 7.27.
Листинг 7.27
private void fillProcessList() {
Cursor.Current = Cursors.WaitCursor;
// Получаем список запущенных процессов
processes = Process.GetProcesses();
// Заполняем ListView
ListViewItem lvi;
listView.BeginUpdate();
listView.Items.Clear();
foreach (Process p in processes) {
lvi = new ListViewItem(p.ProcessName);
//lvi.SubItems.Add("ID");
listView.Items.Add(lvi);
}
listView.EndUpdate();
if (listView.Items.Count > 0) {
listView.Items[0].Selected = true;
listView.Items[0].Focused = true;
}
Cursor.Current = Cursors.Default;
}
Список активных процессов извлекается при помощи класса Process. Основой класса является метод GetProcesses, приведенный в листинге 7.28.
Листинг 7.28
public static Process[] GetProcesses() {
ArrayList procList = new ArrayList();
IntPtr handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if ((int)handle > 0) {
try {
PROCESSENTRY32 peCurrent;
PROCESSENTRY32 pe32 = new PROCESSENTRY32();
byte[] peBytes = pe32.ToByteArray();
int retval = Process32First(handle, peBytes);
while(retval == 1) {
peCurrent = new PROCESSENTRY32(peBytes);
Process proc =
new Process(new IntPtr((int)peCurrent.PID), peCurrent.Name,
(int)peCurrent.ThreadCount, (int)peCurrent.BaseAddress);
procList.Add(proc);
retval = Process32Next(handle, peBytes);
}
} catch(Exception ex) {
throw new Exception("Exception: " + ex.Message);
}
CloseToolhelp32Snapshot(handle);
return (Process[])procList.ToArray(typeof(Process));
} else {
throw new Exception("Unable to get processes!");
}
}
С помощью данного метода можно узнать детальную информацию о каждом процессе.
Чтобы закрыть процесс, используется метод Kill, код которого приведен в листинге 7.29.
Листинг 7.29
public void Kill() {
IntPtr hProcess;
hProcess = OpenProcess(PROCESS_TERMINATE, false, (int) processId);
if (hProcess != (IntPtr) INVALID_HANDLE_VALUE) {
bool bRet;
bRet = TerminateProcess(hProcess, 0);
CloseHandle(hProcess);
}
}
Данный метод также использует вызовы функций Windows API. Функция OpenProcessполучает дескриптор процесса, который затем передается функции TerminateProcessдля уничтожения процесса.
Код, отвечающий за внешний вид элемента управления ListView, полностью идентичен коду из предыдущего примера, поэтому его можно просто скопировать и не рассматривать отдельно. Теперь с помощью Диспетчера задач пользователь сможет узнать список запущенных программ и процессов и даже управлять ими.
Читать дальше