How to catch Delphi App shutting down when run in IDE? - delphi-2009

Scenario
Using Delphi 2009 on Windows 10 I have an app that performs shut down operations such as logging and database manipulation.
Anywhere the user is able to exit the app I call Form.Close on the main form which calls a procedure to do the required operations. This works ok regardless of whether the user exits via the menu or by using the Windows task bar icon to close the window (as some of my users do).
Problem
When debugging the app in the IDE however, clicking the red square in the Delphi menu bar to stop the app running does not call Form.Close and hence doesn't call my shut down procedure.
Question
Is there a way to make the app correctly call form.close when shut down via the IDE so that I can ensure all parts get debugged?
Other info
I've looked here which describes a method using WMQueryEndSession to catch windows shut down messages but when I use that code in my app it is not called when the IDE shuts down the application, so maybe the IDE is using a different method.
Code used in my WMQueryEndSession procedure
procedure TFrmMain.WMQueryEndSession(var Msg: TWMQueryEndSession);
{intercept the shut down message and call our proc first
SafeFormClose is very simple and quick so no issues.
Also called first in case the inherited procedure shuts us down
before SafeFormClose has a chance to run}
begin
SafeFormClose; //Do our shut down and logging stuff
Msg.Result := 1; //Signal that it is OK for Windows to shut us down
inherited; //Do whatever the original handler would have done.
end;

If you are running the program in debugger, clicking the red square (reset button) terminates the program immediately. The debugger has full control of the program, and no more code is run after you click the reset button.
This is different than for example terminating the program in the task manager (in which case Windows would send a close signal to the program, which could reject it if it doesn't want to close yet).
You should design the program so that if it stops at any point, the next time it is started it fixes any problems caused by the reset (for example fixes corrupted database files). This is a real situation that can occur when power is lost or the operating system crashes. You cannot trust that your shutdown routine can be run every time.

Related

Halt code at dialog (msgbox()) command in IDE

Title quite much says it all.
In VB6, and in VBA/Access it was possible to hit break key, and jump into debug mode when using the msgbox() command.
Is there a way to do this in vb.net (desktop/winforms) applications?
Often, some code will toss up a dialog box, and it is rather nice then to jump into debug mode as a result of that message box having been displayed.
Edit
Ok, hitting pause button in most applications work, but in this application, when I hit pause, then I get this:
Edit two:
Ok, I have discovered the reason for this behavior. I have the application Frame work box un-checked. The reason for this is I did't want to specify the main application form as startup form, and I desired additional control over what occurs if the main startup form (that I don't specify) is closed. Thus, my main application form is launched via application.Run(my form)
It thus seems that due to starting the main form as a new separate application thread (which is the result of using application.Run(), then you can't use ctrl-break, or more common use/hit the pause button in the IDE to halt the code. Hitting pause will thus display that the application is running a main app thread, which indeed is the case since I use applicaiton.Run() to launch the main form from the classic and traditional Sub Main().
Edit 3
A way to fix this, and enable the pause key to work is to un-check in tools->debugging the [ ] Enable Just My Code. This will thus allow debug mode of the other "main" application thread.
Hmm. [CTRL][BREAK] clears the dialog box. However, clicking the pause button in the IDE will do what you want.
Alternatively, select Debug > Break All from the menu.

Create a background proccess that terminates a program on KeyPress (VB 2013)

I'm look for code which can help me accomplish what the title suggests.
I want this because I have an issue with a program which is quite buggy (it's a game), and if It freezes, and results in a black screen. Even after using Shift+Ctrl+Esc, Ctrl+Alt+Del, Alt+F4 and the rest of them, I acn't seem to end the program. So I thought that a KeyPress event would work, as it doesn't require me to use the UI in any way.
However, I've never used VB for anything other than Form's, so I have no idea how to start on something which runs in the background.
Thanks :)
A background app won't help in this case.
Ctrl+Alt+Del is specail key combo that is handled directly by Windows and can't be intercepted by a running program.
What this means is that if your game locks up and Ctrl+Alt+Del doesn't bring up the Windows menu, then the game has corrupted the system. The only fix at that point would be a restart.
That being said, you can kill a running process using VB.NET like this:
For Each program As Process In System.Diagnostics.Process.GetProcesses
If program.ProcessName = "ProcessName" Then
program.Kill()
End If
Next
Read more about it on the MSDN.
Okay, so Windows isn't actually locking up, but you just need some way to kill the process. Use the above code, replacing "ProcessName" with the name of your game process, and then either:
(basic) Turn the VB.NET code into an .exe file. Then set up a keyboard macro (using your keyboard software or some freeware) to launch the .exe you made which will kill all running instances of the given process. or...
(advanced) Import "user32.dll" into the VB.NET code, call SetWindowsHookEx with a hook id of 13, a pointer to a LowLevelKeyboardProc function, the handle to your running program, and a thread id of 0. Then, whenever a key is pressed in any program, your KeyboardProc function will be invoked. If the key(s) pressed match your desired kill-key combo, then run the above process killing code. This looks like it may give you more step-by-step instructions.

How can I simulate my Metro app being terminated?

VS2012's default C# "Metro style" project templates include code in App.xaml.cs (in the OnLaunched override) to restore the application state after a suspend-and-terminate. This code only runs when LaunchActivatedEventArgs.PreviousExecutionState is Terminated, i.e., "The app was terminated after being suspended."
How can I force my app to be suspended and terminated, so I can test this suspend/resume functionality in my app?
Things I've tried that don't work:
If I use the "close app" gesture (drag from the top of the screen to the bottom), then the next run's PreviousExecutionState is ClosedByUser.
If I kill the app -- either using Task Manager, or (if I was debugging) with the "stop" button on the VS toolbar -- then the next run's PreviousExecutionState is NotRunning. This is true even if Task Manager showed the app as "Suspended" before I ended task, so clearly it's more nuanced than the description of "terminated after being suspended".
You'd think I could just switch away from my app, and then open lots of other Metro-style apps until my app eventually gets kicked out. But even if I open every single Metro-style app that ships with the Windows 8 Release Preview, that's apparently not enough memory pressure to make Windows terminate my app. (I assume Windows would be less likely to terminate an app that was being debugged, so I launched my app from the Start screen -- no debugger -- before I tried this.)
It does appear that, if I switch away from my app and type into a StackOverflow window for several minutes, that my app will eventually get terminated, so perhaps there's a time-based component to it. But if I have to wait five or ten minutes every time for my app to terminate, that's a pretty slow testing cycle.
Given that this is something developers will have to test, you'd think there would be a nice, easy way for a dev to force an app to suspend-and-terminate. Is there some kind of stress-test app that comes with Visual Studio that will force enough memory pressure? Is there some menu item in Visual Studio that will force termination of my app? How are we supposed to test this?
In Visual Studio 2012, when you're debugging, there are "Suspend", "Resume" and "Suspend and Shutdown" buttons. By default, you should see the buttons while you are debugging your app. See this article for more info on debugging process lifecycle.
I had trouble finding the Suspend control because VS wasn't showing a second row of toolbars for me. As it turns out, this is on the "Debug Location" toolbar. Make sure you have this toolbar turned on and then you should be able to find the Suspend control (and it does work to solve the OP's problem).
If they don't show by default, go to TOOLS -> CUSTOMIZE, and under the Toolbars tab, check the box that says "Debug Location"
I was looking for VS 2013, just in case others came for the same reason.
Source:
http://blogs.msdn.com/b/visualstudio/archive/2012/08/23/new-visual-studio-2012-debugging-features-for-the-windows-8-app-lifecycle-model.aspx
a busy cat http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-92-metablogapi/2210.image_5F00_thumb_5F00_1FBA9C1E.png

When calling to NSOpenPanel's runModal, my application will not properly terminate

I'm writing a simple Cocoa Application, no core data or multiple document support. Running on a Mac Pro, OS X 10.6.6, Xcode 3.2.3.
I have reduced my application to the following code in my AppDelegate class:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel runModal];
return;
}
From within the debugger, I will run my application. As expected a somewhat not-to-useful OpenPanel will appear. I will click Cancel and it will disappear. All this is as expected. When I click [Command + Q] to Quit the application, the UI will go away but the debugger will indicate that the application is still running (as does the console output).
Based upon all the information I'm reading, I should not have to do anything else in order for this to run right. I've downloaded several examples on the Open Panel's usage but most use the deprecated methods of opening modal giving additional information as parameters. FWIW, I tried those methods and am still seeing the same result.
One last item, when the Open dialog appears, just for an instant I see a message box asking me something to the extent if I want my application to receive incoming connections. The dialog quickly disappears. I don't know if that is part of my problem or not. [Update - this deals with my Firewall being turned on.]
Yes, I'm fairly new at Objective C but not at programming in general. Any words of wisdom is greatly appreciated!
2011.02.07 - Update:
I have walked the debugger line by line without incident. There is no indication of any program failure in the console window.
I say that the debugger is still active after [Command + Q] because the Stop Process toolbar button is still enabled as is the Break button. Further the console indicates that after I tell the application to terminate (either via the menu or key command) that it is still running. The following is the Complete console output from start of run to after I Quit the application.
Program loaded.
run
[Switching to process 62370]
Running...
The Activity Monitor (system tool) will show my application terminating (no longer shows up as a process) but the Debugger will still not transition to "edit" mode - if I tell Xcode to run the debugger again, it will ask me if it's OK to Stop the current debugging session. If I was in Windows I would start looking for background threads keeping the process alive but as far as I know, NSOpenPanel should not be doing something like that.
I have further simplified the program to nothing more than creating a brand new Cocoa application and inserting the code snippet above - no other additions to the template project or updates in any way.
And lastly, when the application is run under the Leaks Performance Tool, everything runs fine when the panel is created but never used. When created and actually used though, at the end of the run I will get the following message in the tool "insufficient task_for_pid privileges (leakagent64)". Googling this hurts. If I read it right, the debugger does not have sufficient permissions to fully kill the target process ??? Now that sounds stupid but ... It does not make sense!
Another update - I just downloaded and ran FunHouse, one of the SDK sample applications that also uses NSOpenPanel. Well don't I feel special. It exhibits the same exact behavior. So from this I conclude either Apple has a bug in their code, my machine is special and messed up, and finally, it is Not my code that is at fault. That being the best part. Tomorrow, I will use a friends Mac and see if the same behavior is exhibited on his box.
This is just too weird.
I rebooted my box, took it to work and found it worked like a charm! I will assume this is fixed and has nothing to do with any other connected devices at home as compared to at work.
If it re-exhibits at home, then it is a network/device issue. Thanks all for your inputs and suggestions! Very much appreciated.
What, specifically, does the debugger say? It's possible that your program crashed, so the debugger is showing you information about the crash.
What if you omit any attempt to run an Open panel?

Python freezes after computer sleep/hibernate

I have a python script that is running in the background with pythonw. If I close my laptop, it goes into sleep mode. and when I open my laptop, my program has little functionality and freezes after a couple of seconds. Is there any way that my script can tell if my computer is going into sleep mode, so that it can lie dormant and restart when I re-open my laptop?
You can catch WM_POWERBROADCAST window message with PBT_APMQUERYSUSPEND event inside it. To catch this message inside Python program, you can create new invisible window and make separate thread repeatedly calling GetMessage().
In the worst case you can archieve all these by using ctypes only, but you can also use pywin32, sometimes referred to as win32py.