Листинг 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
, полностью идентичен коду из предыдущего примера, поэтому его можно просто скопировать и не рассматривать отдельно. Теперь с помощью Диспетчера задач пользователь сможет узнать список запущенных программ и процессов и даже управлять ими.
Читать дальше