Статьи по Делфи
Меню сайта


Категории каталога
Мои статьи [2]
Функции и процедуры Win Api [20]
Работа с мышью [10]
Реестр и Делфи [11]
Работа с файлами [38]
Делфи и Хакер [10]
Инсталлятор собственными руками [6]
Хитрости в делфи [3]
Работа с системой [19]


Форма входа


Поиск по каталогу


Друзья сайта


Наш опрос
Понравились ли вам треки
Всего ответов: 156


Приветствую Вас, Гость · RSS 2024-04-19, 9:51 AM
Начало » Статьи » Работа с системой

Как писать сервисы на Delphi
Если Вы воспользуетесь мастером создания сервиса в delphi, то он даст Вам минимальный код, который годится разве что только для самого начала работы по созданию заготовки пустого ничего не делающего сервиса. К тому же сервис довольно трудно отлаживать. А в операционных системах windows 9x невозможно использовать вовсе. Поэтому, обычно, сервис делают одновременно обычным приложением с возможностью регистрации и запуска как сервис. Т.е. если операционная система windows 9x, то запускаем его в автозагрузке, если windows nt, xp и выше, то регистрируем в сервисах. Если сервис нуждается в настройках или показе текущего состояния, то лучше всего, чтобы он отображал свою иконку в панели задач, как это делают, например, часы, с возможностью управлять им через всплывающее меню. Вот такой сервис мы с Вами сейчас и создадим.
Итак, выполним пункт меню file|new|other… В списке категорий выберите delphi projects и дважды щелкните по иконке service applications.

Сохраните полученные модули на диск. Я сохранил сервис как main.pas, а проект – myservice.pas. Переименуйте сервис в myservice. Затем, добавьте к проекту окно. Это будет окно, показывающее состояние сервера и информацию о программе. Сохраните модуль под именем aboutform. Так как мы будем запускать наш сервис еще и в режиме простой программы, то нам как-то нужно различать эти два режима. Для этого можно завести глобальную переменную в модуле aboutform. Я назвал её fromservice: boolean. Если запускается сервис, то она равна true, если как программа – false. Вот модуль сервиса:

unit main;
interface
uses
windows, messages, sysutils, classes, graphics, controls, svcmgr, dialogs,
menus;
type
tmyservice = class(tservice)
procedure servicestop(sender: tservice; var stopped: boolean);
procedure servicestart(sender: tservice; var started: boolean);
private
public
function getservicecontroller: tservicecontroller; override;
{ public declarations }
end;
var
myservice: tmyservice;
implementation
uses aboutform;
{$r *.dfm}
procedure servicecontroller(ctrlcode: dword); stdcall;
begin
myservice.controller(ctrlcode);
end;
function tmyservice.getservicecontroller: tservicecontroller;
begin
result:=servicecontroller;
end;
procedure tmyservice.servicestart(sender: tservice; var started: boolean);
begin
started:=true;
end;
procedure tmyservice.servicestop(sender: tservice; var stopped: boolean);
begin
stopped:=true;
end;
end.
Как видите, он практически пустой. Здесь есть только два обработчика на старт и останов сервиса. Вот код окна about:

unit aboutform;
interface
uses
windows, messages, sysutils, variants, classes, graphics, controls, forms,
dialogs, menus, shellapi, buttons, stdctrls;
const wm_midasicon = wm_user + 1;
type
tfabout = class(tform)
popupmenu: tpopupmenu;
miclose: tmenuitem;
n1: tmenuitem;
config1: tmenuitem;
miproperties: tmenuitem;
speedbutton1: tspeedbutton;
label8: tlabel;
label9: tlabel;
label11: tlabel;
label7: tlabel;
label6: tlabel;
procedure config1click(sender: tobject);
procedure label7click(sender: tobject);
procedure label6click(sender: tobject);
procedure speedbutton1click(sender: tobject);
procedure formclose(sender: tobject; var action: tcloseaction);
procedure formdestroy(sender: tobject);
procedure formcreate(sender: tobject);
procedure mipropertiesclick(sender: tobject);
procedure micloseclick(sender: tobject);
private
fnt351: boolean;
ficondata: tnotifyicondata;
fclosing: boolean;
procedure addicon;
procedure deleteicon;
procedure wmmidasicon(var message: tmessage); message wm_midasicon;
protected
public
end;
var
fabout: tfabout;
fromservice: boolean;
implementation
{$r *.dfm}
uses main;

Иконку можно добавить только начиная с windows 95 или windows nt4 (как известно, у неё рабочий стол от windows 95). Поэтому, сначала нужно проверить версию windows, и если она выше nt 3.51, то можно добавлять. Добавляется иконка вызовом api оболочки - shell_notifyicon. Для этого просто заполняется структура tnotifyicondata и делается соответствующий вызов. Как видите, саму иконку можно взять из окна about. Это хорошо, т.к. тогда можно сделать иконку 16Х16, а не 32Х32. Такая иконка будет лучше смотреться в панели задач. ucallbackmessage будет посылаться оболочкой всякий раз, когда там происходят некоторые события с мышью.

procedure tfabout.addicon;
begin
if not fnt351 then
begin
with ficondata do
begin
cbsize := sizeof(ficondata);
wnd:=handle;
uid:=$dedb;
uflags:=nif_message or nif_icon or nif_tip;
hicon:=icon.handle;
ucallbackmessage:=wm_midasicon;
strcopy(sztip, pchar('my service'));
end;
shell_notifyicon(nim_add, @ficondata);
end;
end;

Здесь мы просто просим оболочку удалить иконку из панели задач.

procedure tfabout.deleteicon;
begin
if not fnt351 then
shell_notifyicon(nim_delete, @ficondata);
end;

Метод wmmidasicon объявлен как обработчик события wm_midasicon. Здесь проверяется какое именно событие произошло. Если двойной клик по иконке, то показывается окно about, если клик правой кнопкой мыши, то показывается всплывающее меню. Это меню можно поставить прямо на окно about. Там три пункта: close, разделитель, configuration, about. К нему мы еще вернемся позже.

procedure tfabout.wmmidasicon(var message: tmessage);
var pt: tpoint;
begin
case message.lparam of
wm_rbuttonup: begin
if not visible then
begin
setforegroundwindow(handle);
getcursorpos(pt);
popupmenu.popup(pt.x, pt.y);
end
else
setforegroundwindow(handle);
end;
wm_lbuttondblclk: if visible then
setforegroundwindow(handle)
else
mipropertiesclick(nil);
end;
end;

При создании окна проверяется версия windows, затем, если программа запущена как сервис, то делается невидимым пункт меню close и разделитель. Это сделано специально, чтобы останавливать сервис можно было только в штатном режиме из апплета управления компьютером. Далее, добавляется иконка.

procedure tfabout.formcreate(sender: tobject);
begin
fnt351 := (win32majorversion <= 3) and (win32platform = ver_platform_win32_nt);
if fromservice then
begin
miclose.visible:=false;
n1.visible:=false;
end;
addicon;
fclosing:=false;
end;

При уничтожении окна иконка удаляется.

procedure tfabout.formdestroy(sender: tobject);
begin
deleteicon;
end;

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

procedure tfabout.formclose(sender: tobject; var action: tcloseaction);
begin
if fclosing then
action:=cafree
else
action:=cahide;
end;

На форме about есть кнопка для вызова справки. Т.к. application для сервиса не имеет методов вызова файла помощи, то пришлось пользоваться api. Здесь id_cont определен в файле помощи пункт, а myserver.hlp – имя файла помощи.

procedure tfabout.speedbutton1click(sender: tobject);
var command: array[0..255] of char;
begin
strlfmt(command, sizeof(command) - 1, 'jumpid("","%s")', ['id_cont']);
winhelp(handle, pchar(extractfilepath(paramstr(0))+'myserver.hlp'), help_contents, longint(@command));
end;

На форме стоит две метки с надписью support и www.myserver.ru для перехода на сайт разработчика.
procedure tfabout.label6click(sender: tobject);
begin
shellexecute(forms.application.handle, 'open', 'mailto:support@myserver.ru?subject=myserver : bugs!!!', '', '', sw_show);
end;
procedure tfabout.label7click(sender: tobject);
begin
shellexecute(forms.application.handle,'open','http://www.myserver.ru','','',sw_show);
end;

Пункт меню close. Когда запушено приложение, то уничтожение окна about закрывает программу, т.к. оно является главным окном.

procedure tfabout.micloseclick(sender: tobject);
begin
fclosing:=true;
close;
end;

Пункт меню about – просто показывает форму, т.е. саму себя.

procedure tfabout.mipropertiesclick(sender: tobject);
begin
showmodal;
deleteicon;
addicon;
end;

Пункт меню configuration. Здесь один из вариантов решения проблемы. Часто для управления настройками сервисов используют апплеты в панели управления. Для этого достаточно написать свою cpl. Но, не хотелось бы повторять весь этот код в сервере. Как известно, cpl – это обычная dll, поэтому нам ничего не мешает экспортировать какой-нибудь метод из нее и загрузить её динамически…

procedure tfabout.config1click(sender: tobject);
type tgetdesignerinterface = procedure; safecall;
var getfunc: tgetdesignerinterface;
dllhandle: thandle;
const
dllname = 'mysrvcnf.cpl';
funcname = 'editconfiguration';
begin
dllhandle:=loadlibrary(pchar(dllname));
if dllhandle < 32 then
raise exception.create('not found "'+dllname+'" !');
getfunc:=getprocaddress(dllhandle, pchar(funcname));
if not assigned(getfunc) then
begin
freelibrary(dllhandle);
raise exception.create('not fount function "'+funcname+'"');
end;
try
getfunc;
finally
freelibrary(dllhandle);
end;
end;
end.
Наконец, код проекта сервиса:

program myserver;

Обратите внимание, что в uses указан модуль forms, который не включается автоматически в проект. Он нам понадобится для запуска нашего сервера как приложения.
uses
svcmgr,
forms,
sysutils,
windows,
types,
winsvc,
main in 'main.pas' {myserver: tservice},
aboutform in 'aboutform.pas' {fabout};
{$r *.res}
Проверка командной строки на предмет указаний инсталлировать или удалить сервис.

function installing: boolean;
begin
result:=findcmdlineswitch('install',['-','','/'], true) or
findcmdlineswitch('uninstall',['-','','/'], true);
end;
Функция проверяет, что приложение запущено как сервис. Этот код просто взят из модуля scktsrvr.dpr. Кстати, если разобраться в этом проекте, то Вы сможете писать сервисы даже на delphi 2, 3.
function startservice: boolean;
var mgr, svc: integer;
username, servicestartname: string;
config: pointer;
size: dword;
begin
result:=false;
mgr:=openscmanager(nil, nil, sc_manager_all_access);
if mgr <> 0 then
begin
svc:=openservice(mgr, pchar('myservice'), service_all_access);
result:=svc <> 0;
if result then
begin
queryserviceconfig(svc, nil, 0, size);
config:=allocmem(size);
try
queryserviceconfig(svc, config, size, size);
servicestartname:=pqueryserviceconfig(config)^.lpservicestartname;
if comparetext(servicestartname, 'localsystem') = 0 then
servicestartname:='system';
finally
dispose(config);
end;
closeservicehandle(svc);
end;
closeservicehandle(mgr);
end;
if result then
begin
size:=256;
setlength(username, size);
getusername(pchar(username), size);
setlength(username, strlen(pchar(username)));
result:=comparetext(username, servicestartname) = 0;
end;
end;

Если приложение запускается как сервис, или если его хотят зарегистрировать как сервис, то мы идем по пути как в проекте, созданном delphi по умолчанию. Единственное, что лучше явно указывать, какой именно application мы используем: в svcmrg – это сервис, а в forms – это простое приложение. Если же запуск идет как простое приложение, указываем, что не нужно показывать главную форму, делаем форму about основной (первая созданная), создаем форму сервиса. Важно, что сервис – это tdatamodule. И когда мы его так создадим из tapplication, то сервис не будет запущен. Это и хорошо – у нас будет просто подходящий модуль данных j

begin
if installing or startservice then
begin
svcmgr.application.initialize;
aboutform.fromservice:=true;
svcmgr.application.createform(tfabout, fabout);
svcmgr.application.createform(tmyservice, myservice);
svcmgr.application.run;
end
else
begin
forms.application.showmainform:=false;
forms.application.initialize;
aboutform.fromservice:=false;
forms.application.createform(tfabout, fabout);
forms.application.createform(tmyservice, myservice);
forms.application.run;
end;
end.
Уже можно запустить и покликать по меню, закрыть, зарегистрировать и запустить как сервис – все работает. Но, наш сервис пуст и ничего не делает. Что он должен делать – Вам решать.
И последнее, зарегистрировать сервис можно командой myserver /install, а удалить регистрацию – myserver /uninstall.
Успехов в разработке своих сервисов!

Категория: Работа с системой | Добавил: Admin (2006-12-18)
Просмотров: 12917 | Комментарии: 82 | Рейтинг: 2.5 |

Всего комментариев: 4
4 Larryfup  
0
http://proxyelite.biz/ - купить приватные прокси - аренда прокси, прокси купить.

3 deborahsy1  
0
Анальный секс, фото галереи анала, секс фото
http://porno.blondinka.sexgalleries.top/?blog.jayla
Секс фото галереи для взрослых

2 KennethBirm  
0
http://vermoxbezreceptu.etowns.net - http://vermoxbezreceptu.etowns.net/vyprodej700.jpg
http://vermoxbezreceptu.etowns.net 21. rijen 2010 ... Casopis dTest nakupuje vyrobky v bezne obchodni siti a naklady spojene s testovanim hradi z prodeje predplatneho. ... Mezi ne patri napriklad znama Kamagra vyrabena indickou ... Foto: marketingpilgrim.comViagra je ucinna, ale draha ... na body ani na cas, ale hodnotime hlavne umelecky dojem a styl.7. cerven 2006 ... Diskuse · Ostatni ..... Atomoxetin (Strattera) je selektivni inhibitor zpetneho vychytavani noradrenalinu, ktery se od ... WEISS, M., MURRAY, C. Assessment and management of attention-deficit hyperactivity disorder in adults. http://vermoxbezreceptu.etowns.net - vermox

1 Sergeymup  
0
Прошлой ночью смотрел материалы интернет, и неожиданно к своему восторгу заметил восхитительный сайт. Вот смотрите: http://kinogolos.ru/news/dnevniki_vampira_smotret_onlajn/1-0-10 - дневники вампира 8 сезон . Для нас данный веб-сайт оказал радостное впечатление. Всем пока!

Имя *:
Email *:
Код *: