在Delphi中,您可以創建一個獨立的Windows VCL Forms應用程序。您還可以創建Windows服務應用程序。一個獨立的Delphi應用程序,也可以安裝爲Windows服務
是否可以將這兩者組合成一個單獨的應用程序,它可以作爲獨立應用程序運行,也可以作爲Windows服務來安裝?
在Delphi中,您可以創建一個獨立的Windows VCL Forms應用程序。您還可以創建Windows服務應用程序。一個獨立的Delphi應用程序,也可以安裝爲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實現完全一樣的效果。
我寫了一篇關於多年前德爾福雜誌的文章。你可以在這裏閱讀:Many Faces Of An Application。
這是可能的,但在這種情況下,您不能使用正常的TServiceApplication和TService。你應該自己實現所有服務特定的代碼。
我們有一個similat問題,並提出了兩個框架應用程序:一個用於單獨的沙EX和一個用於服務。現在我們可以創建一個嵌入到兩個容器中的單個BPL/DLL。
如果你想花一些錢:你應該看看SvCOM,我認爲他們有解決問題的辦法。
這將是很難解釋,但我會試試:)
我已經在我的項目一樣,做到了(德爾福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://iain.cx/src/nssm。不要忘記啓動您的應用程序所依賴的所有服務,然後才能將您的應用程序作爲服務啓動。谷歌圍繞如何做到這一點的信息。
另一個差不多簡單的選擇可在http://cc.embarcadero.com/item/19703,你只需要包括單位和改變你的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」參數(在提升的命令提示符下)。之後它將作爲服務運行,直到您使用「/卸載」參數(同樣在提升的命令提示符下)。
是否可以創建一個'{$ DEFINE}'全局編譯來識別它是在standlone還是windows服務模式下運行? – dipold 2015-09-15 18:24:44
這個單元是什麼'SvCom_NTService'? – 2018-01-18 23:01:45
http://www.aldyn-software.com/svcom.html – gabr 2018-01-19 10:55:35