![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Запуск программы из службы [D6, WinXP]
ildarkh © (2006-10-05 13:23:00)Здравствуйте,
я написал службу, в которой запускаю Блокнот. Он запускается, но без окна, только как процесс в памяти. Надо, что бы окно появлялось. Что делать?
program Project2;
const
ServiceName = 'ReplicatorGuarder';
ServiceDisplayName = 'Ñëóæáà êîíòðîëÿ èñïîëíåíèÿ Ðåïëèêàòîðà';
function GetLastErrorText:string;
var
dwSize:DWORD;
lpszTemp:LPSTR;
begin
dwSize:=512;
lpszTemp:=nil;
try
GetMem(lpszTemp,dwSize);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or
FORMAT_MESSAGE_ARGUMENT_ARRAY,
nil,GetLastError,LANG_NEUTRAL,lpszTemp,dwSize,nil);
finally
Result:=StrPas(lpszTemp);
FreeMem(lpszTemp);
end;
end;
procedure ServiceStop;
begin
if (hServerStopEvent>0) then
begin
SetEvent(hServerStopEvent);
end;
end;
procedure AddToMessageLog(sMsg:string);
var
sString:array [0..1] of string;
hEventSource:THandle;
begin
hEventSource:=RegisterEventSource(nil,ServiceName);
if hEventSource>0 then
begin
sString[0]:=ServiceName+' error: '+IntToStr(dwErr);
sString[1]:=sMsg;
ReportEvent(hEventSource,EVENTLOG_ERROR_TYPE,0,0,nil,2,0,@sString,nil);
DeregisterEventSource(hEventSource);
end;
end;
function ReportStatusToSCMgr(dwState,dwExitCode,dwWait:DWORD):BOOL;
begin
Result:=True;
with ssStatus do
begin
if (dwState=SERVICE_START_PENDING) then
dwControlsAccepted:=0
else
dwControlsAccepted:=SERVICE_ACCEPT_STOP;
dwCurrentState:=dwState;
dwWin32ExitCode:=dwExitCode;
dwWaitHint:=dwWait;
if (dwState=SERVICE_RUNNING) or (dwState=SERVICE_STOPPED) then
dwCheckPoint:=0
else
inc(dwCheckPoint);
end;
Result:=SetServiceStatus(ServiceStatusHandle,ssStatus);
//if not Result then AddToMessageLog('SetServiceStatus');
end;
procedure InstallService;
var
schService:SC_HANDLE;
schSCManager:SC_HANDLE;
lpszPath:LPSTR;
dwSize:DWORD;
begin
dwSize:=512;
GetMem(lpszPath,dwSize);
if GetModuleFileName(0,lpszPath,dwSize)=0 then
begin
FreeMem(lpszPath);
exit;
end;
schSCManager:=OpenSCManager(nil,nil,SC_MANAGER_ALL_ACCESS);
if (schSCManager>0) then
begin
schService:=CreateService(schSCManager,ServiceName,ServiceDisplayName,
SERVICE_ALL_ACCESS - 2,SERVICE_WIN32_OWN_PROCESS,SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,lpszPath,nil,nil,nil,nil,nil);
FreeMem(lpszPath);
if (schService>0) then
begin
CloseServiceHandle(schService);
end
else begin
end;
end
else
end;
procedure UnInstallService;
var
schService:SC_HANDLE;
schSCManager:SC_HANDLE;
begin
schSCManager:=OpenSCManager(nil,nil,SC_MANAGER_ALL_ACCESS);
if (schSCManager>0) then
begin
schService:=OpenService(schSCManager,ServiceName,SERVICE_ALL_ACCESS);
if (schService>0) then
begin
// Try to stop service at first
if ControlService(schService,SERVICE_CONTROL_STOP,ssStatus) then
begin
//Write('Stopping Service ');
Sleep(1000);
while (QueryServiceStatus(schService,ssStatus)) do
begin
if ssStatus.dwCurrentState=SERVICE_STOP_PENDING then
begin
//Write('.');
Sleep(1000);
end
else
break;
end;
if ssStatus.dwCurrentState=SERVICE_STOPPED then
begin end
else begin
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
exit;
end;
end;
// Remove the service
if (DeleteService(schService)) then
begin end
else
begin end;
CloseServiceHandle(schService);
end
else
begin end;
CloseServiceHandle(schSCManager);
end
else
begin end;
end;
procedure ServiceStart;
var
dwWait:DWORD;
Si : TStartupInfo;
p : TProcessInformation;
begin
// Report Status
if not ReportStatusToSCMgr(SERVICE_START_PENDING,NO_ERROR,3000) then exit;
// Create the event object. The control handler function signals
// this event when it receives the "stop" control code.
hServerStopEvent:=CreateEvent(nil,TRUE,False,nil);
if hServerStopEvent=0 then
begin
AddToMessageLog('CreateEvent');
exit;
end;
if not ReportStatusToSCMgr(SERVICE_RUNNING,NO_ERROR,0) then
begin
CloseHandle(hServerStopEvent);
exit;
end;
CreateProcess(nil,'notepad.exe',nil,nil,false,0, nil,nil,Si,p);
while True do
begin
dwWait:=WaitforSingleObject(hServerStopEvent,1);
if dwWait=WAIT_OBJECT_0 then
begin
CloseHandle(hServerStopEvent);
exit;
end;
Sleep(1000*10);
end;
end;
procedure Handler(dwCtrlCode:DWORD);stdcall;
begin
// Handle the requested control code.
case dwCtrlCode of
SERVICE_CONTROL_STOP:
begin
ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0);
ServiceStop;
ReportStatusToSCMgr(SERVICE_STOPPED,{GetLastError}0, 0);
exit;
end;
SERVICE_CONTROL_INTERROGATE:
begin
end;
SERVICE_CONTROL_PAUSE:
begin
end;
SERVICE_CONTROL_CONTINUE:
begin
end;
SERVICE_CONTROL_SHUTDOWN:
begin
end;
// invalid control code
else
end;
// Update the service status.
ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
end;
procedure ServiceMain;
begin
// Register the handler function with dispatcher;
ServiceStatusHandle:=RegisterServiceCtrlHandler(ServiceName,ThandlerFunction
(@Handler));
if ServiceStatusHandle=0 then
begin
ReportStatusToSCMgr(SERVICE_STOPPED,GetLastError,0);
exit;
end;
ssStatus.dwServiceType:=SERVICE_WIN32_OWN_PROCESS;
ssStatus.dwServiceSpecificExitCode:=0;
ssStatus.dwCheckPoint:=1;
// Report current status to SCM (Service Control Manager)
if not ReportStatusToSCMgr(SERVICE_START_PENDING,NO_ERROR,3000) then
begin
ReportStatusToSCMgr(SERVICE_STOPPED,GetLastError,0);
exit;
end;
// Start Service
ServiceStart;
end;
begin
if (ParamCount=1) then
begin
if Uppercase(ParamStr(1))='/INSTALL' then
begin
InstallService;
Halt;
end;
if Uppercase(ParamStr(1))='/UNINSTALL' then
begin
UnInstallService;
Halt;
end;
end;
// Setup service table which define all services in this process
with ServiceTableEntry[0] do
begin
lpServiceName:=ServiceName;
lpServiceProc:=TServiceMainFunction(@ServiceMain);
end;
// Last entry in the table must have nil values to designate the end of the table
with ServiceTableEntry[1] do
begin
lpServiceName:=nil;
lpServiceProc:=nil;
end;
StartServiceCtrlDispatcher(ServiceTableEntry[0]);
end.
Eraser (2006-10-07 14:44:00) [1]> [15] ildarkh (07.10.06 14:37)
теперь нажми Выход из системы -> Сменить пользователя, зайди под другим пользователем и посмотри будет работать или нет :))
ildarkh (2006-10-07 14:37:00) [2]Я использовал SERVICE_INTERACTIVE_PROCESS и работает нормально. У меня конечно запускается не блокнот, там программа в трее с диалоговым окном. Так вот, при запуске ОСи, сервис грузится, грузит и мою программу. Однако в трей она не вылазит, как если бы не использовался SERVICE_INTERACTIVE_PROCESS. Предполагаю, чисто интуитивно, она рановато грузится. Что сделать? Пока задержку поставлю, но сколько она держаться должна, точно не может быть известно.
ildarkh (2006-10-07 14:32:00) [3]Всем спасибо, проблема решена.
Германн (2006-10-06 14:47:00) [4]2 Игорь Шевченко © (06.10.06 10:18) [12]
> Это наверное очень старая виста...
Ага. И очень хреновая. Но именно её рекомендует использовать МВД. :-)
Игорь Шевченко (2006-10-06 10:18:00) [5]Германн © (06.10.06 01:25) [11]
> Зато я вижу висту вот уже более 10 лет.
Это наверное очень старая виста...
Германн (2006-10-06 01:25:00) [6]
> etmar © (05.10.06 23:31) [10]
>
> >[9] Eraser(c) 5-Oct-2006, 22:52
> >а не в курсе
> а я висту в глаза не видел. %-)
>
Зато я вижу висту вот уже более 10 лет. Глаза б мои её не видели б никогда! :-)
Ketmar (2006-10-05 23:31:00) [7]>[9] Eraser(c) 5-Oct-2006, 22:52
>а не в курсе
а я висту в глаза не видел. %-)
Eraser (2006-10-05 22:52:00) [8]> [8] Ketmar © (05.10.06 22:46)
offtop:
а не в курсе, как в висте добраться до рабочего стола, когда еще ни один юзер не залогинен, и вообще в какой по счету терминальной сессии находится десктоп в этот момент?
Ketmar (2006-10-05 22:46:00) [9]>[7] Eraser(c) 5-Oct-2006, 22:43
>единственное общее решиние - для каждого нового
>пользователя (терминальной сессии) запускать GUI
>приложение-посредник
кстати, так обычно и делаю. видимо, интуитивно. %-)
Eraser (2006-10-05 22:43:00) [10]> [0] ildarkh (05.10.06 13:23)
единственное общее решиние - для каждого нового пользователя (терминальной сессии) запускать GUI приложение-посредник, которое и будет запускать приложения по команде сервиса, передаваемой, к примеру, через именованые каналы.
остальные решения, в т.ч. и с SERVICE_INTERACTIVE_PROCESS не будут работать в Vist'е вообще, а в winXP будут глючить, если применять FUS.
Ketmar (2006-10-05 16:26:00) [11]и, по-моему, стоит ещё проверять десктопы. на всякий случай. %-)
han_malign (2006-10-05 14:05:00) [12]
> разрешить службе взаимодействие с рабочим столом
- укорочу поиск
CreateService(...,SERVICE_WIN32_OWN_PROCESS or SERVICE_INTERACTIVE_PROCESS,...)
Polevi (2006-10-05 13:59:00) [13]разрешить службе взаимодействие с рабочим столом
Игорь Шевченко (2006-10-05 13:53:00) [14]Окно есть, только оно на другом десктопе. Я угадал ?
BiN (2006-10-05 13:30:00) [15]Единственное, что мне интересно, это как процесс запускается без инициализации STARTUPINFO.
clickmaker (2006-10-05 13:26:00) [16]а зачем запускать из службы блокнот?