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不会生成与