Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Windows Shutdown handling #1

Open
GordCaswell opened this issue Aug 1, 2017 · 5 comments
Open

Improve Windows Shutdown handling #1

GordCaswell opened this issue Aug 1, 2017 · 5 comments

Comments

@GordCaswell
Copy link
Member

https://portableapps.com/comment/223241#comment-223241

@daemondevin
Copy link

Try something like this:

;=== Prevent Win Shutdown
!include nsDialogs.nsh
!define /ifndef WS_POPUP 0x80000000
Function CreateShutdownBlockReason
	StrCpy $1 $hwndParent
	${If} $1 Z= 0 ; $hwndParent is 0, create a new window for silent installers.
		System::Call 'USER32::CreateWindowEx(i0,t"STATIC",t"$(^Name)",i${WS_CHILD}|${WS_POPUP},i0,i0,i0,i0,pr1,i0,i0,i0)p.r1'
	${EndIf}
	System::Call 'USER32::ShutdownBlockReasonCreate(pr1,w"$AppNamePortable is running and still needs to clean up before shutting down!")'
FunctionEnd

What this does is allows for sufficient time for the portable to exit (I believe the default is 5 seconds, which should allow enough time to close). This default value of 5 seconds can be changed in the Registry (what reg key it is escapes me right now, however I don't think tampering with this key is a good idea either--plus it would need admin rights I believe anyway). This is just a quick answer ..it's not meant to be a full blown solution as I have not tested this fully in regards to having multiple PAFs open at once. This fix still needs work, I'm sure.

Now I'm not sure of a better place to call this function other than Function .OnInit. I'm assuming it should be used inside the Function .OnInit as this is a callback function and runs (obviously) on initialization which is what we want.

You can add language support as well instead of using just that English string at the end; something like:

	;= other code here blah blah
	System::Call 'USER32::ShutdownBlockReasonCreate(pr1,w"$(LauncherPreventShutdown)")'
FunctionEnd

Where $(LauncherPreventShutdown) holds the string for different languages. I'm sure you can take it from here.

@3D1T0R
Copy link
Member

3D1T0R commented Aug 7, 2017

It's been a while since I looked into this, but if I remember correctly there's a way to postpone the shutdown for as long as necessary for it to clean up & exit properly, as long as the end user doesn't tell windows to force an immediate shutdown.
I'll have to check on it again.

@daemondevin
Copy link

@3D1T0R Can you explain to me what you think the code I shared actually does?

I don't mean to seem out of sorts here but the code I shared does exactly what you just said. You can tell because I explained the usage underneath the code snippet.

@3D1T0R
Copy link
Member

3D1T0R commented Aug 7, 2017

You stated that it will make it wait 5 seconds (unless some registry key is altered, which probably resides in part of the Registry that we'd need Admin privileges to alter, which makes that something we wouldn't want to touch, let alone rely on).

The issue I'm bringing up is that 5 seconds is not always enough time (especially for apps which have to copy potentially large amounts of data, e.g. OperaPortableLegacy12) and if I remember correctly, there is another way to go about it, which can do a better job of what we want here. I'll look it up and post more info on it when I have a chance.

@daemondevin
Copy link

daemondevin commented Aug 7, 2017

I should have probably explained this better but the default 5 seconds is just the default allotment for any open application when the end-user decides to shutdown their PC (applies to Vista+). I might have missed something in my research which may be what you're referring to but in my travels I found that for Windows XP, NSIS already handles WM_QUERYENDSESSION on its own. So not much we can do there and Windows XP is a dying breed anyway.

However, for Windows Vista and later, we need to create a hidden window which is what is used to prevent the default 5 seconds by the system entirely. So with what I was saying earlier about the 5 seconds mechanism is frivolous because I forgot to outline that we use the hidden window along side of the system plugin call to USER32 for a ShutdownBlockReasonCreate and pretty much prevents/cancels the shutdown process (this doesn't help if the end-user decides to do a hard-restart/shutdown though lol) until our portable is exited.

I'm sorry for my lack of explanation earlier; to my defense I was tired.. Lol.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants