Шаг 382 - Пример создания приложения подобного "Службы" в WinNT

Привет Артем.
Я здесь прогу сделал для работы с сервисами
Посмотри может посчитаеш ее нужной для твоего сайта.
С Уважением Володя Салий (saliy@rambler.ru).

Постановка задачи: Создать приложение(используя AppWizard) - которое читает все сервисы в WinNT, делает представление сервисов в стандартном виде Windows, а также остановка, запуск и удаление сервиса.

382_1.gif (13034 b)

В приложении использованы классы CDialog, CListCtrl, CProgressDlg, CMenu.

Отличие от других примеров в том что класс CListCtrl - использован в простом исполнении (без сортировки , без раскраски и т.д.) кто хочет может развить дальше . Ипользуется контекстное меню , а также CProgress в отдельном окне.

Приступаем. Запускаем VC.

MFC AppWizard -> Dialog based

Oтключаем About, 3D Control, ActiveX. Далее

as statically linked library .Открываем проект -> закладку Resource -> Dialog -> IDD_SERVICE_DIALOG -> open

Заготовка есть. С диалога удалим кнопки OK и CANCEL - они нам не нужны. Теперь нам надо создать переменную класса CListCtrl. В панели Control находим значок Control list - щелкаем и на диалоге создаем окно диалога Control List - вот так.

382_2.gif (13477 b)

Щелкаем правой мышкой на диалоге и запускаем Class Wizard. Идем в Member Variable->IDC-LIST1->add variable. Называем ее m_List. Category(Тип) - Control. Жмем OK. В файле AppServiceDlg.h появится надпись

CListCtrl   m_List ;

Теперь нам надо сделать реализацию этого класса CListCtrl - создать колонки с именами и сами записи в колонках. В первой колонке - имя сервиса , во второй его состояние , в третьей oписание. Для создания колонок используется метод Creat его надо сделать. Запускаем Class Wizard, в Object IDs выделяем CAppServiceDlg, а в Message - WM_CREATE жмем Add Function т.е. мы добавили функцию Create она появится сразу в AppServiceDlg.cpp в конце в таком виде.

int CAppServiceDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CDialog::OnCreate(lpCreateStruct) == -1) 
	return -1;

	// TODO: Add your specialized creation code here 

	return 0; 
} 

Теперь сделаем заполнение наших колонок данными из структуры Service. Для начала объявим переменные и структуры в файле AppServiceDlg.cpp.

#include "winsvc.h" //Заголовочный файл для сервисов
//  Резервируем память
#define SIZE_BUF 4096
//Описываем структуру для сервиса
ENUM_SERVICE_STATUS Status[SIZE_BUF]; 
DWORD Size = sizeof(Status); 
DWORD Needed = 0;
DWORD Return = 0; 
DWORD Handle = 0; 
SC_HANDLE hSCM; 
SERVICE_STATUS ssStatus; 
DWORD dwOldCheckPoint; 
//Структура для позиции курсора
POSITION pos; 
//Имя сервиса 
CString SZSERVICENAME ; 

В самой функции int CAppServiceDlg::OnCreate вставим следующий код.

CRect rect;
GetClientRect(rect);
m_List.Create(LVS_ICON|LVS_REPORT|WS_VISIBLE,rect, this, 100);
m_List.InsertColumn(0,_T("Имя Сервиса"), LVCFMT_LEFT, rect.Width()/3);
m_List.InsertColumn(1,_T("Состояние"), LVCFMT_LEFT, rect.Width()/3);
m_List.InsertColumn(2,_T("Описание"), LVCFMT_LEFT, rect.Width()/3);
LV_ITEM item; 
item.iItem=0;
item.iImage=0; 
item.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM; 
item.iSubItem = 0; 
CString csText; 
hSCM = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); 
if (hSCM!=NULL) 
{ 
	if (EnumServicesStatus(hSCM,SERVICE_WIN32,
		SERVICE_STATE_ALL,(LPENUM_SERVICE_STATUS)&Status,
		Size,&Needed,&Return,&Handle)) 
	{ 
		for (unsigned int x=0; x < Return; x++) 
		{
			csText=Status[x].lpServiceName; 
			m_List.InsertItem(x,csText) ;
			m_List.SetItemText(x,2,Status[x].lpDisplayName);
			if (Status[x].ServiceStatus.dwCurrentState==SERVICE_RUNNING)
				csText="Работает"; 
			else
				csText="";
			m_List.SetItemText(x,1,csText);
		}
	} else {
		CloseServiceHandle(hSCM);
		return FALSE ; 
	} 
} else { 
	CloseServiceHandle(hSCM); 
	return FALSE ; 
}; 
CloseServiceHandle(hSCM); 
return 0;

Теперь откроем ресурсы , зайдем в диалоговое окно и удалим окошко раннее созданное нами Control List (что бы оно не появлялось на экране). В файле AppServiceDlg.cpp - заремаркируйте строку обмена с диалоговой панелью вот она :

//DDX_Control(pDX, IDC_LIST1, m_List);

иначе будут выдаваться ошибки. Нам нужен был объект класса CListCtrl мы его получили, но можно было вручную вписать строку в файл AppServiceDlg.h создав переменную.

CListCtrl  m_List;  

Собирайте проект и запускайте. У вас появится следующее.

382_3.gif (11626 b)

Далее. Теперь добавим Меню на диалог и сделаем контекстное меню, а также Progress окошко.

Идем в закладку Resource , выделяем правой кнопкой AppServiceResource->Insert->Menu->New

Появился в ресурсах пункт Menu - IDR_MENU1. Добавим его на диалоговую панель. Открываем в ресурсах IDD_APPSERVICE_DIALOG. Щелкаем правой кнопкой по диалогу появляются Properties - открываем - в подпункте Menu - указываем - IDR_MENU1. Тем самым мы привязали наше меню к диалоговой панели. Сделаем пункты меню: Главное , Стоп , Старт , Обновить ,Удалить сервис . Теперь делаем контекстное меню .В VC открываем project ->add to project->Components and Controls выбираем Visual C++ Components, а из предложенного списка Pop-up Menu. Жмите и вставляйте. В ресурсах меню появится CG_IDR_POPUP_APP_SERVICE_DLG. Открывайте и устанавливайте те же самые пункты меню что и в обычном далоговом меню (Стоп,Старт,Обновить,Удалить сервис) кроме пункта Главное.

Добавляем индикатор в отдельном окне. Когда у нас идет процесс запуска сервиса индикатор должен появится В отдельном окошке .Идем в Project->Add to Project->Components and Controls->VisualC++ Components. Вставляем Progress Dialog. Запускаем Class Wizard спросит создавать ли новый класс для CProgressDlg,скажите да.

Создаете c_Progress, типа CProgressCtrl. Жмите ok. Объект готов. Реализация этого класса описана в программе и в функции CAppServiceDlg::OnStop имеет вид:

CProgressDlg m_Progress;
m_Progress.Create(this);
m_Progress.SetRange(0,10);
m_Progress.SetPos(1);

События же на выбор пунктов меню вы можете установить используя Class Wizard они все описаны в программе. Я не буду приводить листинг функций - они есть в программе.


Загрузить проект | Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем - 31.05.2002