Форум программистов, компьютерный форум, киберфорум
Delphi
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.59/82: Рейтинг темы: голосов - 82, средняя оценка - 4.59
92 / 59 / 8
Регистрация: 09.11.2011
Сообщений: 443

Сервисы или службы в delphi. Инсталл, деинсталл, запуск, остановка

14.06.2012, 08:11. Показов 15329. Ответов 2
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Написал программку для инсталляции и пуска, остановки и деинсталляции Сервиса.
Всё работает, но есть одна странность.
Когда делаю деинсталл, сервис хотя и умирает, но все еще виден в окне менеджера SCManager - "Службы(локальные)". Виден до тех пор пока я своё приложение не закрою, как только приложение, в котором я нажал кнопку "деинстал", закрылось - сервис деинсталлируется окончательно, и больше не виден в менеджере локальных Служб. Хотя видно, что он деинсталлируется, тк более недоступен для команд "Пуск" или "Останов". Нельзя также инсталлировать новый сервис с таким же именем, пока я программку не перезапущу.

Вопрос: почему не до конца происходит деинсталляция?

Ранее делал командами WinExec, все было четко.

Вот код:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
{***********************************************************
Инсталл сервиса
************************************************************}
function ServiceInstall:boolean;
var
  Service,SCManager: SC_HANDLE;
begin
 
   SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
   Service := CreateService(SCManager, ProgServiceName, ServiceName,
                              SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
                              SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
                              PathServiceExeFile,
                              nil, nil, '', nil, nil);
   case Service of
     0:   Result:=false;
     else Result:=true;
   end;
   CloseServiceHandle(SCManager);
end;
 
 
{***********************************************************
Старт сервиса
************************************************************}
function ServiceStart: Boolean;
var
  SCManager, Service: SC_HANDLE;
  P:PChar;
begin
  Result := False;
  SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if SCManager <> 0 then
  try
    Service := OpenService(SCManager, ProgServiceName, SERVICE_ALL_ACCESS);
    if Service <> 0 then
    try
      P:=nil;
      Result := StartService(Service, 0, P);
    finally
      CloseServiceHandle(Service);
    end;
  finally
    CloseServiceHandle(SCManager);
  end;
end;
 
 
{***********************************************************
Остановка сервиса
************************************************************}
function ServiceStop:boolean;
var Service,SCManager: SC_HANDLE;
    ss: SERVICE_STATUS;
begin
  SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  Service := OpenService(SCManager, ProgServiceName, SERVICE_ALL_ACCESS);
  Result:=ControlService(Service, SERVICE_CONTROL_STOP, ss);
  CloseServiceHandle(SCManager);
end;
 
 
{***********************************************************
Деинсталяция сервиса
************************************************************}
Function ServiceUninstall:boolean;
var Service,SCManager: SC_HANDLE;
    ss: SERVICE_STATUS;
begin
  SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  Service := OpenService(SCManager, ProgServiceName, SERVICE_ALL_ACCESS);
  ControlService(Service, SERVICE_CONTROL_STOP, ss);
  Result:=DeleteService(Service);
  CloseServiceHandle(SCManager);
end;
Добавлено через 16 часов 45 минут
Да , видимо тут такими вещами никто не занимается.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
14.06.2012, 08:11
Ответы с готовыми решениями:

Остановка и запуск службы(сервиса) из другой службы или из приложения не используя консоль
Добрый день! Компилятор Embarcadero XE8 Скажите, как можно остановить и запустить некую службу(сервис) зная его имя (например...

Запуск/остановка службы через ярлык
Как можно сделать запуск и остановку служб, чтобы не нужно было каждый раз заходить в &quot;Службы&quot; и запускать/останавливать их?

Удаленный запуск и остановка служб PsService: вне зависимости от состояние службы ERRORLEVEL всегда 1
Доброго дня Необходимо запуск и остановка служб Win XP удаленно. Имеется такой батник: @ECHO off start C:\psservice \\192.168.3.1...

2
 Аватар для raxper
10236 / 6614 / 498
Регистрация: 28.12.2010
Сообщений: 21,154
Записей в блоге: 1
14.06.2012, 09:24
...нет времени разбираться в вашем. Вот пример рабочего сервиса, дополнительно выполняющего функцию прокси

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
program proxi;
 
uses
  Windows, WinSvc,sysutils, classes, messages,
  IdBaseComponent, IdComponent, IdTCPServer, IdMappedPortTCP;
 
  
 type
  HUDP = class
    IdMappedPortTCP1: TIdMappedPortTCP;
 
 public
    constructor Create;
    destructor Destroy; override;
    procedure WMQueryEndSession(var Message: TWMQueryEndSession); message WM_QUERYENDSESSION;
 end;
 
const
  SERVICE_NAME = 'Proxi service';
  SERVICE_DISPLAY_NAME = 'Proxi';
  SERVICE_DISPLAY_TOTAL = 'http://raxp.radioliga.com';
 
var
  hSCM: SC_HANDLE;
  hService: SC_HANDLE;
  hServStatus: SERVICE_STATUS_HANDLE;
  status: SERVICE_STATUS;
  ServicesListFileName: string;
  hThread: HWND;
  ThID: Cardinal;
  //
  IdMappedPortTCP1: TIdMappedPortTCP;
  HUDP1: HUDP;
 
 
// ПРОКСИ ---------------------------------------------------------------------
procedure HUDP.WMQueryEndSession(var Message: TWMQueryEndSession);
begin
 inherited
end;
 
constructor HUDP.Create;
Begin
 inherited Create;
 
 IdMappedPortTCP1:= TIdMappedPortTCP.Create(nil);
 IdMappedPortTCP1.DefaultPort      := 808;
 IdMappedPortTCP1.MappedHost       := '192.168.0.56';
 IdMappedPortTCP1.MappedPort       := 8080;
 IdMappedPortTCP1.TerminateWaitTime:= 5000;
 IdMappedPortTCP1.Active:= true
end;
 
destructor HUDP.Destroy;
Begin
 IdMappedPortTCP1.Free;
 inherited Destroy
End;
// END ПРОКСИ -----------------------------------------------------------------
 
 
 
// CЕРВИС ---------------------------------------------------------------------
function UpperCase(st: string): string;  stdcall;
var i: integer;
begin
  result:= st;
  for i:= 1 to length(result) do
    if result[i] in ['a'..'z'] then result[i]:= Chr(Ord(result[i])-32)
    else result[i]:= result[i];
end;
 
 
function GetErrosString: string; stdcall;
var
  Len: Integer;
  Buffer: array[0..255] of Char;
begin
  Len:= FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ARGUMENT_ARRAY, nil,
                      GetLastError, 0, Buffer, SizeOf(Buffer), nil);
  while (Len > 0) and (Buffer[Len - 1] in [#0..#32]) do Dec(Len);
  SetString(Result, Buffer, Len);
end;
 
function IsInstalled: boolean; stdcall;
begin
 result:= false;
 try
 hSCM:= OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if hSCM <> 0 then begin
     hService:= OpenService(hSCM, SERVICE_NAME, SERVICE_QUERY_CONFIG);
     if hService <> 0 then begin
       CloseServiceHandle(hService);
       result:= true;
     end else ;
 
     CloseServiceHandle(hSCM);
  end;
 except end
end;
 
function Install: boolean; stdcall;
begin
  result:= true;
  if IsInstalled then exit;
 
  hSCM:= OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if hSCM = 0 then begin
    result:= false;
    exit;
  end;
 
  hService:= CreateService(
    hSCM, SERVICE_NAME, SERVICE_DISPLAY_NAME, SERVICE_ALL_ACCESS,
    SERVICE_WIN32_OWN_PROCESS or SERVICE_INTERACTIVE_PROCESS, SERVICE_AUTO_START,
    SERVICE_ERROR_NORMAL, PChar(ParamStr(0)), SERVICE_DISPLAY_TOTAL, nil, nil, nil, nil);
 
  if (hService = 0) then begin
    CloseServiceHandle(hSCM);
    result:= false;
    exit;
  end;
 
 //
 //
 
 CloseServiceHandle(hService);
 CloseServiceHandle(hSCM)
end;
 
function UnInstall: boolean; stdcall;
var status: SERVICE_STATUS;
begin
 if not IsInstalled then begin
  result:= true;
  exit
 end;
 
 result:= false;
 try
 
 hSCM:= OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
 if hSCM = 0 then begin
  exit
 end;
 
 hService:= OpenService(hSCM, SERVICE_NAME, SERVICE_ALL_ACCESS);
 if hService = 0 then begin
  CloseServiceHandle(hSCM);
  exit
 end;
 
 ControlService(hService, SERVICE_CONTROL_STOP, status);
 if DeleteService(hService) then result:= true;
 //
 CloseServiceHandle(hService);
 CloseServiceHandle(hSCM);
 
 except end
end;
 
function GetData: boolean; stdcall;
type
  TArrayEnumServicesStatus = array of TEnumServiceStatus;
const
  StatusText : array [SERVICE_STOPPED..SERVICE_PAUSED] of string =
  ('Stopped', 'Starting', 'Stopping', 'Started', 'Restarting', 'Pausing', 'Paused');
var
  EnumServiceStatus: Pointer;
  BytesAllocated, BytesNeeded, ServicesReturned, ResumeHandle : DWORD;
  i: Integer;
  bBol: boolean;
 
  fLog: THandle;
  BitesWriten: DWORD;
  Msg: string;
begin
  result:= false;
  ResumeHandle:= 0;
 
  hSCM:= OpenSCManager(nil, nil, GENERIC_READ or GENERIC_EXECUTE);
  if hSCM = 0 then begin
    exit;
  end;
 
  BytesAllocated:= 1024; //маловато будет нужен повтор
  GetMem(EnumServiceStatus, BytesAllocated);
  try
    bBol:= EnumServicesStatus(hSCM, SERVICE_TYPE_ALL, SERVICE_STATE_ALL, TEnumServiceStatus(EnumServiceStatus^),
                              BytesAllocated, BytesNeeded, ServicesReturned, ResumeHandle);
    if GetLastError = ERROR_MORE_DATA then begin
      BytesAllocated:= BytesNeeded;
      ReallocMem(EnumServiceStatus, BytesNeeded);
      bBol:= EnumServicesStatus(hSCM, SERVICE_TYPE_ALL, SERVICE_STATE_ALL, TEnumServiceStatus(EnumServiceStatus^),
                                BytesAllocated, BytesNeeded, ServicesReturned, ResumeHandle);
    end;
 
    if bBol then begin
      fLog:= CreateFile(PChar(ServicesListFileName), GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
 
      for i:= 0 to ServicesReturned - 1 do
      with TArrayEnumServicesStatus((@EnumServiceStatus)^)[i] do begin
        Msg:= lpServiceName + ' - ' + lpDisplayName +', '+ Statustext[ServiceStatus.dwCurrentState] + #13#10;
        WriteFile(fLog, Msg[1], Length(Msg), BitesWriten, nil);
      end;
 
      CloseHandle(fLog);
      result:= true;
    end;
    CloseServiceHandle(hSCM);
  finally
    FreeMem (EnumServiceStatus, BytesAllocated);
  end;
end;
 
function ReportStatusToSCMgr(dwCurrentState, dwWin32ExitCode, dwWaitHint: DWORD): boolean; stdcall;
begin
  if dwCurrentState = SERVICE_START_PENDING then status.dwControlsAccepted:= SERVICE_ACCEPT_SHUTDOWN
  else status.dwControlsAccepted:= SERVICE_ACCEPT_STOP or SERVICE_ACCEPT_SHUTDOWN or SERVICE_ACCEPT_PAUSE_CONTINUE;
 
  status.dwCurrentState:= dwCurrentState;
  status.dwWin32ExitCode:= dwWin32ExitCode;
  status.dwWaitHint:= dwWaitHint;
 
  if (dwCurrentState = SERVICE_RUNNING) or (dwCurrentState = SERVICE_STOPPED) then status.dwCheckPoint:= 0
  else inc(status.dwCheckPoint);
 
  result:= SetServiceStatus(hServStatus, status);
end;
 
procedure ServiceCtrlHandler(Opcode: Cardinal); stdcall;
begin
  case Opcode of
    SERVICE_CONTROL_STOP: begin
      if not ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0) then
      while (Status.dwCurrentState = SERVICE_STOP_PENDING) do sleep(100);
    end;
    SERVICE_CONTROL_PAUSE: begin
      ReportStatusToSCMgr(SERVICE_PAUSE_PENDING, NO_ERROR, 0);
      SuspendThread(hThread);
      ReportStatusToSCMgr(SERVICE_PAUSED, NO_ERROR, 0);
    end;
 
    SERVICE_CONTROL_CONTINUE: begin
      ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 0);
      ResumeThread(hThread);
      ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0);
    end;
 
    SERVICE_CONTROL_INTERROGATE: begin
      SetServiceStatus(hServStatus, status);
    end;
 
    SERVICE_CONTROL_SHUTDOWN: begin
      ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0);
      while (Status.dwCurrentState = SERVICE_STOP_PENDING) do sleep(100);
    end;
  end;
end;
 
function ServiceThread(P: Pointer): DWORD; stdcall;
var h: thandle;
    s: string;
begin
 if not ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0) then begin
  result:= GetLastError;
  exit
 end;
 
 try
  while (Status.dwCurrentState <> SERVICE_STOP_PENDING) do begin
   sleep(700);
 
   
   //---
 
 
  end;
  result:= 0
 finally Status.dwCurrentState:= SERVICE_STOP end
end;
 
procedure ServiceProc(argc : DWORD;var argv : array of PChar) stdcall;
begin
  Status.dwServiceType:= SERVICE_WIN32;
  Status.dwServiceSpecificExitCode:= 0;
 
  hServStatus:= RegisterServiceCtrlHandler(SERVICE_NAME, @ServiceCtrlHandler);
  if hServStatus = 0 then begin
    ReportStatusToSCMgr(SERVICE_STOPPED, GetLastError, 0);
    exit;
  end;
 
  if not ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 0) then begin
    exit;
  end;
 
  hThread:= CreateThread(nil, 0, @ServiceThread, nil, 0, ThID);
  WaitForSingleObject(hThread, INFINITE);
  CloseHandle(hThread);
 
  ReportStatusToSCMgr(SERVICE_STOPPED, NO_ERROR, 0);
end;
 
function Start: boolean; stdcall;
var
  ServTable: array [0..1] of SERVICE_TABLE_ENTRYA;
begin
  ServTable[0].lpServiceName:= SERVICE_NAME;
  ServTable[0].lpServiceProc:= @ServiceProc;
  ServTable[1].lpServiceName:= nil;
  ServTable[1].lpServiceProc:= nil;
  if not StartServiceCtrlDispatcher(ServTable[0]) then begin
    result:= false;
  end else result:= true;
end;
 
function RunService: boolean; stdcall;
var pParameters: PChar;
begin
 result:= false;
 //
 hSCM:= OpenSCManager(nil, nil, GENERIC_READ or GENERIC_EXECUTE);
 if hSCM = 0 then begin
  exit
 end;
 hService:= OpenService(hSCM, SERVICE_NAME, SERVICE_ALL_ACCESS);
 
 if hService = 0 then begin
  CloseServiceHandle(hSCM);
  exit
 end;
 
 StartService(hService, 0, pParameters);
 //
 CloseServiceHandle(hService);
 CloseServiceHandle(hSCM);
 result:= true
end;
 
begin
 HUDP1:= HUDP.Create;
 //
 ErrorLogFileName:= ParamStr(0);
 ErrorLogFileName:= Copy(ErrorLogFileName, 1, length(ErrorLogFileName)-3) + 'Log';
 ServicesListFileName:= Copy(ErrorLogFileName, 1, length(ErrorLogFileName)-3) + 'Txt';
 
 if ParamCount > 0 then begin
    if UpperCase(ParamStr(1)) = 'I' then begin
      if Install then begin
        RunService
      end;
    end;
 
    if UpperCase(ParamStr(1)) = 'U' then begin
      HUDP1.Destroy;
      UnInstall;
    end;
 
    if UpperCase(ParamStr(1)) = 'G' then begin
     GetData;
    end;
    exit;
  end;
 
 Start
// END CЕРВИС -----------------------------------------------------------------
 
end.
1
92 / 59 / 8
Регистрация: 09.11.2011
Сообщений: 443
02.11.2012, 11:12  [ТС]
Спасибо !!
Я объединил этот код со своим Ошибка 1053 типа нет ответа от службы
и получил что хотел! Разобраться бы еще!
Может ответите на пару вопросов?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
02.11.2012, 11:12
Помогаю со студенческими работами здесь

Delphi: переименовать службу, запуск 2-х экземпляров службы
Написал службу, в системе имя службы и отображаемое имя берется из параметров: Name и DisplayName. Стоит задача установить 2 (или...

Не запускаются сервисы и Msconfig из-за отключенной службы
Ребята,у меня важная проблема.Казалось бы очень известная проблема(Указанная служба не может быть запущена,поскольку она отклю......).делал...

D7, запуск службы из под службы, возможно ли такое?
Hello All. Необходимо написать службу которая будет через определенное время (каждые 5 минут) проверять существует (зарегистрирована) ли...

Остановка службы
Служба может быть остановлена системой по разным причинам: нехватка памяти, режим экономии энергии... А можно ли запретить остановку...

Остановка службы MSSQLSERVER
каждое утро в одно и тоже время служба останавливается привожу запись в об этом событии, скажите почему это происходит и как это исправить?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru