Yes and I already told you that it will not work.Originally Posted by TrifonovS View PostI read in Internet that this plug-in will not going to work by sub-classing? Is this so?
Execute actions before reboot
64 posts
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.
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.
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!
I uploaded a Unicode version of the WndSubclass plug-in to the wiki.
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.
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.
${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.
Can you modify example1.nsi or something simple to make it crash?
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?
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?
Very strange. I hope you are not calling WndSubclass_Subclass from a section? You need to use the page init/show callback.
I don't call it in a section. Here is a part of my code:
...
!define MUI_PAGE_CUSTOMFUNCTION_SHOW InstFilesShow
!insertmacro MUI_PAGE_INSTFILES
...
; Function that is called when the installation dialog is shown
Function InstFilesShow
; Set a function that will receive the messages to the parent window
${WndSubclass_Subclass} $HWNDPARENT GetWinMessage $GetWinMessage $GetWinMessage
FunctionEnd
...
; Function that receives the messages to the parent window
Function GetWinMessage
${If} $2 = ${WM_QUERYENDSESSION}
...
${EndIf}
...
FunctionEnd I'm currently simplifying my script to be able to reproduce the problem easier. Unfortunately this is not an easy task, because the script is very complex. However I came to much simpler code that uses WndSubclass plug-in together with my special macro that makes copy of some files from the installer to some Windows folders. Now I can reproduce another crash, but I still think that the reason is the same. My macro contains on two places the following line:
When I comment the line that calls the macro ${WndSubclass_Subclass} all works fine. Is this information helpful?
SetOutPath "$TEMP" First time when this line is executed, I see the correct path in the Details:Output folder: C:\Users\UserName\AppData\Local\Temp But the second time when this line is reached the path is the following:Output folder: 0x0011 It seems that the content of the system variable $TEMP is changed. I don't do this in my script (at least not intentionally 🙂).When I comment the line that calls the macro ${WndSubclass_Subclass} all works fine. Is this information helpful?
It is certainly possible that I messed up and have a bad pointer offset somewhere or a problem with message recursion. A complete example might still be required but I can try to take a look to see if I can reproduce it.
OK! The example is still too complex to send it to you, but I will continue with the reduction.
It might just be threading issues, NSIS was not designed to be thread safe and the sections are executed in a different thread.
Ans what could be the solution? Is it still useful to try to simplify my script for further investigation?
Probably not, it's best to just give up. My guess is that GetNSISString in the stub uses a single temporary buffer and when you access strings from multiple threads at the same time things go wrong and there is not much a plug-in can do about that.Originally Posted by TrifonovS View PostIs it still useful to try to simplify my script for further investigation?
The solution is to not subclass $hwndparent nor any other window on the instfiles page.
And what about the initial idea to make a helper application that is started in parallel f the installer's executable? Do you expect the same problems?
Should be OK as long as you don't call any instructions that takes a variable as a parameter in any sections.Originally Posted by TrifonovS View PostAnd what about the initial idea to make a helper application that is started in parallel f the installer's executable? Do you expect the same problems?
I made a helper application, but I need some more help. This helper application is programmed with the installer's script. This is the easiest way for me, since I'm not a PC programmer and programming on C++ is more difficult to me.
The problem now is that my application works fine if I show a dialog. I though that if I make it silent the dialog won't be shown, but in this case also my function that uses the plug-in is not called too (that's logical). Then I tried to call the plug-in in .onInit function, but it doesn't work. Is there a way to make this application without user interface and still to call correct the plug-in?
The problem now is that my application works fine if I show a dialog. I though that if I make it silent the dialog won't be shown, but in this case also my function that uses the plug-in is not called too (that's logical). Then I tried to call the plug-in in .onInit function, but it doesn't work. Is there a way to make this application without user interface and still to call correct the plug-in?
You have to use a hack and just hide the UI in a section. ShowWindow does not parse its parameter and should be OK IIRC.
I thought that I'm almost ready, but now another problem appeared. When I detect a message WM_QUERYENDSESSION, I write something in Windows registry (just before the reboot). But actually there is nothing written in the registry. I'm sure that the line of the script is executed, because I have some prints before and after this action. If I write the same thing before the check for this specific message, all works fine. I cannot find an explanation and solution about this...
And your code looks like this?
Function MySubProc
${if} $2 = ${WM_QUERYENDSESSION}
writeregstr ...
${endif}
FunctionEnd
Yes, this is exactly my code. But I thing that the code works fine, just the Regedit cannot show the change... I actually write an entry in RunOnce section to be able to call my installer after reboot. Now I saw that it works. But if I initiate Windows restart, than I cancel it, I don't see my entry (I check it with Regedit). If I reboot, it works!... I can't explain it.
Since NSIS is a 32-bit app, if you didn't use the command "SetRegView 64", then your entry will be automatically redirected to WOW6432Node, e.g.,
instead of e.g.,HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\RunOnce
As you discovered, it'll still work from that location, it's just confusing if you go looking for it with the Registry Editor.HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
Yes, I know this and I'm looking in the right area with Regedit:
HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\RunOnce
So this doesn't explain my observation...
HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\RunOnce
So this doesn't explain my observation...
My only other thought is you're looking in the wrong root (HKLM vs HKCU).
I checked everywhere, but there is no entry like mine. But if I call the same line of script (that writes the value in the registry), in another position in my function (for example before the check ${if} $2 = ${WM_QUERYENDSESSION}) I can see my entry exactly when I expect it in the registry. It is really strange, but I think that this is not a problem, because as I said it actually works. And I also tested it on my Windows 7 64-bit. Maybe it will be different under Windows 10...
By the way, one more question (I hope the last for this topic 🙂). In my helper application a dialog is shown and immediately hidden (as Anders advised me). This works fine, but the dialog can be seen for a part of a second. Is there any chance to avoid this visual problem?
By the way, one more question (I hope the last for this topic 🙂). In my helper application a dialog is shown and immediately hidden (as Anders advised me). This works fine, but the dialog can be seen for a part of a second. Is there any chance to avoid this visual problem?
Start it minimized with ExecShell or move it off-screen in .onGuiInit.
So far so good. It looks that all works fine now... more tests are needed. Thanks for the good support.