Delphi 如何在运行时或安装后启动Windows服务

Delphi 如何在运行时或安装后启动Windows服务,delphi,windows-services,Delphi,Windows Services,历史 我正在构建一个Windows服务,作为平台应用程序的一部分来处理更新和服务器功能,因此它可以安装在不同于安装客户端应用程序的机器上。它使用UDP发送和接收广播消息,使用TCP处理更敏感和最重要的消息 客观的 我希望最终用户可以轻松安装我的应用程序,只需在计算机中复制可执行文件并执行它们即可。主应用程序应该验证用户是否是管理员,创建配置文件,然后安装Windows服务并运行它,这样非管理用户登录时,他们就不会收到我的应用程序关于管理权限的任何错误。目标是在不需要现有技术人员的情况下进行大多数

历史

我正在构建一个
Windows服务
,作为
平台应用程序的一部分
来处理更新和服务器功能,因此它可以安装在不同于安装
客户端应用程序
的机器上。它使用UDP发送和接收广播消息,使用TCP处理更敏感和最重要的消息

客观的

我希望最终用户可以轻松安装我的应用程序,只需在计算机中复制可执行文件并执行它们即可。主应用程序应该验证用户是否是管理员,创建配置文件,然后安装Windows服务并运行它,这样非管理用户登录时,他们就不会收到我的应用程序关于管理权限的任何错误。目标是在不需要现有技术人员的情况下进行大多数配置,因为数据库将是远程的

问题

使用命令
MyService.exe/install
正常安装我的服务,但它不会自动启动。启动它的唯一方法是继续
控制面板>管理工具>服务
并手动执行。我试图通过我的应用程序调用
net start MyService
,但我在shell中收到了
无效的服务名称
。我尝试了服务的
可执行名称
显示名称
对象名称
,但都不起作用。这是我的TService的目标:

object ServiceMainController: TServiceMainController
  OldCreateOrder = False
  OnCreate = ServiceCreate
  DisplayName = 'PlatformUpdateService'
  Interactive = True
  AfterInstall = ServiceAfterInstall
  AfterUninstall = ServiceAfterUninstall
  OnShutdown = ServiceShutdown
  OnStart = ServiceStart
  OnStop = ServiceStop
  Height = 210
  Width = 320 
问题:


我应该怎样做才能通过代码而不是用户的手来启动我的服务?如果我能在我的客户端应用程序中,或者在调用
OnServiceAfterInstall
后,自己执行,那将是最好的选择。

以下是
StartService
调用示例,在
AfterInstall
事件中:

procedure TServiceMainController.ServiceAfterInstall(Sender: TService);
var
  Manager, Service: SC_HANDLE;
begin
  Manager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  Win32Check(Manager <> 0);
  try
    Service := OpenService(Manager, PChar(Name), SERVICE_ALL_ACCESS);
    Win32Check(Service <> 0);
    try
      Win32Check(StartService(Service, 0, PChar(nil^)));
    finally
      CloseServiceHandle(Service);
    end;
  finally
    CloseServiceHandle(Manager);
  end;
end;
程序TServiceMainController.ServiceAfterInstall(发送方:TService);
变量
服务经理:SC_HANDLE;
开始
Manager:=OpenSCManager(无、无、SC\u Manager\u ALL\u访问);
Win32Check(管理器0);
尝试
服务:=OpenService(经理、PChar(名称)、服务\u所有访问权限);
Win32Check(服务0);
尝试
Win32Check(StartService(服务,0,PChar(nil^));
最后
CloseServiceHandle(服务);
结束;
最后
CloseServiceHandle(经理);
结束;
结束;

但是我不确定它是否适用于您,因为通常情况下,您应该也能成功地使用
网络启动

以下是
StartService
调用示例,在
AfterInstall
事件中:

procedure TServiceMainController.ServiceAfterInstall(Sender: TService);
var
  Manager, Service: SC_HANDLE;
begin
  Manager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  Win32Check(Manager <> 0);
  try
    Service := OpenService(Manager, PChar(Name), SERVICE_ALL_ACCESS);
    Win32Check(Service <> 0);
    try
      Win32Check(StartService(Service, 0, PChar(nil^)));
    finally
      CloseServiceHandle(Service);
    end;
  finally
    CloseServiceHandle(Manager);
  end;
end;
程序TServiceMainController.ServiceAfterInstall(发送方:TService);
变量
服务经理:SC_HANDLE;
开始
Manager:=OpenSCManager(无、无、SC\u Manager\u ALL\u访问);
Win32Check(管理器0);
尝试
服务:=OpenService(经理、PChar(名称)、服务\u所有访问权限);
Win32Check(服务0);
尝试
Win32Check(StartService(服务,0,PChar(nil^));
最后
CloseServiceHandle(服务);
结束;
最后
CloseServiceHandle(经理);
结束;
结束;


但是,我不确定它是否适用于您,因为通常情况下,您在
净启动
方面也会取得成功。

使用
净启动
时,您需要提供您在服务模块的
名称
属性中输入的唯一名称,这是默认的
Service1
.PS-我强烈建议不要在安装后事件中启动它。无论安装什么应用程序,它都应该是启动它的同一个应用程序。你看过InnoSetup吗?我会看看的。我也可以这样启动服务,您告诉我.net启动/停止应该与服务的
Name
DisplayName
一起工作(这两种服务都不是MyService BTW)。最好在'AfterInstall'中调用
StartService
。@SertacAkyuz确实,这是服务安装实现的问题。我自然会假设,如果InnoSetup这样的安装程序正在安装该服务,那么同一安装程序也应该负责启动该服务。当使用
net start
时,您需要提供您在服务模块的
name
属性中输入的唯一名称,这是默认的
Service1
.PS-我强烈建议不要在安装后事件中启动它。无论安装什么应用程序,它都应该是启动它的同一个应用程序。你看过InnoSetup吗?我会看看的。我也可以这样启动服务,您告诉我.net启动/停止应该与服务的
Name
DisplayName
一起工作(这两种服务都不是MyService BTW)。最好在'AfterInstall'中调用
StartService
。@SertacAkyuz确实,这是服务安装实现的问题。我自然会认为,如果像InnoSetup这样的安装程序正在安装服务,那么同一个安装程序也应该负责启动服务。+1但我不太关心bool casting。Win32Check(Manager0)怎么了?@David-谢谢!bool casting不会生成与比较不同的任何代码。但我喜欢它的原因是,它看起来更自然。不过没什么大不了的。依赖于实现细节对我来说似乎一点也不自然,但每个细节都有自己的。@DavidHeffernan我认为这取决于你的背景和你通常使用的语言,我个人同意你的看法,但是我现在主要是用delphi来开发本机的win32。Bool cast在Win64上是什么意思?我猜这是一个编译错误。文档说返回值为0表示失败,这是我要测试的队列。当然,当返回类型恰好是BOOL时,您可以将其视为boolean,即使BOOL发明时流行的C语言没有boolean类型。+1但我不太关心BOOL类型转换。Win32Check(Manager0)怎么了?@David-谢谢!bool casting不会生成与