一个独立的Delphi应用程序,也可以作为Windows服务安装

在Delphi中,您可以创build一个独立的Windows VCL Forms应用程序。 您也可以创build一个Windows服务应用程序。

是否可以将这两个应用程序合并为一个独立的应用程序,也可以作为Windows服务来安装?

完全可能。 诀窍是编辑.dpr来创建主窗体,当你想作为一个应用程序运行时,以及当你想作为一个服务运行的服务形式。 喜欢这个:

if SvComFindCommand('config') then begin //When run with the /config switch, display the configuration dialog. Forms.Application.Initialize; Forms.Application.CreateForm(TfrmConfig, frmConfig); Forms.Application.Run; end else begin SvCom_NTService.Application.Initialize; SvCom_NTService.Application.CreateForm(TscmServiceSvc, scmServiceSvc); SvCom_NTService.Application.Run; end; 

上面的代码使用SvCom来运行服务,但使用标准的TService可以达到完全相同的效果。

我写了一篇关于Delphi杂志多年前的文章。 你可以在这里阅读: 应用程序的许多面孔 。

这将是很难解释,但我会尝试:)

我已经完成了我的项目(德尔福5):

 program TestSvc; uses SvcMgr, SvcMain, //the unit for TTestService inherited from TService ... ; var IsDesktopMode : Boolean; function IsServiceRunning : Boolean; var Svc: Integer; SvcMgr: Integer; ServSt : TServiceStatus; begin Result := False; SvcMgr := OpenSCManager(nil, nil, SC_MANAGER_CONNECT); if SvcMgr = 0 then Exit; try Svc := OpenService(SvcMgr, 'TestService', SERVICE_QUERY_STATUS); if Svc = 0 then Exit; try if not QueryServiceStatus(Svc, ServSt) then Exit; Result := (ServSt.dwCurrentState = SERVICE_RUNNING) or (ServSt.dwCurrentState = SERVICE_START_PENDING); finally CloseServiceHandle(Svc); end; finally CloseServiceHandle(SvcMgr); end; end; begin if (Win32Platform <> VER_PLATFORM_WIN32_NT) or FindCmdLineSwitch('S', ['-', '/'], True) then IsDesktopMode := True else begin IsDesktopMode := not FindCmdLineSwitch('INSTALL', ['-', '/'], True) and not FindCmdLineSwitch('UNINSTALL', ['-', '/'], True) and not IsServiceRunning; end; if IsDesktopMode then begin //desktop mode Forms.Application.Initialize; Forms.Application.Title := 'App. Title'; ShowTrayIcon(Forms.Application.Icon.Handle, NIM_ADD); // This function for create an icon to tray. You can create a popupmenu for the Icon. while GetMessage(Msg, 0, 0, 0) do begin TranslateMessage(Msg); DispatchMessage(Msg); end; ShowTrayIcon(Forms.Application.Icon.Handle, NIM_DELETE); // for delete the tray Icon end else begin // Service mode SvcMgr.Application.Initialize; SvcMgr.Application.CreateForm(TTestService, TestService); SvcMgr.Application.Run; end; end. 

另一个几乎更简单的选项可以在http://cc.embarcadero.com/item/19703上找&#x5230; ,你只需要包含一个单元并将你的DPR改为如下所示:

 begin if CiaStartService('SERVICE NAME') then begin CiaService.CreateForm(TMain, Main); CiaService.Run; Exit; end; Application.Initialize; Application.Title := 'SERVICE NAME'; Application.CreateForm(TMain, Main); Application.Run; end. 

虽然这个例子现在已经过时了,但是这个技术非常简单,即使在Delphi XE2下也能正常工作。 有了这个,您的应用程序将继续作为非服务运行,直到您使用“ / install ”参数(在提升的命令提示符下)。 之后它将作为服务运行,直到您使用“ / uninstall ”参数(也在提升的命令提示符下)。

没有写一行代码就有解决这个问题的办法。 这取决于你的应用程序,但通常是可以实现的。 试试这个: http : //iain.cx/src/nssm 。 不要忘记启动应用程序所依赖的所有服务,然后才能将应用程序作为服务启动。 谷歌周围的信息如何做到这一点。

这是可能的,但在这种情况下,您不能使用正常的TServiceApplication和TService。 您应该自己实现所有服务特定的代码。

我们有一个类似的问题,并提出了两个框架的应用程序:一个是单独的沙,一个是服务。 现在我们可以创建一个嵌入到两个容器中的单个BPL / DLL。

如果你想花一些钱:你应该看看SvCOM,我认为他们有解决问题的办法。