Recent

Author Topic: Run application as a service or as a GUI application via command line parameters  (Read 5332 times)

JD

  • Hero Member
  • *****
  • Posts: 1847
Hi there everyone,

I have an existing GUI application server on a network that handles client requests. I would like to modify this server such that it can be run as a service or as the usual GUI application just by launching it with the appropriate command line parameters. 

This is where I need some assistance because I do not develop console applications.

I would appreciate your kind assistance.

Cheers,

JD
Windows (10) - Lazarus 2.1/FPC 3.2 (svn 64160 built using fpcupdeluxe),
Linux Mint - Lazarus 2.1/FPC 3.2 (svn 64380 built using fpcupdeluxe),
Delphi

Indy 10.6 series; mORMot; Zeos 7.3; SQLite, Firebird, PostgreSQL & MariaDB; VirtualTreeView 5.5.3 R1

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1975
  • Former Delphi 1-7, 10.2 user
See the Wiki article: Daemons and Services.
Lazarus 2.3, FPC 3.3.1 macOS 12.3.1 x86_64 Xcode 13.4
Lazarus 2.3, FPC 3.3.1 macOS 12.3.1 aarch64 Xcode 13.4

Warfley

  • Hero Member
  • *****
  • Posts: 814
This is not that easy, at least for Windows, because on Windows GUI applications and Services are structured differently and handled differently by the OS.
On Unix this is a different story, because there is no OS level difference between a GUI application and a Daemon, as a GUI application is just an application that calls drawing routines, while a daemon is just an application that doesnt.

What you could do is to write two programs, a Service and a GUI. The service is always executed and runs in the background, while the GUI just connects to the service and interacts with it (e.g. through IPC)

Thaddy

  • Hero Member
  • *****
  • Posts: 11517
What you could do is to write two programs, a Service and a GUI. The service is always executed and runs in the background, while the GUI just connects to the service and interacts with it (e.g. through IPC)
Indeed, and that is usually how it should be done (not only on Windows, but also on Linux (rights))
1) a Controlling app with a Userinterface
2) a Daemon/Service that has no userinterface and is optionally controlled by the Controller.

Note that 1. is not strictly necessary if one uses Daemon start-up options and/or config files, depends on purpose.
This goes for both Daemons/Services on Windows and Linux.
And I disagree about this being difficult: it is not. It may be that most programmers do not often write Daemons/Services.
The example in the manual is a good starting point.
« Last Edit: January 29, 2022, 08:17:10 am by Thaddy »
Путин преступник. Россияне дезинформированы.

Warfley

  • Hero Member
  • *****
  • Posts: 814
And I disagree about this being difficult: it is not. It may be that most programmers do not often write Daemons/Services.
The example in the manual is a good starting point.
This wasn't meant to be to the "solution" of two applications, the "this is not that easy" was specifically for the 2 in one solution, because while there might be a solution for Windows, it would be hacky as hell.
Creating two applications isn't that hard, but it can be tideous to implement all the controlling functionality through IPC (as you basically have to define a fully fledged communication interface that covers all usecases, this is much more effort than just accessing the datastructures directly)

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1099
    • Lebeau Software
This is not that easy, at least for Windows, because on Windows GUI applications and Services are structured differently and handled differently by the OS.

It is not THAT hard, though.  It is just a matter of which API the application uses at runtime.  For instance, when running as a GUI, using a standard TForm.  When running as a service, using a TService (Delphi) or TDaemon (FPC).  In my Delphi VCL service+GUI apps, I use the SvCom framework to handle this difference for me, but it is not very hard to do it manually.
« Last Edit: January 31, 2022, 06:29:35 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

Zvoni

  • Hero Member
  • *****
  • Posts: 1185
Depending on what that application-server is doing:
Don't forget, that a service/daemon can be setup to run without a user-context (e.g. DB-Server which runs, despite no user being logged-in)
a GUI-App requires a logged-in User resp. a Desktop-Session
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1099
    • Lebeau Software
Don't forget, that a service/daemon can be setup to run without a user-context (e.g. DB-Server which runs, despite no user being logged-in)
a GUI-App requires a logged-in User resp. a Desktop-Session

On Windows, there is no such thing as a user-less process, or a session-less process.  All processes run under a user account and a session, even services.  They always run under Session 0, and under the LocalSystem account by default unless specified differently.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

Zvoni

  • Hero Member
  • *****
  • Posts: 1185
Remy, agreed.
Wasn‘t precise enough (more in „common“ terms)
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

JD

  • Hero Member
  • *****
  • Posts: 1847
Hi there everyone,

Thanks a lot for your advice and contributions.

Taken inspiration from this post: https://forum.lazarus.freepascal.org/index.php/topic,20274.msg430834.html#msg430834, I have built a skeletal Service application.

However even without functioning code, I am having memory leaks. And I cannot find the problem.

I attached the published project which was created from the template for the standard Daemon (service) application in the Lazarus IDE.

I would appreciate your help to locate the memory leaks.

Cheers,

JD
Windows (10) - Lazarus 2.1/FPC 3.2 (svn 64160 built using fpcupdeluxe),
Linux Mint - Lazarus 2.1/FPC 3.2 (svn 64380 built using fpcupdeluxe),
Delphi

Indy 10.6 series; mORMot; Zeos 7.3; SQLite, Firebird, PostgreSQL & MariaDB; VirtualTreeView 5.5.3 R1

Zvoni

  • Hero Member
  • *****
  • Posts: 1185
Is it just me?
I have never seen the heaptrc-unit in a Uses-clause..... (in OP's case in the lpr-file)
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

JD

  • Hero Member
  • *****
  • Posts: 1847
Is it just me?
I have never seen the heaptrc-unit in a Uses-clause..... (in OP's case in the lpr-file)

It is needed by SetHeapTraceOutput.

JD
Windows (10) - Lazarus 2.1/FPC 3.2 (svn 64160 built using fpcupdeluxe),
Linux Mint - Lazarus 2.1/FPC 3.2 (svn 64380 built using fpcupdeluxe),
Delphi

Indy 10.6 series; mORMot; Zeos 7.3; SQLite, Firebird, PostgreSQL & MariaDB; VirtualTreeView 5.5.3 R1

DonAlfredo

  • Hero Member
  • *****
  • Posts: 1540
You might put heaptrc as first unit in your uses clause ?

Zvoni

  • Hero Member
  • *****
  • Posts: 1185
It is needed by SetHeapTraceOutput.

JD
??????
Quote
Warning: Do not add the Heaptrc unit manually. The Heaptrc unit needs to be loaded before Lineinfo and only the compiler can do that. Heaptrc is also a memory manager, so do not try to use any memory manager – including Heaptrc itself – in the uses clause, because that may lead to memory corruption and false results. This topic contains a note with example code to handle such a case in a generic way.
And for the TraceOutput: Just do a {$IFDEF UseHeapTrace}SetHeapTraceOutput('Trace.log');{$ENDIF}
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Thaddy

  • Hero Member
  • *****
  • Posts: 11517
You might put heaptrc as first unit in your uses clause ?
What have you been drinking this weekend... Of course not! See the docs and the wiki. NEVER add heaptrc as a unit yourself. And you of all people know that.
Путин преступник. Россияне дезинформированы.

 

TinyPortal © 2005-2018