Old 1st March 2018, 20:08   #1
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
Execute actions before reboot

Hi,
I have a strange issue and I cannot find a solution. My installer calls an external installer (included in it), but sometimes this external installer reboots the PC. I want my installer to execute some actions before the reboot. How it can handle this?
TrifonovS is offline   Reply With Quote
Old 2nd March 2018, 22:45   #2
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,814
I don't see how you can, ExecWait does not return until the process has completed. Is this a MSI based external installer?

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 4th March 2018, 20:13   #3
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
Yes, it is MSI based installer. I know that I cannot do anything inside my installer, but I'm thinking that I can register somewhere another small application (before to call this external installer) that will be called when Windows tries to reboot and it can do the job.But I don't really know how to do it...
TrifonovS is offline   Reply With Quote
Old 4th March 2018, 21:39   #4
Nutzzz
Junior Member
 
Join Date: May 2007
Location: Orange County, CA, U.S.A.
Posts: 47
MSI installers take the /norestart command line parameter, and return 3010 if install was successful but requires a reboot.

If the installer didn't take a command line parameter, I could think of some wacky hacks like adding a logoff script and then removing it once the script runs, or just removing it without running it if the installer didn't reboot.
Nutzzz is online now   Reply With Quote
Old 5th March 2018, 11:06   #5
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
Thank you Nutzzz, but ca you explain a little bit the idea of the logoff script. I didn't get it...
TrifonovS is offline   Reply With Quote
Old 5th March 2018, 18:52   #6
Nutzzz
Junior Member
 
Join Date: May 2007
Location: Orange County, CA, U.S.A.
Posts: 47
Well, since the former method should work for you, that's by far the better solution.

The hacky method I mention is to replicate the method that the group policy editor uses to assign a shutdown script to the machine (or a logoff script for the current user) by using a .reg file with "regedit.exe /s regfile.reg" (and/or a group of WriteRegStr/WriteRegDWORD NSIS commands). See this page for an example .reg file for a startup script.

Your script would be a .bat/.cmd or .vbs file that runs your actions and then applies another .reg file that deletes the registry entries so the shutdown script doesn't run next time around. If you want/need to use NSIS for your actions, you could create another installer or even leverage your uninstaller by calling it with a command line parameter that uses an otherwise unused routine and then immediately quits before the regular uninstall routines begin.

If a reboot isn't performed and execution returns to your installer, then delete the registry entries so that they're never used.

FYI, to delete registry values using a .reg file, assign it an unquoted hyphen (-), e.g.:
code:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\Scripts\Shutdown\0\0]
"Script"=-
"Parameters"=-
"ExecTime"=-

Nutzzz is online now   Reply With Quote
Old 5th March 2018, 19:12   #7
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
Hi again Nutzzz,
Thanks a lot. This is exactly what I'm searching for.
TrifonovS is offline   Reply With Quote
Old 3rd July 2018, 08:59   #8
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
Hi again!
This doesn't work. When the PC is connected to the network, the group policy is changed by the network server. The problem still occurs. Isn't there another way to catch the reboot without hacks?
TrifonovS is offline   Reply With Quote
Old 3rd July 2018, 11:29   #9
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
One additional question. I found somewhere in Internet that NSIS handles WM_QUERYENDSESSION message and returns FALSE, so it must prevent rebooting from another application. Is there any possibility to execute a function from the script when thos message is received?
TrifonovS is offline   Reply With Quote
Old 3rd July 2018, 11:48   #10
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,814
Quote:
Originally Posted by TrifonovS View Post
One additional question. I found somewhere in Internet that NSIS handles WM_QUERYENDSESSION message and returns FALSE, so it must prevent rebooting from another application. Is there any possibility to execute a function from the script when thos message is received?
Only if you write a custom plug-in. You don't know if Windows is really restarting at that point though.

See also:
https://blogs.msdn.microsoft.com/old...29-00/?p=95855

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 3rd July 2018, 14:02   #11
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
Thank you Anders. I want to avoid writing a plug-in, because my knowledge is not enough. However, is it possible to use code like this:
PHP Code:
  !include SysFunc.nsh
  
!include WinMessages.nsh

  
...
  
StrCpy $5 $hwndParent
  
Create MSG struct
  System
::Call "*${stMSG} (_) p.R9"
  
Get message
  System
::Call "${sysGetMessage} (R9, r5,_) .s"
  
!insertmacro SINGLE_CALLBACK 1 $R8 1 ShutDownRequest

  
...
  Function 
ShutDownRequest
    MessageBox MB_OK 
"NSIS: Shutdown request detected!!!"
  
FunctionEnd 
I tried this code, but the installer hangs-up somewhere in these lines. My problem is that this is ready code and I don't understand it completely. Maybe there is an error that I cannot see...
TrifonovS is offline   Reply With Quote
Old 3rd July 2018, 20:24   #12
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,814
You can't use the system plug-in to do this. I wrote a WndSubClass plug-in a long time ago, it might work.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 4th July 2018, 06:19   #13
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
Hi Anders,
I'm following you advice. I installed the WndSubclass plug-in and also executed the example that comes with it. It works fine, but I still can't understand how to use it for my needs. Sorry for that, but can you give me a next hint?
TrifonovS is offline   Reply With Quote
Old 4th July 2018, 08:02   #14
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
One more question. I cannot understand from the example why the message is in $2:
PHP Code:
  ${If} $= ${WM_NCHITTEST}
    ; ...
  ${ElseIf} $
= ${WM_TIMER}
    ; ...
  ${ElseIf} $
= ${WM_LBUTTONUP}
    ; ...
  ${EndIf} 
Where it comes the value in $2?
TrifonovS is offline   Reply With Quote
Old 4th July 2018, 08:31   #15
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,814
The plug-in uses $1, $2, $3 and $4 so you don't have to pop IIRC.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 4th July 2018, 09:00   #16
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
Ok! I played a little bit with the example to reach what I want. Probably I still don't understand how the things must work, but here is a part of the modified code:

PHP Code:
Function ShutDownEvent
${If} $= ${WM_QUERYENDSESSION}
  
MessageBox MB_OK "ShutDownEvent"
${EndIf}
FunctionEnd

Function licshow
FindWindow 
$"#32770" "" $HWNDPARENT
${WndSubclass_Subclass} $0 ShutDownEvent $$8
FunctionEnd 
I expect that when I try to reboot Windows I will see the message box "ShutDownEvent", but this never happens. What I'm doing wrong?
TrifonovS is offline   Reply With Quote
Old 4th July 2018, 09:56   #17
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,814
Only top-level windows get this message, you must subclass $HWNDPARENT. Also, WM_QUERYENDSESSION is not the shutdown event, it is the maybe shutdown event. You get one more message if it actually happens.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 4th July 2018, 10:32   #18
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
Great! Thank you, Anders. Now it works. It is not a problem for me if this message doesn't guarantee that the Windows will shut down after it. It will be a problem if I don't understand when Windows will shut down.
TrifonovS is offline   Reply With Quote
Old 4th July 2018, 12:17   #19
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
I have a new problem now. I moved my code from the example to my official installer and now there is no way to see the message box when reboot is requested. Here is my modified code:

PHP Code:
!define MUI_PAGE_CUSTOMFUNCTION_SHOW InstFilesShow
!insertmacro MUI_PAGE_INSTFILES

...

; Function 
that is called when the installation dialog is shown
Function InstFilesShow
  MessageBox MB_OK 
"InstFilesShow"
  
Set a function that will receive the messages to the parent window
  
${WndSubclass_Subclass$HWNDPARENT GetWinMessage $$8
FunctionEnd

; Function that receives the messages to the parent window
Function GetWinMessage
  MessageBox MB_OK 
"Got a message!"
  
${If} $= ${WM_QUERYENDSESSION}
    
MessageBox MB_OK "End session query!"
  
${EndIf}
FunctionEnd 
When I start the installer I see the message box with text "InstFilesShow", but the function GetWinMessage is never called (I don't see even the message box with text "Got a message!". I really don't have an idea why...
TrifonovS is offline   Reply With Quote
Old 4th July 2018, 12:37   #20
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,814
Putting a MessageBox that is displayed for all messages is not a good idea, remember that MessageBox itself will end up sending a message to the window that owns it (changing active window etc.) and it quickly ends up with a stackoverflow or something else bad.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 4th July 2018, 12:57   #21
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
Yes, I know this. Initially I didn't have this message box, but because I cannot see anymore the other text "End session query!" I added it. I removed it again, but the text "End session query!" doesn't appear when the installer's install page is shown and I try to reboot Windows. This worked well in the example, based on WndSubclass.ini, but not inside of my installer...
TrifonovS is offline   Reply With Quote
Old 4th July 2018, 13:39   #22
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,814
Maybe you are using other plug-ins that also subclass? Impossible to tell without more information.

Use System::Call 'kernel32::OutputDebugString(ts)' "Hello World$\n" and DebugView from SysInternals instead of MessageBox for something like this.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 4th July 2018, 14:14   #23
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
I made this. I see that the function InstFilesShow is called, but function GetWinMessage - never. The $HWNDPARENT contains value 592010 and the returned value in $8 is "NONE". Is this useful information?
TrifonovS is offline   Reply With Quote
Old 4th July 2018, 14:33   #24
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,814
I was thinking more information about which other plug-ins you are using. Try commenting out other code until it works.

The value of $HWNDPARENT is not important, it just needs to be <> 0. "None" in $8 does not seem right, it should probably be a number and <> 0. This plug-in is also ANSI only.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 4th July 2018, 14:43   #25
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
This is the problem. Thanks for the idea. I cannot imagine that I couldn't guess myself. The example is using ANSI plug-ins, but my installer - Unicode. And I cannot change this. I remember that I have seen somewhere in Internet a macro that converts the parameters. I hope that this will help. I another case I'm on a dead end again.
TrifonovS is offline   Reply With Quote
Old 4th July 2018, 14:49   #26
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,814
There is a CallAnsiPlugin plug-in but it will not work here. I guess you could create a little helper ANSI app.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 4th July 2018, 15:03   #27
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
On a first look it sounds complex to me . But if there is no other way I should make it. By the way I found this (it's only a part of the code, cause it is integrated in a macro):

PHP Code:
  Exch $0
  System
::Call 'kernel32::WideCharToMultiByte(i0,i0,w"$0",i-1,t.s,i${NSIS_MAX_STRLEN},i0,i0)i'
  
Pop $0
  Exch 
$
But it can't convert the function's name. I thought that it will be converted like a string, but it doesn't work like this. The compiler show error message:

Error: resolving install function "$0" in function "InstFilesShow"
TrifonovS is offline   Reply With Quote
Old 4th July 2018, 15:06   #28
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,814
You cannot convert on your own.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 5th July 2018, 05:23   #29
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
I found the following plug-in: http://nsis.sourceforge.net/CallAnsiPlugin_plug-in.
It looks that it already can do what I need. I will try it.
TrifonovS is offline   Reply With Quote
Old 5th July 2018, 06:51   #30
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
I read in Internet that this plug-in will not going to work by sub-classing? Is this so?
TrifonovS is offline   Reply With Quote
Old 5th July 2018, 10:03   #31
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,814
Quote:
Originally Posted by TrifonovS View Post
I read in Internet that this plug-in will not going to work by sub-classing? Is this so?
Yes and I already told you that it will not work.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 5th July 2018, 10:10   #32
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
The problem is that I don't have an idea how to create a helper ANSI app. I'm embedded programmer. That's why I desperately search a ready solution.
TrifonovS is offline   Reply With Quote
Old 5th July 2018, 10:37   #33
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,814
Just create a NSIS ANSI installer that does whatever you need when it reboots. Extract it to $pluginsdir and start it before the thing that is going to reboot.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 5th July 2018, 11:08   #34
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
That's clear. This is what came to my mind too, but I thought that I didn't understand correct your idea. It's a little bit ugly, but it's a job that I can do alone. Thank you for the help!
TrifonovS is offline   Reply With Quote
Old 6th July 2018, 00:13   #35
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,814
I uploaded a Unicode version of the WndSubclass plug-in to the wiki.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 11th July 2018, 13:01   #36
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
Thank you very much Anders!!! It works perfect. I made what I want in my installer, using the new unicode version of the WndSubclass plug-in and all works fine.
TrifonovS is offline   Reply With Quote
Old 12th July 2018, 08:59   #37
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
Unfortunate I see another problem. It could be in my code, but I cannot find it. The installer crashes sometimes (most of the time) during the installation. Since the usage of the plug-in is the only new thing, I tried to comment the line where I'm calling it and the crash doesn't occur anymore. Here is the line:

${WndSubclass_Subclass} $HWNDPARENT GetWinMessage $GetWinMessage $GetWinMessage

$GetWinMessage is a defined variable and GetWinMessage is the name of my callback function.

This is all that I'm using from the plug-in. I don't use ${WndSubClass_Ret} and ${WndSubClass_CallNextWndProc} macros. Am I doing something wrong? I used the DLL from the folder x86-unicode.
TrifonovS is offline   Reply With Quote
Old 12th July 2018, 10:12   #38
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,814
Can you modify example1.nsi or something simple to make it crash?

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 12th July 2018, 10:28   #39
TrifonovS
Senior Member
 
Join Date: Apr 2009
Location: Bulgaria
Posts: 174
I will try, but first I want to report what I have seen additionally. Before the crash I opened the Details field and the last line before the crash is always different and very strange. Here are the results after several executions of the installer:

Execution 1:
Could not find symbol: t

Execution 2:
Could not load: 0x0011\System.dll

Execution 3:
There is no additional line

My OS is Windows 7 64-bit version.
What is the reason for the messages from Execution 1 and 2?
TrifonovS is offline   Reply With Quote
Old 12th July 2018, 10:33   #40
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,814
Very strange. I hope you are not calling WndSubclass_Subclass from a section? You need to use the page init/show callback.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Reply
Go Back   Winamp & SHOUTcast Forums > Developer Center > NSIS Discussion

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump