Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Остановить зависшую службу


Автор: neweraser 5.6.2018, 09:16
Доброго времени суток!
Суть в чем, есть программа, некая оболочка для запуска своих самописных служб. Если служба кривая (как и мои руки иногда) - бывают моменты, что она зависает на запуске в статусе "Start pending", помогает только ребут или следующие действия в cmd:
Код

sc queryex SERVICENAME
taskkill /PID PROCESS_PID_NNN /F

где PROCESS_PID_NNN - номер процесса для остановки.
В WinApi я не разбираюсь, использую готовые процедуры, например:
Код

function TMainForm.StopService(ServiceName: String): Boolean;
var
  hService, hSCM: Dword;
  svc_status: TServiceStatus;
begin
  Result:= True;
  hSCM:= OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if hSCM = 0 then
  begin
    Result:= False;
    MessageBox(handle, PChar('Для остановки службы нужны права администратора!'), PChar('Внимание!'), MB_OK + MB_ICONWARNING);
    Exit;
  end;
  hService:= OpenService(hSCM, PChar(ServiceName), SERVICE_ALL_ACCESS);
  if hService <> 0 then
  begin
    if not ControlService(hService, SERVICE_CONTROL_STOP, svc_status) then
    begin
      CloseServiceHandle(hService);
      CloseServiceHandle(hSCM);
      Result:= False;
      MessageBox(handle, PChar('Ошибка остановки службы!'), PChar('Внимание!'), MB_OK + MB_ICONWARNING);
      Exit;
    end;
  end else
  begin
    CloseServiceHandle(hSCM);
    Result:= False;
    MessageBox(handle, PChar('Ошибка открытия службы!'), PChar('Внимание!'), MB_OK + MB_ICONWARNING);
    Exit;
  end;
  CloseServiceHandle(hService);
  CloseServiceHandle(hSCM);
end;

Но приведенный выше код останавливает только корректно запущенную службу.
Есть ли какое-то решение на WinApi для остановки зависшей службы или мне смотреть в сторону cmd по PID процесса? Поиск не дал результатов, решения так и не нашел. 

Автор: navodri 5.6.2018, 12:15
Посмотри вот http://win32api-library.hol.es/. Там много пример на айпи. Может, что-то поможет.

Автор: neweraser 5.6.2018, 14:42
navodri, не нашел то что мне нужно, да и она немного платная. А вы всем на форуме ее рекомендуете?  smile 

Автор: Snowy 5.6.2018, 17:20
Ну раз сервис не отвечает, значит нужно его смертельно убивать насмерть.
Как-то так:
Код
type
  SC_HANDLE = Cardinal;
  SC_STATUS_TYPE=(SC_STATUS_PROCESS_INFO);
  SERVICE_STATUS_PROCESS = record
    dwServiceType: DWORD;
    dwCurrentState: DWORD;
    dwControlsAccepted: DWORD;
    dwWin32ExitCode: DWORD;
    dwServiceSpecificExitCode: DWORD;
    dwCheckPoint: DWORD;
    dwWaitHint: DWORD;
    dwProcessId: DWORD;
    dwServiceFlags: DWORD;
  end;
function QueryServiceStatusEx(hService: SC_HANDLE; InfoLevel: SC_STATUS_TYPE;
  var lpBuffer: SERVICE_STATUS_PROCESS; cbBufSize: DWORD; var pcbBytesNeeded: DWORD): BOOL; stdcall;
  external advapi32 name 'QueryServiceStatusEx';

// получить id процесса службы
function GetServiceProcessId(ServiceName: String; Status: DWORD = 0): THandle;
var
  hService, hSCM, d: Dword;
  scStatus: SERVICE_STATUS_PROCESS;
begin
  Result := 0;
  hSCM := OpenSCManager(nil, nil, SC_MANAGER_CONNECT);
  if hSCM > 0 then
  begin
    hService := OpenService(hSCM, PChar(ServiceName), SERVICE_QUERY_STATUS);
    if hService > 0 then
    begin
      d := SizeOf(scStatus);
      if QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, scStatus, d, d) then
      begin
        if (Status = 0) or (scStatus.dwCurrentState = Status) then
          Result := scStatus.dwProcessId;
      end;
    end;
  end;
end;


function TMainForm.StopService(ServiceName: String): Boolean;
var
  pid: THandle;
begin
  pid := GetServiceProcessId(ServiceName, SERVICE_START_PENDING);
  // pid := GetServiceProcessId(ServiceName); // если нам всё равно, висит он или нет
  if pid <> 0 then // если процесс есть и он висит 
    TerminateProcess(OpenProcess(PROCESS_TERMINATE, false, pid), 0); // убить его, если прав хватит
  Result := pid <> 0;
end;


По сути это и есть
sc queryex SERVICENAME
taskkill /PID PROCESS_PID_NNN

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)