Форум: "WinAPI";
Текущий архив: 2005.08.07;
Скачать: [xml.tar.bz2];
ВнизЗапуск программы как службы. Очень нужна помощь. Найти похожие ветки
← →
m52 (2005-05-24 10:17) [0]Здравствуйте!
--------------
Я написал программу на дельфи, которая при старте Windows загружается и сворачивается в SysTray. Возникла необходимость сделать возможность загрузки и работы этой программы как службы Windows.
Что для этого нужно?
Что нужно переделать в программе, чтобы она работала как служба?
Чем отличается код, написанный просто как приложение и код, написанный для работы приложения как службы.
Очень нужна помощь.
Заранее благодарен.
← →
Digitman © (2005-05-24 10:33) [1]
> Что для этого нужно?
> Что нужно переделать в программе, чтобы она работала как
> служба?
для этого нужно было изначально создать проект приложения не как File -> New.. -> Application, а как File -> New.. -> Service Application
> Чем отличается код, написанный просто как приложение и код,
> написанный для работы приложения как службы.
весьма многим
начиная с того, что VCL-приложение-сервис использует в качестве базового класс TServiceApplication, в то время как обычное приложение - класс TApplication.
← →
m52 (2005-05-24 10:40) [2]Т.е. получается так, что нельзя сделать так, чтобы приложение запускалось опционально
1) как служба
2) как приложение
Видимо нужно жестко завязывать код программы либо под службу, либо под приложение.
← →
Digitman © (2005-05-24 10:46) [3]
> m52 (24.05.05 10:40) [2]
> Т.е. получается так, что нельзя сделать так, чтобы приложение
> запускалось опционально
> 1) как служба
> 2) как приложение
почему нельзя ? можно !
> Видимо нужно жестко завязывать код программы либо под службу,
> либо под приложение
.. либо реализовать такой алгоритм, который будет универсален, т.е. при запуске обычным образом пойдет по ветви для обычного приложения, а при запуске по соглашениям системы для сервисов - по иной ветви
← →
Digitman © (2005-05-24 11:09) [4]это - в качестве комментария к ветвлению :
uses
Forms,
SvcMgr,
FormMain in "SvcMain.pas" {MainForm: TMainForm},
SvcMain in "SvcMain.pas" {MainForm: TForm},
{$R *.RES}
begin
//если в ком.строке обнаружен 1-й параметр "/GUI"
//стартуем как обычное приложение
if ParamStr(1) = "/GUI" then
begin
Forms.Application.Initialize;
Forms.Application.CreateForm(TMainForm, MainForm);
Forms.Application.Run;
end
//иначе как сервис-приложение
else
begin
SvcMgr.Application.Initialize;
SvcMgr.Application.CreateForm(TMainService, MainService);
SvcMgr.Application.Run;
end;
end.
← →
Digitman © (2005-05-24 11:17) [5]вероятно, можно обойтись и без анализа ком.строки при принятии решения о ветвлении
родительским процессом для вновь стартуемого сервис-процесса, по идее, должен выступать процесс svchost.exe .. это условие, вероятно, и следует анализировать в dpr при принятии решения
← →
m52 (2005-05-24 11:38) [6]Спасибо. Попробую.
← →
Eraser © (2005-05-24 11:40) [7]Digitman © (24.05.05 11:17) [5]
В Borland Socket Server"e анализируется так:
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(SServiceName), 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;
← →
Digitman © (2005-05-24 11:48) [8]
> Eraser © (24.05.05 11:40) [7]
ерунду городишь
это - из другой оперы и к сабжу никакого отношения не имеет
← →
Eraser © (2005-05-24 11:52) [9]Digitman © (24.05.05 11:48) [8]
Не! Это как раз по сабжу, просто название ф-ии с толку сбивает, надо было её называть IsStartService.
← →
Digitman © (2005-05-24 12:08) [10]
> Eraser © (24.05.05 11:52) [9]
ты "смотришь в книгу - видишь фигу")
← →
Digitman © (2005-05-24 12:16) [11]
> Eraser
в BSS решение о ветвлении принимается опять же либо по наличию ключа в ком.строке либо по наличию соотв.записи в реестре.
← →
Eraser © (2005-05-24 16:54) [12]Digitman © (24.05.05 12:16) [11]
Вот код загрузки приложения/сервиса:
begin
if not Installing then
begin
CreateMutex(nil, True, "SCKTSRVR");
if GetLastError = ERROR_ALREADY_EXISTS then
begin
MessageBox(0, PChar(SAlreadyRunning), SApplicationName, MB_ICONERROR);
Halt;
end;
end;
if Installing or StartService then
begin
SvcMgr.Application.Initialize;
SocketService := TSocketService.CreateNew(SvcMgr.Application, 0);
SvcMgr.Application.CreateForm(TSocketForm, SocketForm);
SvcMgr.Application.Run;
end else
begin
Forms.Application.ShowMainForm := False;
Forms.Application.Initialize;
Forms.Application.CreateForm(TSocketForm, SocketForm);
SocketForm.Initialize(False);
Forms.Application.Run;
end;
end.
вот код ф-ии Installing
function Installing: Boolean;
begin
Result := FindCmdLineSwitch("INSTALL",["-","\","/"], True) or
FindCmdLineSwitch("UNINSTALL",["-","\","/"], True);
end;
Installing используется чисто для установки деинсталляции сервиса.
Соответственно решение о том сервис/не_сервис принимается в ф-ии StartService...
Или я что-то не допонял...
Тема интересная... самому в скором времени понадобится.
← →
Digitman © (2005-05-24 17:04) [13]
> Соответственно решение о том сервис/не_сервис принимается
> в ф-ии StartService...
да галиматья !!)
мало ли чего в реестре прописано !?)
я туда накидать всякой похожей дряни могу и безо всякого /INSTALL .. но от этого всяка дрянь, на которую я опять же могу сослаться из реестра, вовсе не обязана быть натурально сервисом ...
← →
Игорь Шевченко © (2005-05-24 17:06) [14]Digitman © (24.05.05 12:16) [11]
> в BSS решение о ветвлении принимается опять же либо по наличию
> ключа в ком.строке либо по наличию соотв.записи в реестре.
А вроде без записи в реестре сервисом стать не получится ? Или я чего не понимаю ?
← →
Eraser © (2005-05-24 17:09) [15]Digitman © (24.05.05 17:04) [13]
Так значит самый надёжный вариант определения сервис/несервис - проверять родительский процесс?
имхо наверное тогда стОит проверять по параметру при запуске и не парить себе мОзги... )
← →
Digitman © (2005-05-24 17:09) [16]
> Игорь Шевченко © (24.05.05 17:06) [14]
а вроде ком.строка, имеющая в своем контексте ключи вида /install, не обязана быть ком.строкой, имеющей ОБЯЗАТЕЛЬНОЕ отношение к сервисам ?
← →
Digitman © (2005-05-24 17:10) [17]
> Eraser © (24.05.05 17:09) [15]
> Digitman © (24.05.05 17:04) [13]
>
> Так значит самый надёжный вариант определения сервис/несервис
> - проверять родительский процесс?
мне так показалось.
думаю, ИШ прояснит ситуацию ..
← →
Игорь Шевченко © (2005-05-24 18:07) [18]Digitman © (24.05.05 17:09) [16]
> а вроде ком.строка, имеющая в своем контексте ключи вида
> /install, не обязана быть ком.строкой, имеющей ОБЯЗАТЕЛЬНОЕ
> отношение к сервисам ?
Абсолютно не обязана. Я навскидку могу написать программу, которая по ключу /Install будет выполнять форматирование винчестера.
Я к другому - сервис, он обязан придерживаться протокола взаимодействия с менеджером сервисов, и прочая и прочая. И запускаться он (сервис) будет ТОЛЬКО services.exe и никем более.
← →
ORMADA © (2005-05-25 07:19) [19]тоже заинтересовала данная тема но только не понял как проанализировать что при старте сервис-процесса выступает процесс svchost.exe ?
==>Digitman © (24.05.05 11:17) [5]
вероятно, можно обойтись и без анализа ком.строки при принятии решения о ветвлении родительским процессом для вновь стартуемого сервис-процесса, по идее, должен выступать процесс svchost.exe .. это условие, вероятно, и следует анализировать в dpr при принятии решения
← →
Digitman © (2005-05-25 08:17) [20]
> ORMADA
NtQuerySystemInformation() infoclass = SystemProcessThreadInfo
← →
Warlock © (2005-06-10 06:15) [21]Создаешь ServiceApplication. Код ServiceExecute:
procedure THaspRunnerService.ServiceExecute(Sender: TService);
var hwndHandle : THANDLE;
begin
WinExec("Путь и имя программы которую хочешь запускать",SW_SHOWMINNOACTIVE);
while not Terminated do
ServiceThread.ProcessRequests(True);
hwndHandle:=FindWindow(Nil, "Тут заголовок главного окна программы");
if hwndHandle<>0 then
PostMessage(hwndHandle, WM_QUIT, 0, 0);
end;
Способ может не лучший, но работал
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.08.07;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.038 c