« Поставить закладку » « Сделать стартовой »

« Форумы » « Блоги » « Статьи » « Новости » « Файлы » « Realcoding IRC » « Site map » « Поиск »


Главная Главная
Анонсы Анонсы
Форумы Форумы
Каталог Каталог
Поиск Поиск
Опросы Опросы
Книжный магазин Книжный магазин
Реклама на сайте
Публикации Публикации
Партнеры Партнеры
Карта Карта сайта
Рассылки Рассылки
RSS экспорт
Настройки Настройки
О нас пишут О нас пишут
Контакты Контакты
Гостевая книга Гостевая книга


ПнВтСрЧтПтСбВс
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
    Популярное
Изменение последовательности ввода информации в поля формы

Функция AccessResource

Работа с буфером обмена в Delphi

С++ Builder: как ускорить компиляцию (часть 2)

Описание функций C (Си) / C++ - itoa

MASM32 и DELPHI - битва за размер

Комплексные числа в .NET

Описание функций C (Си) / C++ - sscanf

Передача данных в Microsoft Excel с помощью OLE

Программирование метаклассов на Python




    Архив файлов



    Сообщества

    Документация

    Кто на сайте
Вы не зарегистрированы.
Имя:

Пароль:

Запомнить

Регистрация позволит Вам пользоваться дополнительными сервисами.
Сейчас на сайте:
Гостей: 88
Пользователей: 0

Статьи:: C/С++ :: C/C++: Пишем процесс-менеджер



отправить ссылку другу версия для печати  Обсудить на форуме

C/C++: Пишем процесс-менеджер



Николай "G" Андреев

(gorlum@real.xakep.ru)

Процесс... Как много в этом звуке... Я еще помню времена, когда у меня стоял Windows 95, и на компьютере творился сплошной хаос. Стоило зависнуть одной программе, как сразу вылетали все форточки. Стандартный таскменеджер не просто не справлялся с работой, он сам порой являлся причиной сбоя. Тогда-то я и задумался о том, как бы получить над системой больше власти. Облазив кучу ресурсов в инете и не найдя ничего путного, я понял, что надо писать свой менеджер, имеющий больше возможностей, чем обычный, и самое главное – стабильно работающий. И я его написал, причем пользуюсь им по сей день. А вот как он был создан - этим я поделюсь с тобой в этой статье.

Мы научимся не только перечислять и выводить на экран все запущенные на данный момент процессы, но и по-разному манипулировать ими. Научимся "завершать задачу", менять приоритет процесса, его свойства и получать о нем любую информацию. Все эти навыки могут очень пригодиться при написании программ под windows.

Кодим

Сразу к делу. Сначала создадим форму и кинем на нее объект ListBox и объект Button. В листбокс запишем все текущие процессы, а кнопочка Button даст нам возможность убивать эти процессы. В коде мы создадим соответствующую оконную процедуру для обработки сообщений (например, сообщения о нажатии клавиши). Как это сделать, я не буду здесь описывать, просто загляни в майский выпуск твоего любимого журнала :).

Способов перечислить процессы много. В Windows NT 4.0, например, доступен только один - воспользоваться функцией EnumProcesses из набора Process Status Application Programming Interface (в простонародье PSAPI). Он также доступен и в старших НТях, а в 9x - нет, так что, хотя этот способ и очень удобен, он, увы, отпадает. Есть способ порыться в реестре, в скрытом разделе HKEY_PERFOMANCE_DATA, но он также отпадает из-за сложности реализации. На наше счастье, яйцеголовые из Microsoft придумали универсальный способ и дали ему название ToolHelp API.

Для использования этого способа подключим заголовочный файл tlhelp32.h к нашей программе. Он находится в стандартной поставке Platform SDK (прилагающейся к студии), но если вдруг компилятор его не найдет, посмотри на нашем диске - я его приложил к программе. Для перечисления процессов мы будем использовать три функции:

CreateToolhelp32Snapshot - для получения "снимка" процессов;

Process32First - для получения первого процесса из снимка;

Process32Next - для получения оставшихся процессов.

Получаем процессы

При перечислении мы должны добавить имя процесса в листбокс на форме и идентификатор этого процесса в массив. Это необходимо для того, чтобы, связав значение в массиве со значением в списке, мы могли манипулировать процессом. Например, выделить определенный процесс в списке и нажать на кнопку "завершить", что, по идее, должно привести к завершению выбранного процесса.

Итак, определим переменные: массив типа DWORD из, допустим, 1024 элементов и переменную типа PROCESSENTRY32, в которую у нас будут заноситься значения свойств и характеристик процесса.

Структура PROCESSENTRY32

typedef struct tagPROCESSENTRY32 {

DWORD dwSize;

DWORD cntUsage;

DWORD th32ProcessID;

ULONG_PTR th32DefaultHeapID;

DWORD th32ModuleID;

DWORD cntThreads;

DWORD th32ParentProcessID;

LONG pcPriClassBase;

DWORD dwFlags;

TCHAR szExeFile[MAX_PATH];

} PROCESSENTRY32;

typedef PROCESSENTRY32 *PPROCESSENTRY32;

Создадим снимок процесса и начнем его исследовать. Воспользуемся для этого функцией CreateToolhelp32Snapshot, о которой я уже говорил раньше. В первом параметре мы передадим ей константу TH32CS_SNAPPROCESS, говорящую о нашем желании получить снимок именно процессов, а не модулей, нитей или чего-нибудь другого в этом роде. Второй параметр нас совершенно не интересует, поэтому передаем NULL. Функция вернет значение типа HANDLE, которое мы сохраним в какую-нибудь переменную и будем впоследствии его использовать.

Получив снимок, можно начать перечислять процессы при помощи функции Process32First, в первом параметре которой мы передадим полученный HANDLE снимка, а во втором ссылку на переменную типа PROCESSENTRY32. Далее создадим цикл do - while, его условием является равенство нулю функции Process32Next. Там же в цикле будем заносить в массив DWORD значение члена th32ProcessID нашей структуры, увеличивать счетчик на 1 и ставить имя процесса в листбокс. В коде это выглядит так:

// process - наша структура

idarray[i++] = process.th32ProcessID;

SendDlgItemMessage(hwnd, IDC_LISTBOX1, LB_ADDSTRING,

0, (LPARAM)process.szExeFile);

SendDlgItemMessage(hwnd, IDC_LISTBOX1, LB_SETCURSEL,

(WPARAM)SendDlgItemMessage(hw, IDC_LISTBOX1, LB_GETCOUNT, 0, 0)-1, 0

где hwnd - описание нашего окна (формы), а IDC_LISTBOX1 - идентификатор листбокса. В итоге, для того, чтобы перечислить процессы и сообщить о них нашему таскменеджеру, необходимо всего лишь выполнить этот цикл. Но системные процессы не дадут доступа к своим свойствам, и мы не сможем ни закрыть их, ни даже посмотреть их имена. Как это исправить? Надо повысить привилегии процесса-менеджера до уровня отладчика. Звучит сложно, но на самом деле - раз плюнуть. Я написал небольшую функцию для изменения собственных привилегий. Запусти ее с параметром true, и получишь уровень отладчика, с false - ты его, соответственно, лишишься.

Листинг функции, дающей привилегии отладчика нашей программе

void EnableDebugPrivilege(bool fEnable){

HANDLE hToken;

if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)){

TOKEN_PRIVILEGES tp;

tp.PrivilegeCount = 1;

LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);

tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;

AdjustTokenPrivileges(hToken, false, &tp, sizeof(tp), NULL, NULL);

CloseHandle(hToken);

}

}

Убиваем процессы

Хорошо, какие процессы есть в системе - мы знаем, но как ими манипулировать? Для этого нам нужно получить хэндл процесса. Только получив его, можно с ним что-нибудь сотворить. Делается это с помощью функции OpenProcess, передав которой параметры PROCESS_ALL_ACCESS, false и идентификатор процесса (из массива), получим дескриптор. Поскольку мы пишем менеджер процессов, то первое, что он должен уметь - эти процессы убивать (завершать). Завершить их совсем не сложно. Достаточно запустить функцию TerminateProcess с параметрами: хэндл процесса и код завершения (я пишу 0). Функция завершит процесс, а так как привилегии у нас высокие, то убиваемый процесс умрет без лишних слов.

После того, как ты завершил работу с дескриптором процесса или любым другим хэндлом, стоит его закрыть с помощью функции CloseHandle.

Практика убийства процесса проста так же, как и теория. В нашей программе массив идентификаторов процессов и список связаны, так что при нажатии на кнопку завершения процесса необходимо будет вычислить номер выделенного в списке элемента и уже с ним работать. В итоге код завершения получился довольно компактный:

// вычисляем индекс выделенного элемента

int index = SendDlgItemMessage(hwnd, IDC_LISTBOX1, LB_GETCOUNT, 0, 0);

// открываем процесс из массива с этим индексом

HANDLE hProcess = OpenProcess (PROCESS_ALL_ACCESS, false, idarray[index]);

// убиваем его

TerminateProcess(hProcess, 0);

// закрываем хэндл

CloseHandle(hProcess);

Break

Так уж вышло, что я терпеть не могу стандартные системные утилиты Windows и всегда стараюсь написать свои. Так получилось и с процесс-менеджером. Я описал самую примитивную программу для манипулирования процессами, так что для твоего творчества остается уйма места. Например, ты можешь заменить listbox на listview и добавить к именам процессов их иконки или, например, создать возможность изменения приоритетов процесса с помощью функции SetPriorityClass. Если возникли какие-нибудь вопросы, идеи или замечания - пиши. Постараюсь ответить.

На этом все. Удачного компилирования.

Мне часто пишут письма с просьбой объяснить, как работает та или иная утилита, или чем руководствоваться при написании системных программ. В последнее время при ответе на такие письма я стал ограничиваться всего лишь ссылкой на одну великую книгу: "Programming Applications for Windows" (русское название - "Windows для профессионалов"), автором которой является редактор Microsoft Press Джеффри Рихтер. Эта книга является библией системного программирования под Windows. В ней читатель может найти ответы на все вопросы, возникающие при написании приложений. Безусловно, огромный интерес при прочтении книги вызывает целая глава о перехвате API функций, о технологии, позволяющей как угодно манипулировать системой. Книга содержит в себе огромное количество прекрасно оформленных исходников и будет полезна любому начинающему или продвинутому кодеру.




Рубрика: C/С++




Вышел MySQL 5.1.30, первый стабильный рели....

MySQL

После публикации 29 тестовых версий анонсирован первый стабильный релиз MySQL 5.1, пригодный для промышленной эксплуатации и обеспечивающий увеличение производительности для "тяжелых" SQL запросов, по сравнению с MySQL 5.0, примерно на 15-20%. Главные новшества появившиеся в MySQL 5.1:


Подробнее... | Рубрика: MySQL | Добавлено: 28.11.2008

Тестирование параллельных программ.

Тестирование

Тестирование параллельного программного обеспечения представляет собой более сложную задачу по сравнению с тестированием последовательной программы. Программист должен знать о подводных камнях при тестировании параллельного кода, имеющихся методологиях и инструментарии.


Подробнее... | Рубрика: Тестирование | Добавлено: 28.11.2008

Архитектура AMD64 (EM64T).

Архитектура AMD

Аннотация. В статье кратко рассматривается архитектура AMD64 компании AMD и ее реализация EM64T компании Intel. Описаны особенности архитектуры, ее возможности, достоинства и недостатки.


Подробнее... | Рубрика: Архитектура AMD | Добавлено: 27.11.2008

Остальные статьи:

Платформа 2009. Определяя будущее
Windows Vista Bridge Sample Library - упра...
Оптимизация 64-битных программ
Подгрузка через AJAX HTML-кода, содержащег...
Обзор нового релиза самой мощной Ajax библ...
Firebug 1.3 и 1.4 alpha — что нового и инт...
Релиз Microsoft Silverlight 2.0. Что новог...
XML документация в C#
Курсоры в MySQL 5
Microsoft опубликовала подробности о сесси...
Microsoft делится подробностями о том, что...
Тестируем новый javascript от нового брауз...
MySQL Query Cache
Использование провайдеров компиляции в As...
Чего мы ждем от C# 4.0
Delphi 2009 и C++Builder 2009
Джоэл Спольски и Джеф Этвуд запустили новы...
Поиск кода Google /* что нового? */
10 jQuery скриптов для улучшения интерфейс...
Генераторы отчетов FastReport 4 и QuickRep...


Цитата дня (все,добавить):

Портал фрилансеров

работа на дому


    Рубрикатор

Программирование

C/С++
Обучение
Windows API
XAML
Моделирование
Паттерны
Visual Basic 7 .NET
WxWidgets
Функции WinApi
Функции С++
Разработка под Mac OS
Eiffel
Visual Studio 2008
UI дизайн
Алгоритмы
Конкурсные статьи
Turbo Pascal
Visual Studio
CASE-средства
Visual Studio 2005
Без VCL
Delphi
Тех. документация
Тестирование
Software Testing
ООП
TCP/IP
Google Android
Windows Installer
.NET Framework
Драйвера
C# C Sharp
Справка
Проектирование
Информ. системы
Visual Basic
Assembler
Оптимизация кода
Gtk+
Компоненты
Реинжиниринг
Управление проектами
Extreeme programming
Lotus Notes
Алгебраическое проектирование


Интернет технологии

PHP
Perl
ASP
WAP
Cookies
SSI
CGI
Web Servers
VB Script
DNS
CSS
XML
Html
Java Script
Java2ME
Firewall
Flash
.htaccess
Apache
VRML
Протоколы
Поисковые системы
Технология JAVA
Учебник по PHP
Учебник по JavaScript
Учебник по XML
Java Q&A
AJAX
DHTML
XHTML
Dreamweaver
Web 2.0
Python
Вебмастеру
Cisco
Ruby on Rails
Silverlight

Базы данных

Access
InterBase
MySQL
Oracle
ADO .NET
Основы SQL
Учебник по Access 2002
MS
Microsoft FoxPro
Доступ к данным
XML в MS SQL Server 2000
ODBC и MyODBC
Обучение
Caché
DB2
PostgresSQL
Sybase
Теория
Хранилища данных
Безопасность
Реляционные данные
MySQL и mSQL

Остальное:

Разное
Обзоры книг
Безопасность
Графика и дизайн
Юмор
Linux
Фракталы
Microsoft Axapta
Многоядерность
Сети
Microsoft Office
Работа
MS-DOS
Криптография
Графика и игроделание
Новости SDK
Системы защиты
Учебник по AutoCad
CVS
Windows XP
Windows Server 2003
Windows Vista
Windows 7
Мероприятия