Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Console Application Install as Service

I'm looking and trying to install my console application as service but not figured out how to do it.

any recommendation ?

actually i just wanted to install as service and start automatically each time windows starts or delay start

program Project1;

  Uses
  Windows,
  SysUtils,
  Dialogs,
  Messages,TlHelp32,Classes, Graphics, Controls, SvcMgr,ExtCtrls;

 Const
  SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
  SECURITY_BUILTIN_DOMAIN_RID = $00000020;
  DOMAIN_ALIAS_RID_ADMINS = $00000220;

  type
  TService1 = class(TService)
  private
  public
    function GetServiceController: TServiceController; override;
  end;


  var
  Service1: TService1;
  Msg: TMsg;

 Procedure ServiceController(CtrlCode: DWord); stdcall;
  begin
   Service1.Controller(CtrlCode);
 end;


 Function TService1.GetServiceController: TServiceController;
  begin
    Result := ServiceController;
 end;

Function IsAdmin: Boolean;
var
  hAccessToken: THandle;
  ptgGroups: PTokenGroups;
  dwInfoBufferSize: DWORD;
  psidAdministrators: PSID;
  x: Integer;
  bSuccess: BOOL;
begin
  Result   := False;
  bSuccess := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True,
    hAccessToken);
  if not bSuccess then
  begin
    if GetLastError = ERROR_NO_TOKEN then
      bSuccess := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY,
        hAccessToken);
  end;
  if bSuccess then
  begin
    GetMem(ptgGroups, 1024);
    bSuccess := GetTokenInformation(hAccessToken, TokenGroups,
      ptgGroups, 1024, dwInfoBufferSize);
    CloseHandle(hAccessToken);
    if bSuccess then
    begin
      AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2,
        SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
        0, 0, 0, 0, 0, 0, psidAdministrators);
      {$R-}
      for x := 0 to ptgGroups.GroupCount - 1 do
        if EqualSid(psidAdministrators, ptgGroups.Groups[x].Sid) then
        begin
          Result := True;
          Break;
        end;
      {$R+}
      FreeSid(psidAdministrators);
    end;
    FreeMem(ptgGroups);
  end;
end;

begin

 if IsAdmin then
   begin
                 // Install me as service 
   end else
 begin
    ShowMessage('Not Running As Admin');
 end;


  while GetMessage(Msg, 0, 0, 0) do
   begin
   TranslateMessage(Msg);
   DispatchMessage(Msg);
  end;

end.
like image 771
user1023395 Avatar asked Mar 18 '26 15:03

user1023395


2 Answers

There are at least two ways: one of these is the 'right' way, and one is 'wrong' (but works.)

The wrong-but-works way

You can run any application as a service through (host) helper utilities, such as:

  • ServiceEx, "a freeware Windows application that allows a normal program to run as a Windows service". I have never used this, I just found it through Googling.
  • One of two utilities Microsoft provides (Since it's from MS, I would use this one.)

Why is this the wrong way? Because if you want your application to run as a service, you should create a service app. And it just so happens that that's very easy with Delphi. This is the right way:

The right way: create a service app

This delphi.about.com article has a lot of information about service applications. However, it's fairly simple: create a new service application through File > New > [perhaps Other >] Service Application. Set the display name etc. To install it, run with the command line switch /install; to uninstall run with /uninstall.

If the reason you want your command-line app to run as a service is because you don't want to write two applications, with good design you can minimise the extra work. In your project group have two applications, your command-line app and your service app. Then share the code in other files - i.e. write the code to do your app's work once, and include / call it from both projects.

like image 59
David Avatar answered Mar 21 '26 04:03

David


A TService need a TServiceApplication to create and run it, just like a TForm need a TApplication to create and run it.

Application.Initialize;
Application.CreateForm(TService1, TService1);
Application.Run;

Of cause with the TServiceApplication it is no longer console application.

As far as I know, if you really want to write console service, you need to skip TService and use almost purely Window API to achieve Console Service.

There is an old example with explanation in the web : NT Service and Console Application

Quote from that article:

Delphi compiler support developing the NT services using TServiceApplication and TService classes. But Delphi approach does not support dual interface and brings very much of overhead. I show how to write lightweight dual interface service application using Windows API function. Even example application is written in Delphi it is very easy to port to another compiler since only native API functions are used.

I would say making a Delphi TServiceApplication is much more easier...

like image 21
Justmade Avatar answered Mar 21 '26 03:03

Justmade



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!