2

Pre-amble: I use Lazarus 1.2.6 and Freepascal 2.6.4 on Windows 7 and my solution must be based on that - not C or C++. I could use Delphi though, if something similar exists for that.

Problem: I wish to create a small program that is ideally launched from the command line, but then just runs in the background without the need for the console application to be open visibly.

I'm trying to work out how best to achieve it.

I read this link and this link and this C based example and this Linux example but as one user points out "if you don't want a console application, don't make one", which begs the question of what are the other ways? If you don't want a GUI, and you don't want a console, I assume there's another way to create a silent program, then launch it, and then just have it run in the background? Preseumbly as a service or some such?

Or, the other way that occured to me is to create a Library (which generates a DLL when compiled of course) that contains my programs functions, export those functions at the end of the DLL, then call them from a seperate terminal application which, I assume, I could then close but the functions that are called from the DLL might continue to run? In other words - two programs - one terminal program to launch the other non-visible program and then close the launching program? Is that possible or recommended?

Community
  • 1
  • 1
Gizmo_the_Great
  • 979
  • 13
  • 28
  • 1
    If you don't want either a Console or GUI app, the solution is to still make a GUI app but just without showing one (for example how tray icons work). These are background processes. Or, you could write a Windows Service. – Jerry Dodge Feb 02 '15 at 17:00
  • I dno't know if you downvoted it for that, but if you did, can I say this: I made it quite clear that I am using Windows and developing a Windows application. I make no reference to creating it for other platforms. The "Linux example" was just another thread that covers the same sort of subject so I linked it in to be helpful to other readers. I get fed up when people downvoting questions that are sometimes asked, for the very reason of not understanding something very well, and then they get downvoted for not being precise. – Gizmo_the_Great Feb 02 '15 at 18:05
  • Forgive me for not being fully versed in all the various strands of programming that exist. – Gizmo_the_Great Feb 02 '15 at 18:28
  • @Gizmo_the_Great, you may want to lose sarcasm as well. No one will downvote you if you do some research and get a minimal understanding of the problem you are interested in. – Free Consulting Feb 02 '15 at 19:16

4 Answers4

3

I've written about this topic before, but not specifically with regard to Delphi or Free Pascal.

Use the {$APPTYPE GUI} directive to tell the compiler to generate a GUI application rather than a console application. You'd generally put it near the top of your main project file, where the program statement is. When you use that directive, the program will neither inherit the console of its parent nor create a new console. If you don't actually want a GUI, then don't display any windows; if you have a console application, the OS creates the console for you automatically because "consoleness" is a property of the EXE file.

Using a separate program and DLL won't have the effect you're looking for. As you already know, functions block the caller until they return. Therefore, when the host program calls your DLL function, it will wait until it returns before exiting. A DLL is not a separate program; it can't run without its host. (Using a separate thread won't work, either, because when the main thread terminates the program, it destroys all other threads whether they're finished or not.)

Community
  • 1
  • 1
Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • Linker, not compiler. Worth to mention what this behaviour in Delphi also controlled by "generate console application" in the "linker options" or `-cc` command line switch. – Free Consulting Feb 02 '15 at 18:02
  • -1 : do you reply to " I wish to create a small program that is ideally launched from the command line, but then just runs in the background without the need for the console application to be open visibly" ? Do you give a simple solution to the question ? – Abstract type Feb 05 '15 at 03:42
  • My answer *is* a simple solution, @Bbaz. Here's a full program: `program Foo; {$APPTYPE GUI} begin end.` It doesn't have a console, and it doesn't block the command prompt from taking further commands. From the parent process's perspective, it will run "in the background." – Rob Kennedy Feb 05 '15 at 04:19
1

If you don't want a console application, don't make one.

That sounds like something that I might have said!! And yes, that's the way to deal with this. When one console application starts another one, the parent process blocks until the child completes. You can arrange for the child process to break away from its parent's console, but then you'll just end up with two consoles.

What you really want to do is create a process that targets the GUI subsystem rather than the console subsystem. In other words, you don't want a console application, so don't make one. Make a GUI application instead.

Now, a GUI application doesn't mean that you have to show GUI. There's no compunction to do so. You have a process to break away, execute in the background, not attach to the parent console. That's an application that targets the GUI subsystem but does not show any GUI.

For example, this program targets the GUI subsystem, but shows no GUI. It's rather useless because it blocks indefinitely. However, you'd replace that with your background task.

program project1;
{$apptype gui}
uses
  windows;
begin
  Sleep(INFINITE);
end.
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Thanks David. Yes - I think it was your quote! Using Lazarus, do you know how to "create an application that targets the GUI subsystem but does not show any GUI"? The only options, when creating a new project, are 'Application' (traditional GUI), 'Program' (basic terminal program), 'Console Program' (terminal program with enhanced features), 'Library' (a DLL) , an 'InstantFPC Program' and lastly, FPC Unit. When creating a traditional Application using Lazarus, there's a mode at the top that says "{$mode objfpc}{$H+}", – Gizmo_the_Great Feb 02 '15 at 17:30
  • **'Application' (traditional GUI)** appears to be the choice. It's then up to you to suppress any GUI that the IDE creates from its app template. – David Heffernan Feb 02 '15 at 17:34
  • -1 because your haven't answered the Q. The OP expects a clear answer to a clear Q, not a comment saying "don't do this don't do that". – Abstract type Feb 04 '15 at 15:07
  • @BBaz I think it's clear from your comments to your answer that you don't understand this subject area. Specifically you don't understand PE subsystems. As such you are not in a position to judge anything written here. – David Heffernan Feb 04 '15 at 15:11
  • -1 : do you reply to " I wish to create a small program that is ideally launched from the command line, but then just runs in the background without the need for the console application to be open visibly" ? Do you give a simple solution to the question ? I have a special thing for you David:https://github.com/BBasile/enumset – Abstract type Feb 05 '15 at 03:44
  • @BBaz That's quite puerile. However, let's be clear, you are the one that thinks that a GUI subsystem app has to show GUI. So, when it comes to admitting mistakes, feel free to show the way. – David Heffernan Feb 05 '15 at 07:03
  • @BBaz Since you've been struggling to understand PE subsystems, I've added a program to help you get on top of it. Note that it targets the GUI subsystem (officially known as the Windows subsystem). Now from the command line, launch the program in my answer. Note what happens. The child process runs, but the interpreter prompt appears immediately. The interpreter does not wait. Contrast that with the code in your answer. Now, let's see about `BadTrait.notadmiterror`. – David Heffernan Feb 05 '15 at 09:26
1

With Lazarus it is very simple. Just write small launcher program:

program project1;

uses
    Process;

var
    p: TProcess;
begin
    p := TProcess.Create(nil);
    try
        p.ShowWindow := swoHIDE; // To hide your console app
        //p.ShowWindow := swoShowNormal; // To show your console app
        p.Options := [poNewConsole];
        p.CommandLine := 'cmd'; // Change to your app name
        p.Execute;
        Writeln('Programm launched.');
    finally
        p.Free;
    end;
end.  

Actually, it is not Lazarus but pure FPC program.

Abelisto
  • 14,826
  • 2
  • 33
  • 41
0

Assuming you're only using this program under Windows, you can simply call FreeConsole from the Windows API:

FreeConsole function

Detaches the calling process from its console.

For example this simple program:

program project1;
uses
  sysutils, windows;
begin
  FreeConsole;
  while(true) do
    sleep(50);
end.

Can be launched from the explorer or from cmd and runs infinitely without showing its own console. When launched from another console, it continues running even if the other cmd instance is closed.

Community
  • 1
  • 1
Abstract type
  • 1,901
  • 2
  • 15
  • 26
  • It's a bad idea to make a console application if you always abandon the console. Utterly pointless. Just make a GUI app and then there's no console to begin with. -1 – David Heffernan Feb 04 '15 at 13:11
  • 1
    a GUI app will have a bloat of useless code because of the LCL (RTL as well) initialization: TApplication, TScreen, etc creates hundred of kbytes in .text which are only useful if the GUI application has a GUI. BTW your argument could be reversed: It's a bad idea to make a gui application if you don't show a form. Utterly pointless. Just make console app and then there's no gui to hide. – Abstract type Feb 04 '15 at 15:06
  • A GUI app does not need to have a GUI. We are talking about the PE subsystem here. We aren't going to show a GUI. In Delphi terms this is nothing more than `{$APPTYPE GUI}`. With MS tools it is `/SUBSYSTEM:Windows`. None of this compels you to have any bloat whatsoever. – David Heffernan Feb 04 '15 at 15:10
  • 2
    Calling `FreeConsole` is almost certainly *not* what you'd want to use. [I've written about it before.](http://stackoverflow.com/a/622666/33732) You mention you can run your program from the command prompt. What you *don't* mention is that the command prompt will *hang* while it continues to wait for your program to terminate, even after the console is released! – Rob Kennedy Feb 04 '15 at 17:38
  • What @Rob means is that when you start this program from the command interpreter, the command interpreter waits for the program to return. Which it never does because it never terminates. Thus the command interpreter is rendered useless, blocking indefinitely until this process is killed. Which also kills the command interpreter. Again, this is an opportunity to show some GoodTrait enums. – David Heffernan Feb 05 '15 at 09:20