gpt4 book ai didi

delphi - 如何在 Delphi for Windows 8 中启动 Windows 服务

转载 作者:行者123 更新时间:2023-12-02 13:32:16 24 4
gpt4 key购买 nike

我需要使用 Delphi Windows 应用程序启动一个服务。它在 Windows 7 中工作正常,但在 Windows 8.1 中无法工作。我使用了以下代码

function ServiceStart(sMachine,sService : string ) : boolean;
var
schm,schs : SC_Handle;
ss : TServiceStatus;
psTemp : PChar;
dwChkP : DWord;
begin
ss.dwCurrentState := 0;
schm := OpenSCManager(PChar(sMachine),Nil,SC_MANAGER_CONNECT);
if(schm > 0)then
begin
schs := OpenService(schm,PChar(sService),SERVICE_START or SERVICE_QUERY_STATUS);
if(schs > 0)then
begin
psTemp := Nil;
if(StartService(schs,0,psTemp))then
begin
if(QueryServiceStatus(schs,ss))then
begin
while(SERVICE_RUNNING <> ss.dwCurrentState)do
begin
dwChkP := ss.dwCheckPoint;
Sleep(ss.dwWaitHint);
if(not QueryServiceStatus(schs,ss))then
begin
break;
end;
if(ss.dwCheckPoint < dwChkP)then
begin
break;
end;
end;
end;
end;
CloseServiceHandle(schs);
end;
CloseServiceHandle(schm);
end;


Result := SERVICE_RUNNING = ss.dwCurrentState;
end;


procedure TForm1.BBSerStatusClick(Sender: TObject);
begin
ServiceStart('','SERVTEST');
end;

注意:SERVTEST是服务应用程序。谁能帮我?

最佳答案

我发现您正在使用从 here 复制的代码.

if(schm > 0)thenif(schs > 0)then应更改为if(schm <> 0)thenif(schs <> 0) then反而。这种情况下唯一的失败值为 0(某些 API 使用 INVALID_HANDLE_VALUE 代替,但 SCM API 不使用)。 任何其他值都是有效句柄。句柄并不是真正的整数(尽管 Delphi 如此声明它们),因此不应将它们视为整数。它们是任意值,不应被解释,而是应按原样使用。如果您没有返回实际的失败值(在本例中为 0),则无论实际返回的值如何,调用都是成功的。

ss.dwCurrentState的处理也有点偏了。而不是循环 while ss.dwCurrentState不是SERVICE_RUNNING , 循环 while ss.dwCurrentStateSERVICE_START_PENDING反而。如果出现问题并且服务永远不会进入 SERVICE_RUNNING状态,循环将永远运行,除非 QueryServiceStatus()本身失败了。我不建议依赖 ss.dwCheckPoint因为并非所有服务都正确实现它(事实上,Delphi 自己的 TService 没有 - 请参阅 QC #1006 TService.ReportStatus reports incorrect CheckPoint )。

尝试类似以下的操作。它区分 SCM API 失败和服务启动失败,而且还执行额外的错误检查来处理某些实际上不是 fatal error 的错误:

function ServiceStart(sMachine, sService : string) : Boolean;
var
schm, schs : SC_HANDLE;
ss : TServiceStatus;
begin
schm := OpenSCManager(PChar(sMachine), nil, SC_MANAGER_CONNECT);
if (schm = 0) then RaiseLastOSError;
try
schs := OpenService(schm, PChar(sService), SERVICE_START or SERVICE_QUERY_STATUS);
if (schs = 0) then RaiseLastOSError;
try
// NOTE: if you use a version of Delphi that incorrectly declares
// StartService() with a 'var' lpServiceArgVectors parameter, you
// can't pass a nil value directly in the 3rd parameter, you would
// have to pass it indirectly as either PPChar(nil)^ or PChar(nil^)
if not StartService(schs, 0, nil) then
begin
Result := ERROR_SERVICE_ALREADY_RUNNING = GetLastError();
if not Result then RaiseLastOSError;
Exit;
end;
repeat
if not QueryServiceStatus(schs, ss) then
begin
if (ERROR_SERVICE_NOT_ACTIVE <> GetLastError()) then RaiseLastOSError;
Result := False;
Exit;
end;
if (SERVICE_START_PENDING <> ss.dwCurrentState) then Break;
Sleep(ss.dwWaitHint);
until False;
Result := SERVICE_RUNNING = ss.dwCurrentState;
finally
CloseServiceHandle(schs);
end;
finally
CloseServiceHandle(schm);
end;
end;

或者,这里是 Microsoft 示例的(修改后的)版本,其中还包括服务位于 SERVICE_STOP_PENDING 中的处理。启动之前的状态(我删除了超时逻辑,因为它基于 dwCheckPoint 处理):

Starting a Service :

function ServiceStart(sMachine, sService : string) : Boolean;
var
schSCManager,
schService : SC_HANDLE;
ssStatus : TServiceStatus;
begin
// Get a handle to the SCM database.

schSCManager := OpenSCManager(PChar(sMachine), nil, SC_MANAGER_CONNECT);
if (schSCManager = 0) then RaiseLastOSError;
try
// Get a handle to the service.

schService := OpenService(schSCManager, PChar(sService), SERVICE_START or SERVICE_QUERY_STATUS);
if (schService = 0) then RaiseLastOSError;
try
// Check the status in case the service is not stopped.

if not QueryServiceStatus(schService, ssStatus) then
begin
if (ERROR_SERVICE_NOT_ACTIVE <> GetLastError()) then RaiseLastOSError;
ssStatus.dwCurrentState := SERVICE_STOPPED;
end;

// Check if the service is already running

if (ssStatus.dwCurrentState <> SERVICE_STOPPED) and ssStatus.dwCurrentState <> SERVICE_STOP_PENDING) then
begin
Result := True;
Exit;
end;

// Wait for the service to stop before attempting to start it.

while (ssStatus.dwCurrentState = SERVICE_STOP_PENDING) do
begin
// Do not wait longer than the wait hint. A good interval is
// one-tenth of the wait hint but not less than 1 second
// and not more than 10 seconds.

dwWaitTime := ssStatus.dwWaitHint div 10;

if (dwWaitTime < 1000) then
dwWaitTime := 1000
else if (dwWaitTime > 10000) then
dwWaitTime := 10000;

Sleep(dwWaitTime);

// Check the status until the service is no longer stop pending.

if not QueryServiceStatus(schService, ssStatus) then
begin
if (ERROR_SERVICE_NOT_ACTIVE <> GetLastError()) then RaiseLastOSError;
Break;
end;
end;

// Attempt to start the service.

// NOTE: if you use a version of Delphi that incorrectly declares
// StartService() with a 'var' lpServiceArgVectors parameter, you
// can't pass a nil value directly in the 3rd parameter, you would
// have to pass it indirectly as either PPChar(nil)^ or PChar(nil^)
if not StartService(schService, 0, nil) then RaiseLastOSError;

// Check the status until the service is no longer start pending.

if not QueryServiceStatus(schService, ssStatus) then
begin
if (ERROR_SERVICE_NOT_ACTIVE <> GetLastError()) then RaiseLastOSError;
ssStatus.dwCurrentState := SERVICE_STOPPED;
end;

while (ssStatus.dwCurrentState = SERVICE_START_PENDING) do
begin
// Do not wait longer than the wait hint. A good interval is
// one-tenth the wait hint, but no less than 1 second and no
// more than 10 seconds.

dwWaitTime := ssStatus.dwWaitHint div 10;

if (dwWaitTime < 1000) then
dwWaitTime := 1000
else if (dwWaitTime > 10000) then
dwWaitTime := 10000;

Sleep(dwWaitTime);

// Check the status again.

if not QueryServiceStatus(schService, ssStatus) then
begin
if (ERROR_SERVICE_NOT_ACTIVE <> GetLastError()) then RaiseLastOSError;
ssStatus.dwCurrentState := SERVICE_STOPPED;
Break;
end;
end;

// Determine whether the service is running.

Result := (ssStatus.dwCurrentState = SERVICE_RUNNING);
finally
CloseServiceHandle(schService);
end;
finally
CloseServiceHandle(schSCManager);
end;
end;

关于delphi - 如何在 Delphi for Windows 8 中启动 Windows 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30506369/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com