小生负责公司的WINDOWS NT服务层编程,在写完服务程序后,日前在写控制程序的时候发现一个极其古怪的问题,就是如果我CreateService之后没有关闭,那么OpenService要么返回的是0,要么就返回的值和CreateService不一样,并由此导致DeleteService删除对象之后无法在当前控制程序中再次安装服务(服务和控制程序是独立的实体),除非退出控制程序并重启。因为在
CreateService->OpenService->DeleteService->CloseServiceHandle会导致服务状态变成“已禁用”但没有被删除,程序关闭后,服务被删除
CreateService->CloseServiceHandle->OpenService->DeleteService->CloseServiceHandle完全成功
代码如下
procedure TFrmMain.InstallBtnClick(Sender: TObject);
var
P: PChar;
begin
hSCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
if hSCManager = 0 then
// didn't work, maybe we asked for too many access rights?
hSCManager := OpenSCManager(nil, nil, 0);
if hSCManager <> 0 then
begin
hService := CreateService(
hSCManager, // SCManager database
PChar(ServiceNameEdit.Text), // name of service
PChar(DisplayEdit.Text), // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_SHARE_PROCESS, // service type
SERVICE_AUTO_START, // start type
SERVICE_ERROR_NORMAL, // error control type
PChar(ProviderEdit.Text), // service's binary
nil, // no load ordering group
nil, // no tag identifier
nil, // no dependencies
nil, // LocalSystem account
nil); // no password
CloseServiceHandle(hSCManager);
if hService <> 0 then
begin
P := PChar(DescrEdit.Text);
ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, @P);
if StartService(hService, 0, PChar(nil^)) then
begin
CloseServiceHandle(hService);/////////这里如果我不关闭掉这个全局句柄,点卸载按钮的时候就会产生奇怪的现象,服务程序状态为已禁用,而控制程序关闭后,服务程序就被卸载了
MessageBox(0, 'Install Service successed', 'Congratulation...', MB_ICONINFORMATION);
end;
end;
end;
end;procedure TFrmMain.UninstallBtnClick(Sender: TObject);
var
hSConfig: DWORD;
lpSConfig: PQueryServiceConfig;
ServiceStatus: TServiceStatus;
ConfigError: boolean;
begin
hSCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
if hSCManager = 0 then hSCManager := OpenSCManager(nil, nil, 0);
if hSCManager <> 0 then
begin
hService := OpenService(hSCManager, PChar(ServiceNameEdit.Text), SERVICE_ALL_ACCESS or _DELETE);
CloseServiceHandle(hSCManager);
if hService <> 0 then
begin
ConfigError := False;
hSConfig := 0;
QueryServiceConfig(hService, nil, 0, hSConfig);
if hSConfig <> 0 then
begin
lpSConfig := Pointer(LocalAlloc(LPTR, hSConfig * 2));
ConfigError := QueryServiceConfig(hService, lpSConfig, hSConfig * 2, hSConfig) and
((lpSConfig^.dwServiceType = SERVICE_WIN32_SHARE_PROCESS) and
(lpSConfig^.dwStartType = SERVICE_AUTO_START) and
(IsTextEqual(lpSConfig^.lpDisplayName, PChar(DisplayEdit.Text))));
LocalFree(DWORD(lpSConfig));
end;
if not ControlService(hService, SERVICE_CONTROL_INTERROGATE, ServiceStatus) then
ServiceStatus.dwCurrentState := SERVICE_STOPPED;
if (ConfigError) and (ServiceStatus.dwCurrentState = SERVICE_RUNNING) then
begin
// the parameters are correct, so we try to stop and remove it
if ControlService(hService, SERVICE_CONTROL_STOP, ServiceStatus) then
begin
if DeleteService(hService) then
begin
CloseServiceHandle(hService);
MessageBox(0, 'The service is removed again', 'information...', MB_ICONINFORMATION);
end
else
MessageBox(0, 'The service is stopped, but removing failed', 'warning...', MB_ICONWARNING);
end
else
MessageBox(0, 'Stopping failed', 'warning...', MB_ICONWARNING);
end
else
begin
if not ConfigError then
// not all parameters are correct, so we try to correct them
if ChangeServiceConfig(hService, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
arrCh, nil, nil, nil, nil, nil, PChar(DisplayEdit.Text)) then
MessageBox(0, 'Correction of service parameters succeeded', 'information...', MB_ICONINFORMATION)
else
MessageBox(0, 'Correction of service parameters failed', 'warning...', MB_ICONWARNING);
end;
end;
end;
end;
CreateService->OpenService->DeleteService->CloseServiceHandle会导致服务状态变成“已禁用”但没有被删除,程序关闭后,服务被删除
CreateService->CloseServiceHandle->OpenService->DeleteService->CloseServiceHandle完全成功
代码如下
procedure TFrmMain.InstallBtnClick(Sender: TObject);
var
P: PChar;
begin
hSCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
if hSCManager = 0 then
// didn't work, maybe we asked for too many access rights?
hSCManager := OpenSCManager(nil, nil, 0);
if hSCManager <> 0 then
begin
hService := CreateService(
hSCManager, // SCManager database
PChar(ServiceNameEdit.Text), // name of service
PChar(DisplayEdit.Text), // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_SHARE_PROCESS, // service type
SERVICE_AUTO_START, // start type
SERVICE_ERROR_NORMAL, // error control type
PChar(ProviderEdit.Text), // service's binary
nil, // no load ordering group
nil, // no tag identifier
nil, // no dependencies
nil, // LocalSystem account
nil); // no password
CloseServiceHandle(hSCManager);
if hService <> 0 then
begin
P := PChar(DescrEdit.Text);
ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, @P);
if StartService(hService, 0, PChar(nil^)) then
begin
CloseServiceHandle(hService);/////////这里如果我不关闭掉这个全局句柄,点卸载按钮的时候就会产生奇怪的现象,服务程序状态为已禁用,而控制程序关闭后,服务程序就被卸载了
MessageBox(0, 'Install Service successed', 'Congratulation...', MB_ICONINFORMATION);
end;
end;
end;
end;procedure TFrmMain.UninstallBtnClick(Sender: TObject);
var
hSConfig: DWORD;
lpSConfig: PQueryServiceConfig;
ServiceStatus: TServiceStatus;
ConfigError: boolean;
begin
hSCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
if hSCManager = 0 then hSCManager := OpenSCManager(nil, nil, 0);
if hSCManager <> 0 then
begin
hService := OpenService(hSCManager, PChar(ServiceNameEdit.Text), SERVICE_ALL_ACCESS or _DELETE);
CloseServiceHandle(hSCManager);
if hService <> 0 then
begin
ConfigError := False;
hSConfig := 0;
QueryServiceConfig(hService, nil, 0, hSConfig);
if hSConfig <> 0 then
begin
lpSConfig := Pointer(LocalAlloc(LPTR, hSConfig * 2));
ConfigError := QueryServiceConfig(hService, lpSConfig, hSConfig * 2, hSConfig) and
((lpSConfig^.dwServiceType = SERVICE_WIN32_SHARE_PROCESS) and
(lpSConfig^.dwStartType = SERVICE_AUTO_START) and
(IsTextEqual(lpSConfig^.lpDisplayName, PChar(DisplayEdit.Text))));
LocalFree(DWORD(lpSConfig));
end;
if not ControlService(hService, SERVICE_CONTROL_INTERROGATE, ServiceStatus) then
ServiceStatus.dwCurrentState := SERVICE_STOPPED;
if (ConfigError) and (ServiceStatus.dwCurrentState = SERVICE_RUNNING) then
begin
// the parameters are correct, so we try to stop and remove it
if ControlService(hService, SERVICE_CONTROL_STOP, ServiceStatus) then
begin
if DeleteService(hService) then
begin
CloseServiceHandle(hService);
MessageBox(0, 'The service is removed again', 'information...', MB_ICONINFORMATION);
end
else
MessageBox(0, 'The service is stopped, but removing failed', 'warning...', MB_ICONWARNING);
end
else
MessageBox(0, 'Stopping failed', 'warning...', MB_ICONWARNING);
end
else
begin
if not ConfigError then
// not all parameters are correct, so we try to correct them
if ChangeServiceConfig(hService, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
arrCh, nil, nil, nil, nil, nil, PChar(DisplayEdit.Text)) then
MessageBox(0, 'Correction of service parameters succeeded', 'information...', MB_ICONINFORMATION)
else
MessageBox(0, 'Correction of service parameters failed', 'warning...', MB_ICONWARNING);
end;
end;
end;
end;
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货