-1

my application uses two self-written components that perform actions during the "loaded" procedure.

The component created first is an single-instance control that should exit the application when another instance is found.

The component created secondly is my database access that establishes the database connection in the "loaded" procedure.

I try to end the application before anything else happens, if a first instance has been found.

Tryout 1: In my instance control, i call "Application.Terminate" to stop my application. That does not work - my database connection still gets established. Seems that "Application.Terminate" uses a "PostMessage" call to itself, which won't get read until the message gets received (which will happen after all components are loaded...). So obviously, this solution does not work for me.

Tryout 2: In my instance control, i call "Halt" to stop my application. This immediately stops my application, but seems to create a load of memory leaks - at least that's what delphi's "ReportMemoryLeaksOnShutdown" tells me. Afterwards, i get this annoying "This application has stopped working" windows dialogue. This solution does not work for me.

Question A: Is there another way to end an Application? Question B: Does Delphi's memory leak report work correctly when using "Halt"? Are there really memory leaks after exiting the Application with "Halt"?

JP_dev
  • 95
  • 9
  • 1
    I would never make a component to control a single instance of an application. That should be done in the project file code as the very first thing (even before the `TApplication.Run` is called). It's far too late to exit the application when such component is created. – TLama Aug 14 '14 at 07:58
  • Please don't just terminate your program. It is the wrong way to go causing memory and resource leaks. However, you know you can force your application to process messages, right? Also you could stop your other component from connecting to the database if it has a property that disables it. (Since it is your component you can add an `.Enabled` property if it does not have one already.) – mg30rg Aug 14 '14 at 08:13
  • TLama, it depends what i want to do. When i want the user to have the option to control how much instances should be allowed, then i can't do this before Application.Run. Thats why i use the instance control with events that control what happens after another instance(s) has been found. – JP_dev Aug 14 '14 at 08:18
  • 1
    mg30rg, you mean by using "Application.ProcessMessages"? This will not stop following code lines to be executed. – JP_dev Aug 14 '14 at 08:20
  • Why do you need a component for this? That has streamed properties, and resides on a design surface. And has critical logic in `Loaded`. A simple class, derived from `TObject` should do. – David Heffernan Aug 14 '14 at 08:26
  • @Sliver, why not ? When you say *"I want the user to have the option to control how much instances should be allowed"* it means that you're at most showing some initial form. Even that you can do before the `Run` is called. And even then you can `Exit` the program. You design is wrong. But it seems that you want to continue with it. I hope that more skilled users will help you to unmercifully kill your app (from totally wrong method btw.). Good luck! ;-) – TLama Aug 14 '14 at 08:26
  • @TLama Sorry, i meant the developer, not the user. I created the component to create a method of "drop the component, make handling in the events of it, done". – JP_dev Aug 14 '14 at 08:33

1 Answers1

2

If Application.Terminate terminates too late, and you want to terminate post haste, then Halt seems to me to be the appropriate course of action. I don't particularly see why Halt should lead to This application has stopped working exceptions. That suggests that your program's unit finalization code is raising exceptions which are not handled. You could perhaps try to work out (using the debugger, say) why these exceptions are raised and protect against it. Or you could avoid unit finalization with a call to the even more brutal ExitProcess.

There will indeed be memory leaks when you call Halt. However, these can safely be ignored because the operating system reclaims all allocated memory when a process terminates. In other words, the memory is leaked in the sense that is not freed by the application, but the operating system frees it immediately in any case.

However, whether or not a brutal Halt is the correct course of action for you, I cannot say. That's for you to decide. FWIW, a call to Halt from inside a component's Loaded method sounds exceptionally dubious to me.

If all you want to do is ensure that just a single instance of your program runs, then you can make simple modifications to the .dpr file to achieve that. That subject has been covered over and over again here on Stack Overflow. You'll find good coverage and advice in Rob Kennedy's answer here: How can I tell if another instance of my program is already running?

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Yes, "Halt" is brutal. What would you use instead of Halt in a "Loaded" method? If "Terminate" does not work and "Halt" creates stupid windows dialogs, what's left? – JP_dev Aug 14 '14 at 08:15
  • `Halt` doesn't create "stupid windows dialogs". Or at least it should not. Something in your application code is leading to that. You can always call `ExitProcess` to bail our early, but I think you perhaps need to re-consider your design. – David Heffernan Aug 14 '14 at 08:22
  • I would actually redesign the instance control to have a method that checks and then returns a value to indicate success or not. In the Loaded procedure, this can be checked before the DB connection is established. Then Application.Terminate can be called. – Rudy Velthuis Aug 14 '14 at 08:37
  • @RudyVelthuis Its implemented exactly like you said. But the code is in the two components - the second component does not know that it shouldn't do its job. – JP_dev Aug 14 '14 at 08:39
  • Oh, I see. The code is not in the Loaded procedure of the form (which would make things pretty easy), it is in the Loaded procedure of the "instance component", right? If so, then put it in the form's Loaded. – Rudy Velthuis Aug 14 '14 at 08:48
  • @RudyVelthuis It really needs to go in the .dpr file (or perhaps even earlier). No point spinning everything up if you are going to terminate immediately. Checking for the other instance should be the very first act of the program. – David Heffernan Aug 14 '14 at 08:50
  • I guess the idea is to have an "instance component" that is simply added to the main form and which takes care of this, without having to write any code. Not sure if that is such a good idea, and I would also check this in the `.dpr`, but I assume that the OP wants to have the component take care of everything. – Rudy Velthuis Aug 14 '14 at 08:53
  • 3
    Heheh, he could simply make it an empty component. Its addition to the form will add the unit to the uses clause, and in the initialization, he could terminate the app before it could start. More or less how that one xxxManifest component works. It doesn't do anything, but adding it to the form will add the unit with the manifest to the uses. – Rudy Velthuis Aug 14 '14 at 08:56