
- •1. Теоретична частина
- •1.1 Основи розробки додатків Windows
- •1.2 Головна функція WinMain
- •1.3 Параметри функції WinMain
- •1.4 Склад функції WinMain()
- •2. Практична частина
- •2. Відслідковувати кожен з процесів(його статус, назву, час життя).
- •2.3 Відслідковувати кожен з процесів(його статус, назву, час життя).
- •2.4 Відслідковувати діяльність користувача
- •2.5 Інші функції, використані в програмі
- •2.6 Опис алгоритму роботи програми
2.3 Відслідковувати кожен з процесів(його статус, назву, час життя).
Після того я файл був обраний він запускається у процесі, а процес створюється за допомогою: CreateProcess.
CreateProcess имеет следующий прототип:
BOOL CreateProcess(
LPCTSTR lpApplicationName, // ім’я виконуючого модуля
LPTSTR lpCommandLine, // командна строчка
LPSECURITY_ATTRIBUTES lpProcessAttributes, // захист процесу
LPSECURITY_ATTRIBUTES lpThreadAttributes, // захист потока
BOOL bInheritHandles, // ознак наслідування дескриптору
DWORD dwCreationFlags, // прапорці створення процесу
LPVOID lpEnvironment, // блок нового середовища
LPCTSTR lpCurrentDirectory, // поточний каталог
LPSTARTUPINFO lpStartUpInfo, // головне вікно
LPPROCESS_INFORMATION lpProcessInformation // інформація о процесі
);
За роботою кожного з процесів слідкує функція: IsProcessStillRunning ця функція перевіряє активний або неактивній процес.
Час життя вимірює звичайним таймером: WM_TIMER який підраховує скільки працює кожен з процесів.
СинтаксисWM_TIMER: WM_TIMER
( WPARAM wParam LPARAM lParam;
)
wParam
[in] Визначає ідентифікатор таймера.
lParam
[in] Покажчик на певну програмою функцію зворотного виклику, яка передавалася в функцію SetTimer, коли таймер був встановлений.
І вся інформація про кожен з процесів передається вже у повідомлені WM_PAINT. Додаток малює у вікні у відповідь на повідомлення. Система посилає це повідомлення віконної процедури, коли змінює у вікні перероблене вміст робочої області. Система посилає повідомлення тільки тоді, якщо немає ніяких інших повідомлень в черзі повідомлень прикладної програми.
Синтаксис WM_PAINT:
LRESULT CALLBACK WindowProc(
HWND hwnd, // дескриптор вікна
UINT uMsg, // WM_PAINT
WPARAM wParam,
LPARAM lParam
);
Рис. 2 виведення розгорнутої інформації про запущений процес
2.4 Відслідковувати діяльність користувача
У завдані чітко вказано що не обхідно виводити інформацію тільки в тому випадку якщо користувач так захоче.
Це було реалізовано за допомогою WM_RBUTTONDOWN яка виконує певні дій на натиснуту праву кнопку миші. Є глобальна змінна button_check дані якої перезаписуються з 0 на 1 та навпаки при натиснутій правій клавіші миші. Після чого у WM_PAINT виконується один с двох варіантів виконання при button_check = 0 дивитись рисунок 3 та при button_check =1 дивитись рисунок 4.
Синтаксис WM_RBUTTONDOWN
WM_RBUTTONDOWN
WPARAM wParam
LPARAM lParam;
Рис 3. Стисла інформація про процес
Рис 4. розгорнута інформація про процес
2.5 Інші функції, використані в програмі
WM_DESTROY
Це повідомлення надсилається коли необхідно знищити вікно. Після видалення його з екрана. Надсилається повідомлення спочатку головного вікна, а потім дочірнім вікнам. Після прийняття цього повідомлення необхідно викликати функцію PostQuitMessage (). Повідомлення про руйнування вікна надійде саме віконної процедури, а не в стандартній черзі повідомлення.
Також у цій функцій використовується KillTimer який виключає таймер щоб він не висів у системі навіть після виключення програми.
2.6 Опис алгоритму роботи програми
При старті програми користувачеві необхідно у полі меню вибрати пункт StartExe після чого для нього відкриється вікно оглядача в якому він повинен буде обрати файл для запуску у програмі. Файли можуть бути лише з розширенням .ехе. Обраній файл запускається у процесі, програма може підтримувати у робочому стані двадцять процесів одночасно. Після того як процес було створено за його статусом слідкує IsProcessStillRunning ця функція перевіряє активний або неактивній процес і передає параметри у таймер WM_TIMER який підраховує скільки працює кожен з процесів до поки від функції IsProcessStillRunning не прийде підтвердження що користувач завершив процес у цьому випадку статус процесу зминеться з ACTIVE на STOPED, а таймер припинить підраховувати час життя процесу.
Якщо користувач під час роботи процесів натисне правою кнопкою миші на робочої області програми він отримає розгорнуту інформацію по кожному з процесів навіть по тим що вже завершили роботу за цим слідкує WM_RBUTTONDOWN завдяки глобальній змінній яка змінює своє значення з 0 на 1 та навпаки при натисканні на праву клавішу миші. Вся інформація передається у WM_PAINT де існує два способи виводу інформації стислий та розгорнутий і варіюється вони в залежності від того що записано у глобальній зміні. Для того щоб завершити виконання програми необхідно вибрати пункт вихід у меню програми або натиснути на хрестик у правому верхньому куті вікна, в цьому випадку знищується батьківське вікно, а разом з ним всі дочірні, також припиняє свою роботу таймер.
ВИСНОВКИ
В курсовій роботі було вирішена поставлена задача, для цього були використані функції, масиви, цикли та інше. Були здобуті навички роботи з файлами, процесами та обробка даних цих процесів . В процесі розробки були здобуті навички роботи з програмним забезпеченням Microsoft Visual Studio, з використанням стандартних бібліотек та функцій Win API.
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ
1. Финогенов К.Г. Win32. Основы программирования. – 2-е изд., испр. и дополн. – М.: ДИАЛОГ – МИФИ, 2006. – 416 с.
2. Побегайло А.П. Системное программирование в Windows, - СПб.: БХВ – Петербург, 2006. - 1056 с.: ил.
3. Литвиненко Н.А. – Технология программирования на С++. Win32 API-приложения – 2010.
4. Рихтер Дж. Windows для профессионалов: создание эффективных Win32- приложений с учетом специфики 64-разрядной версии Windows: Пер. с англ.
5. Шупак Ю. А. Win32 АР1. Разработка приложений для \Vindows. — СПб.: Питер, 2008.
6. Верма Р. Д. Справочник по функциям Win32 АР1. — 2-е изд., перераб. и доп М.: Горячая линия — Телеком, 2005.
ДОДАТОК А
// Kurs.cpp: определяет точку входа для приложения.
//
#include "stdafx.h"
#include "Kurs.h"
#include <Windows.h>
#include <CommDlg.h>
#define MAX_LOADSTRING 100
#define MAX_PROCESSES 20
#define IDT_TIMER 1000
int button_check=0;
// Глобальные переменные:
HINSTANCE hInst; // текущий экземпляр
TCHAR szTitle[MAX_LOADSTRING]; // Текст строки заголовка
TCHAR szWindowClass[MAX_LOADSTRING]; // имя класса главного окна
TCHAR filename[MAX_PATH]; /*буфер под имя файла*/
TCHAR filters[] = "Program files (.)\0*.exe\0";
OPENFILENAME of;
HPEN hPen;
typedef struct {
STARTUPINFO si;
PROCESS_INFORMATION pi;
TCHAR process_name[MAX_PATH];
volatile UINT nCount;
} PROCESS;
PROCESS processes[MAX_PROCESSES];
int current_process;
// Отправить объявления функций, включенных в этот модуль кода:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
void StartExe(HWND);
bool IsProcessStillRunning(PROCESS p);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: разместите код здесь.
MSG msg;
HACCEL hAccelTable;
// Инициализация глобальных строк
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_KURS, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Выполнить инициализацию приложения:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_KURS));
// Цикл основного сообщения:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// ФУНКЦИЯ: MyRegisterClass()
//
// НАЗНАЧЕНИЕ: регистрирует класс окна.
//
// КОММЕНТАРИИ:
//
// Эта функция и ее использование необходимы только в случае, если нужно, чтобы данный код
// был совместим с системами Win32, не имеющими функции RegisterClassEx'
// которая была добавлена в Windows 95. Вызов этой функции важен для того,
// чтобы приложение получило "качественные" мелкие значки и установило связь
// с ними.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_KURS));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_KURS);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// ФУНКЦИЯ: InitInstance(HINSTANCE, int)
//
// НАЗНАЧЕНИЕ: сохраняет обработку экземпляра и создает главное окно.
//
// КОММЕНТАРИИ:
//
// В данной функции дескриптор экземпляра сохраняется в глобальной переменной, а также
// создается и выводится на экран главное окно программы.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Сохранить дескриптор экземпляра в глобальной переменной
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
// Set the timer for the mousetrap.
UINT uResult = SetTimer(hWnd, // handle to main window
IDT_TIMER, // timer identifier
1000, // 1-second interval
(TIMERPROC) NULL); // no timer callback
if (uResult == 0)
{
MessageBox(hWnd, "No timer is available.", "Error", MB_OK);
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// НАЗНАЧЕНИЕ: обрабатывает сообщения в главном окне.
//
// WM_COMMAND - обработка меню приложения
// WM_PAINT -Закрасить главное окно
// WM_DESTROY - ввести сообщение о выходе и вернуться.
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc,hmdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Разобрать выбор в меню:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_START_EXE:
StartExe(hWnd);
break;
case IDM_EXIT:
// !!!! TODO - добавить код убивания процессов
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_TIMER: {
for (int i=0; i<current_process; i++) {
if (IsProcessStillRunning(processes[i])) processes[i].nCount++;
}
RECT rect;
GetClientRect(hWnd, &rect);
InvalidateRect(hWnd, &rect, true);
break;
}
case WM_RBUTTONDOWN:
{
if(button_check==0)
{
button_check=1;
}
else
button_check=0;
break;
}
case WM_PAINT: {
if (button_check==1)
{
hdc = BeginPaint(hWnd, &ps);
// TODO: добавьте любой код отрисовки...
// тут пробежаться циклом по processes и вывести информацию
hPen = CreatePen(0, 2, RGB(0,0,0xFF));
SelectObject(hdc, hPen);
TCHAR process_str[1024];
TCHAR temp[ ] = "Name: %s Process ID: %d Thread ID: %d Live time: %d sec, Active: %s";
for (int i=0; i<current_process; i++) {
wsprintf(process_str, temp, processes[i].process_name, processes[i].pi.dwProcessId, processes[i].pi.dwThreadId, processes[i].nCount,
IsProcessStillRunning(processes[i]) ? "ACTIVE" : "STOPPED");
int len=0; while (process_str[len]!=0) len++;
TextOut(hdc, 400, 400 + 25* i, process_str, len );
}
ValidateRect(hWnd,NULL);
EndPaint(hWnd, &ps);
break;
}
else
hdc = BeginPaint(hWnd, &ps);
// TODO: добавьте любой код отрисовки...
// тут пробежаться циклом по processes и вывести информацию
hPen = CreatePen(0, 2, RGB(0,0,0xFF));
SelectObject(hdc, hPen);
TCHAR process_str[1024];
TCHAR temp[ ] = "Name: %s Active: %s";
for (int i=0; i<current_process; i++) {
wsprintf(process_str, temp, processes[i].process_name,
IsProcessStillRunning(processes[i]) ? "ACTIVE" : "STOPPED");
int len=0; while (process_str[len]!=0) len++;
TextOut(hdc, 400, 400 + 25* i, process_str, len );
}
ValidateRect(hWnd,NULL);
EndPaint(hWnd, &ps);
break;
}
case WM_DESTROY:
KillTimer(hWnd, IDT_TIMER);
for (int i=0; i<current_process; i++)
{
if (IsProcessStillRunning(processes[i])) TerminateProcess(processes[i].pi.hProcess, 0);
}
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
bool IsProcessStillRunning(PROCESS p)
{
DWORD code;
return GetExitCodeProcess(p.pi.hProcess, &code) !=0 && code == STILL_ACTIVE;
}
// Обработчик сообщений для окна "О программе".
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
void StartExe(HWND hWnd)
{
if (current_process >= MAX_PROCESSES) {
MessageBox(hWnd, "Maximum number of processes is being running.", "Error", MB_OK);
return;
}
ZeroMemory(&of, sizeof(of));
ZeroMemory(&filename, sizeof(filename));
of.lStructSize=OPENFILENAME_SIZE_VERSION_400A; /*размер структуры OPENFILENAME*/
of.hwndOwner=NULL ; /*дескриптор родительского окна*/
of.hInstance=hInst; /*дескриптор экземпляра программы*/
of.lpstrFilter=filters;/*фильтр файлов (тип)*/
of.lpstrCustomFilter=NULL; /*еще один фильтр: нам не надо*/
of.nMaxCustFilter=0; /*нам не надо*/
of.nFilterIndex=1; /*количество заданных нами фильтров*/
of.lpstrFile=filename; /*адрес буфера под имя файла*/
of.nMaxFile=MAX_PATH; /*размер буфера под имя файла*/
of.lpstrFileTitle=NULL; /*буфер под рекомендуемый заголовок: нам не надо*/
of.nMaxFileTitle=0; /*нам не надо*/
of.lpstrInitialDir=NULL; /*стартовый каталог: текущий*/
of.Flags=OFN_PATHMUSTEXIST; /*разные флаги*/
if (GetOpenFileName(&of)) {
// действия в случае успешного выбора файла /
CreateProcess(NULL, of.lpstrFile, NULL, NULL, NULL, NULL, NULL, NULL, &(processes[current_process].si), &(processes[current_process].pi));
strcpy (processes[current_process].process_name,of.lpstrFile);
processes[current_process].nCount=0;
current_process++;
}
}