hnedka
23rd December 2010 22:56 UTC
windows exit
Hi, I'm using NSIS to make applications I use portable, but here is a problem - when I click to shutdown/restart windows and the launcher is still running (in ExecWait function, waiting for the application to exit), it exits immediately and is not given a chance to cleanup whatever is needed. How can I force Windows to wait instead, until the launcher does whatever needs to be done and exits? There must be some API or something.
hnedka
24th December 2010 09:14 UTC
Thank you very much! ;)
hnedka
24th December 2010 22:59 UTC
Unfortunately, it doesn't work. It works only when the NSIS launcher window is visible, which is not what I want. When it is in silent mode or when I hide its window using ShowWindow, it doesn't work. My system is Windows 7, btw. Any ideas? I don't want to prevent windows shutdown completely, I just want to give my portable apps few seconds to do their cleanup (currently, they get terminated immediately). One other thing that doesn't seem to work is "ShutdownBlockReasonCreate" API, which probably requires a visible window as well (not to mention it works only on Vista and newer).
Afrow UK
25th December 2010 13:21 UTC
Unless I have misunderstood your problem, it would make more sense for the program(s) you are launching to act on WM_QUERYENDSESSION and clean up accordingly. If they don't have a window then you must create one (it can be hidden).
Stu
hnedka
25th December 2010 20:13 UTC
Modifying the launched program is not an option - after all, that's the whole point of portable launchers - to cleanup after application, that doesn't do it itself (even when it's open source, modifying it is not a good idea, because you would need to update the code everytime you download a new version + plus you would need to setup you machine for the right compiler).
Anyway, I have found a partial solution and it's surprisingly simple. All that I needed to do is to create a window and now, the launcher gets 5 seconds (default Windows value, can be changed in HKEY_CURRENT_USER\Control Panel\Desktop) to cleanup, which should suffice most of the time.
System
::Call `kernel32::GetModuleHandle(i 0) i.R3`
>System::Call `user32::CreateWindowEx(i 0, t "STATIC", t "", i 0, i 0x80000000, i 0x80000000, i 0x80000000, i 0x80000000, i $HWNDPARENT, i 0, i R3, i 0) i.R1`
But it would be nice to be able to control it via the message loop. Will do more experiments.
hnedka
25th December 2010 22:55 UTC
OK, this is a final solution:
System
::Call `kernel32::GetModuleHandle(i 0) i.r3`
System::Call `user32::CreateWindowEx(i 0, t "STATIC", t "MyApp Portable Launcher", i 0, i 0, i 0, i 0, i 0, i $HWNDPARENT, i 0, i r3, i 0) i.r1`
System::Call `user32::ShutdownBlockReasonCreate(i r1, w "MyApp Portable Launcher Cleanup") i.r0`
The first two calls create a long (probably indefinite) block on Windows XP and older. On Vista and newer, the app would get terminated in 5 seconds. For that case, there is the call to "ShutdownBlockReasonCreate", which will override that limit. This function is not present in XP and will fail there, but is not needed there anyway.