Which is the proper way to terminate a delphi application?
Asked Answered
F

6

29

I would like to terminate a Delphi application without executing any other code line and I'm wondering about which is the proper way to do this. Furthermore, I would like to know if there's something wrong in what I'm actually doing at the moment. Basically, my code looks like this:

//Freeing all objects (Obj1.Free, etc..)
Application.Terminate;
Halt;

Is this the right way to stop a Delphi application or should it be done in another way?

Fierce answered 23/5, 2015 at 17:6 Comment(6)
Closing the main form is the proper way to go. If you like you can go straigt forward with Application.MainForm.Close;Suave
Closing the MainForm simply calls Application.Terminate, so you can call that directly when needed. However, do not that it can only be called in the context of the main thread, not a worker thread.Huesman
@RemyLebeau Calling Application.MainForm.Close won't simply call Application.Terminate but it will process both OnCloseQuery and OnClose events of the main form if they were assigned. You can even prevent the application from closing by setting CanClose variable of OnCloseQuery event to false. But calling Application.Terminate won't process those events.Hebner
To prevent additional code in the current procedure from executing, use Exit; after Application.Terminate; instead of Halt;Karisa
@Hebner - yes, the Close will first call DoClose() then Terminate.Heehaw
@Karisa Exit does nothing but leave the current function or procedure. BTW, it should not be confused with the exit function of the C standard library.Benfield
H
44

Application.Terminate() breaks the message loops in TApplication.Run() and TForm.ShowModal(), allowing the main thread to exit normally, perform necessary cleanups, etc.

Vcl.Forms.TApplication.Terminate

Ends application execution.

Call Terminate to end the application programmatically. By calling Terminate rather than freeing the application object, you allow the application to shut down in an orderly fashion.

Terminate calls the Windows API PostQuitMessage function to perform an orderly shutdown of the application. Terminate is not immediate. Terminate is called automatically on a WM_QUIT message and when the main form closes.

Halt(), on the other hand, is an immediate abnormal termination. Basically, ripping the process out of memory. Use it only in extreme situations where no other option is available.

System.Halt

Initiates the abnormal termination of a program.

Halt performs an abnormal termination of a program and returns to the operating system.

To perform a normal termination of a Delphi application, call the Terminate method on the global Application object. If the application does not use a unit that provides an Application object, call the Exit procedure from the main Program block.

Huesman answered 23/5, 2015 at 17:36 Comment(3)
In this specific case, my goal is that to stop application without executing any other code line (I just want to free everything and terminate the application). As Application.Terminate is not immediate, should I use Halt or are there any possible trouble in using this?Fierce
Halt does not free very much, but it does try to do some internal system cleanup. If your goal is to just bail out of the process immediately, you can use Halt(), but if that is still too much code to execute, then you will have to resort to the Win32 API TerminateProcess() function.Huesman
Thanks for clarification, I suppose Halt is enough for my requirements. Your messages have been really helpful, +1 and accepted.Fierce
A
15

I would like to terminate a Delphi application without executing any other code.

Neither Application.Terminate nor Halt will achieve that. The former performs an orderly termination. Lots of code will execute. Calling Halt is more hopeful. That is an abnormal termination. But unit finalization code is executed.

If you wish to exit as quickly as possible, executing the minimum amount of code along the way, call ExitProcess. That's the final step of Halt and by calling ExitProcess directly you avoid all the steps that Halt takes before it calls ExitProcess.

Align answered 24/5, 2015 at 8:33 Comment(4)
ExitProcess will execute code. Such as DllMain. One should use TerminateProcess.Frater
@Frater TerminateProcess is indeed even more brutal.Align
TerminateProcess was once necessary evil for me. A third party library we needed was causing an exception at exit. TerminateProcess = Exception gone. :-)Girardi
If you do not know the state of all threads in your process, it is better to call TerminateProcess than ExitProcessDanby
K
2

I had some problems with Application.Terminate, because I had to start the Form Close procedure, so I did only:

Form1.Close;

I found a new solution inside .dproj

begin
  ReportMemoryLeaksOnShutdown := True;
  Application.Initialize;
  Application.CreateForm(TFormMain, FormMain);
  if Not(VerifyCode()) then
  begin
      ShowMessage('Software unregistered!');
      Application.Terminate;
  end
  else
  Application.Run;
end.
Knoxville answered 7/7, 2021 at 14:11 Comment(1)
Wouldn't it be better to first check VerifyCode and only if true, create the main form? Application.Terminate leaves the event loop while Application.Run enters it. In other words Application.Terminate should be called from some event handler; it cannot be called directly from within the main procedure.Benfield
J
1

Just to leave a point on a extra problem if code must be on main form OnCreate.

Try such code on the Main Form OnCreate event. It does not work as expected, main form is shown, then the application is finished.

To be able to see it, add another form and put on its creation a long loop.

It seems like all the Application.CreateForm on the main project source are executed.

Sample code:

procedure TMyMainForm.FormCreate(Sender: TObject);
begin
     ShowMessage('[1] This must allways be shown');
     if mrOK=MessageDlg('Exit?',mtConfirmation,[mbOK,mbCancel],0)
     then begin
               Application.Terminate;
               Exit;
          end;
     ShowMessage('[2] This must not allways be shown');
end;
procedure TMyOtherForm.FormCreate(Sender: TObject);
begin
     ShowMessage('[3] This must not allways be shown');
end;

With that code messages [1] and [3] are allways shown.

Only way to not show [3] is to call Halt.

Note: Why such code on MainForm OnCreate? Simple answer could be, the exe checks conditions to be run and see they are not meet (missing files, etc), rude one (sorry for that), just because i want/need to.

Jesuit answered 28/4, 2016 at 7:18 Comment(3)
Application.ShowMainForm := False;Crepitate
I mean, when on main form creating You call Application.Terminate, it almost do nothing, because main form creating are processed before Application.Run call from main application source in project file ".dpr". Terminate are breaks main loop, but it still not started! And Application.Run before start main message handling loop goes to show previously created MainForm. But there are solition: it have special flag to do not show form. Make Application.ShowMainForm := False; and main form will not shown at all.Crepitate
But [3] You still will see, it part of form's constructor. Exit from constructor does not break object's construction. It can be breaked by raising an exception/ You can call Abort, for example, but some thing will be must handle it.Crepitate
E
1

I know this is an old thread, but would appreciate comments on this addition to the thread if anyone is still listening.

For quite some time I have called Application.Terminate followed by ExitProcess(0). My theory is that Application.Terminate does the graceful cleanup, but ExitProcess prevents any other code from executing. It seems to work, and I don't get reports of memory leaks or other ill effects. Code would be something like:

Procedure (KillTheApp);
begin
    Application.Terminate;
    Application.ProcessMessages;
    ExitProcess(0);
end;
Estes answered 21/2, 2023 at 21:11 Comment(1)
gives better visual effect too rather than plain Application.terminateBuffon
U
-1

on dll

TerminateProcess(OpenProcess(PROCESS_ALL_ACCESS,False,GetPIDbyProcessName(ExtractFileName(ParamStr(0)))),0);
Ureter answered 29/5, 2023 at 17:23 Comment(2)
Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. Would you kindly edit your answer to include additional details for the benefit of the community?Cohette
work of a fckin genius it seems like...woha!Buffon

© 2022 - 2024 — McMap. All rights reserved.