Archive: How to use switch /sms?


How to use switch /sms?
I call ExecWait with the switch /sms to make the uninstaller wait until it is done. But it doesn't wait. Here is how I use it.

ExecWait '"$R0" /sms'

Here $R0 is an executable. Thanks.


/sms is not a NSIS switch...


Originally posted by Anders
/sms is not a NSIS switch...
I see. So how can I do the similar thing like /sms in NSIS? Thanks.

What does /sms do?


Originally posted by T.Slappy
What does /sms do?
/sms makes ExecWait wait until the current uninstallation is done.

Originally posted by JohnChen
I call ExecWait with the switch /sms to make the uninstaller wait until it is done. But it doesn't wait. Here is how I use it.

ExecWait '"$R0" /sms'

Here $R0 is an executable. Thanks.
FYI, _?=$INSTDIR' works for me. It looks like _?=$INSTDIR' works with NSIS ExecWait. Thanks.

Originally posted by JohnChen
FYI, _?=$INSTDIR' works for me. It looks like _?=$INSTDIR' works with NSIS ExecWait. Thanks.
Does any one know why _?=$INSTDIR ? I found it on the web but I don't really know what it is. Thanks.

It has nothing to do with ExecWait really. All it does is stops the uninstaller copying itself to %TEMP% and relaunching from there (i.e. spawning a new process and so the old process closes; ExecWait returns).

http://nsis.sourceforge.net/Docs/Chapter3.html#3.2.2

Stu


An answer
/sms is an old switch from InstallShield 3 and InstallShield 5 installers (popular around the Windows 95/98 era, InstallShield 6 did away with /sms - it came out around the time of Windows 2000)

What it did:

Back then, you would see "Setup is preparing the InstallShield wizard..." along with a progress bar. That EXE would immediately exit upon launch of the main installer (I'm talking installer, not uninstaller). SMS is Microsoft's Systems Management Server (I don't think they make it any more) and calling an InstallShield EXE with /sms was how you got SMS (or any other program, like a parent installation calling a 3rd party redist installer) to WAIT for installation to finish. My guess is that InstallShield assumed most people needing to keep a parent waiting were using Microsoft's SMS (thus why the switch is "/sms")

An alternative would be the old WinZip Self-Extractor being told to wait for a program called _ISDEL to run (this would clean up InstallShield EXE temporary files after installation is completed).

Granted, these were done in enterprises long before Microsoft came out with Windows Installer, and this is the very old way to do it.


Hope this answers any questions on what /sms is. I haven't seen it discussed in years


Assuming you're trying to uninstall a program from a parent uninstaller (and you want the parent uninstaller to wait for the child), here's how to duplicate:

In this example, the child program uninstaller is called uninstall.exe and the child program is installed to C:\Program Files (x86)\Program 2\

1. Your parent uninstaller needs to COPY the child's uninstaller EXE to another folder such $TEMP. This is because Windows doesn't allow an EXE to delete itself
2. the PARENT uninstaller would then call ExecWait $TEMP\uninstall.exe _?=C:\Program Files (x86)\Program 2\. (this path shouldn't be hard coded - your uninstaller should use a registry key/value (for example, as it's fastest) to grab the path of the child)


Originally posted by RaggieSoft
Assuming you're trying to uninstall a program from a parent uninstaller (and you want the parent uninstaller to wait for the child), here's how to duplicate:

In this example, the child program uninstaller is called uninstall.exe and the child program is installed to C:\Program Files (x86)\Program 2\

1. Your parent uninstaller needs to COPY the child's uninstaller EXE to another folder such $TEMP. This is because Windows doesn't allow an EXE to delete itself
2. the PARENT uninstaller would then call ExecWait $TEMP\uninstall.exe _?=C:\Program Files (x86)\Program 2\. (this path shouldn't be hard coded - your uninstaller should use a registry key/value (for example, as it's fastest) to grab the path of the child)
If the uninstaller has one parameter, so I thought I should call ExecWait like this,'
ExecWait '"$0" "$1" "_?=$INSTDIR"'
Here $0 is uninstaller and $1 is its parameter. But I got an error like "Parsing Failed: Unable to open file _?". What did I wrong? Thanks.

Read the manual page that I linked to.

Stu


Originally posted by Afrow UK
Read the manual page that I linked to.

Stu
Actually I did. The manual page you linked to contains some examples demonstrating how to use ExecWait with _?=. But in those examples, the uninstaller doesn't take any parameter. My specific problem is related to that when the uninstaller takes one parameter, ExecWait failed with error message like "Parsing Failed: Unable to open file _?"
Here is how I did,
ExecWait '"$0" "$1" "_?=$INSTDIR"'
$0 is the uninstaller and $1 is its parameter. Is there anything wrong in this statement? Thanks.

You missed this:

It must be the last parameter used in the command line and must not contain any quotes, even if the path contains spaces.
Edit: I.e. ExecWait '"$0" "$1" _?=$INSTDIR'

Stu

Originally posted by Afrow UK
You missed this:Edit: I.e. ExecWait '"$0" "$1" _?=$INSTDIR'

Stu
Unfortunately this one doesn't work either. Say if $INSTDIR = "C:\Another folder\Myfolder", I got a similar error like "Parsing Failed: Unable to open file folder\Myfolder". Notice that there is a space between "Another" and "folder".

Based on your solution, here is the summary,

ExecWait '"$0" "$1" _?=C:\Another folder\Myfolder'
error msg: Unable to open file folder\Myfolder

ExecWait '"$0" "$1" _?=C:\Temp'
error msg: Unable to open file _?

Errors above happen only when the uninstaller($0) takes one parameter. If the uninstaller doesn't take any parameter, it works fine for both cases. Any idea why? Thanks a lot.

I've never encountered that error. I will look in the source code when I can. Just to be sure, it is an NSIS uninstall executable you are running, not some other one?

Stu


Originally posted by Afrow UK
I've never encountered that error. I will look in the source code when I can. Just to be sure, it is an NSIS uninstall executable you are running, not some other one?

Stu
Yes, I am sure I am running NSIS. Have you ever tried the case where you use ExecWait to run the uninstaller which takes one parameter together with "_?=" option ? Thanks.

Yes I have tried. This works:

!include MUI2.nsh

OutFile TestUninstall.exe
InstallDir $EXEDIR

!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_LANGUAGE English

Section

WriteUninstaller $INSTDIR\un.exe
ExecWait `"$INSTDIR\un.exe" /a /b _?=$INSTDIR`
Delete $INSTDIR\un.exe

SectionEnd

Section Uninstall
SectionEnd
Stu

I can't find a "Parsing Failed: Unable to open file" in the source code so I highly doubt your uninstall executable is an NSIS one (i.e. generated with WriteUninstaller). NSIS only has a generic "Error launching installer" message. You do realise that _?= is specific to NSIS uninstall executables...

Stu


Originally posted by Afrow UK
Yes I have tried. This works:
!include MUI2.nsh

OutFile TestUninstall.exe
InstallDir $EXEDIR

!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_LANGUAGE English

Section

WriteUninstaller $INSTDIR\un.exe
ExecWait `"$INSTDIR\un.exe" /a /b _?=$INSTDIR`
Delete $INSTDIR\un.exe

SectionEnd

Section Uninstall
SectionEnd
Stu
Thanks for your reply. But /a or /b is not considered as a parameter of un.exe and they are just switch. A uninstaller with a switch works for me too. The only problem for me is that if a uninstaller takes a parameter. For example, if un.exe needs a file as an input parameter, you would call ExecWait like this,

ExecWait `"$INSTDIR\un.exe" "$INSTDIR\someFile.txt" _?=$INSTDIR`

I wonder if it works for you too? Thanks a lot.

But /a or /b is not considered as a parameter of un.exe and they are just switch.
There is no difference between a 'parameter' and a 'switch'. A program simply splits up the tokens on its command line with whitespace as the delimiter. If you tried the code yourself you'd see it works fine substituting /a with "$INSTDIR\someFile.txt".

Edit: And the uninstaller doesn't care whether the parameter begins with / or not. It only looks for the first token that begins with _?=, removes that (and proceeding tokens) and then puts the remainder into $CMDLINE which you can use from your uninstall code. It is up to your uninstaller code to handle the parameters from there.

Stu

Originally posted by Afrow UK
There is no difference between a 'parameter' and a 'switch'. A program simply splits up the tokens on its command line with whitespace as the delimiter. If you tried the code yourself you'd see it works fine substituting /a with "$INSTDIR\someFile.txt".

Edit: And the uninstaller doesn't care whether the parameter begins with / or not. It only looks for the first token that begins with _?=, removes that (and proceeding tokens) and then puts the remainder into $CMDLINE which you can use from your uninstall code. It is up to your uninstaller code to handle the parameters from there.

Stu
Before I discuss further, may I ask a simple question? Who is responsible for parsing _?= part? Thanks.

Originally posted by Afrow UK
I can't find a "Parsing Failed: Unable to open file" in the source code so I highly doubt your uninstall executable is an NSIS one (i.e. generated with WriteUninstaller). NSIS only has a generic "Error launching installer" message. You do realise that _?= is specific to NSIS uninstall executables...

Stu
This is very possible. Thanks for your information. Actually the uninstaller in question is a third party uninstaller. If this third party uninstaller is not a NSIS one, is there any way to make it work like a NSIS one? Thanks.

_?= is specific to NSIS uninstall executables (i.e. those generated via WriteUninstaller). The NSIS uninstaller, when executed with this option, automatically handles _?= itself. ExecWait does not handle _?= (perhaps this is what you are confused about). You can use _?= via cmd.exe or via a shortcut; it doesn't matter.

Therefore, you must be trying to execute an uninstall executable which does not know what _?= is (because it's not an NSIS uninstall executable).

Stu


If this third party uninstaller is not a NSIS one, is there any way to make it work like a NSIS one?
You'll need to find out what uninstaller it is (i.e. is it Wise, InnoSetup etc.) and determine the correct command line argument to use to prevent it from spawning a new process.

Stu

Originally posted by Afrow UK
_?= is specific to NSIS uninstall executables (i.e. those generated via WriteUninstaller). The NSIS uninstaller, when executed with this option, automatically handles _?= itself. ExecWait does not handle _?= (perhaps this is what you are confused about). You can use _?= via cmd.exe or via a shortcut; it doesn't matter.

Therefore, you must be trying to execute an uninstall executable which does not know what _?= is (because it's not an NSIS uninstall executable).

Stu
How can I use WriteUninstaller in a uninstall section? In a uninstall section functions are expected to have un.. But un.WriteUninstaller is not defined. Thanks.

Are you getting confused on something else now? Look up WriteUninstaller in the manual. Perhaps you should explain what you are trying to achieve...

Stu


Originally posted by Afrow UK
Are you getting confused on something else now? Look up WriteUninstaller in the manual. Perhaps you should explain what you are trying to achieve...

Stu
Actually, I was trying to use WriteUninstaller to convert a non-NSIS uninstaller to a NSIS uninstaller. But it doesn't look like it works that way. So if I get a non-NSIS uninstaller, is there any way I can use in NSIS? Thanks.

Well logically you have two options:

1. Convert the 3rd party uninstaller to NSIS by writing NSIS script
2. Execute the existing one (as you are trying to do)

The 2nd option is easiest obviously.

Stu


Originally posted by Afrow UK
Well logically you have two options:

1. Convert the 3rd party uninstaller to NSIS by writing NSIS script
2. Execute the existing one (as you are trying to do)

The 2nd option is easiest obviously.

Stu
But if I choose 2nd option, the existing uninstaller doesn't know how to parse _?=. If I choose 1st option, would you please provide me a sample script how to convert the 3rd party uninstaller to NSIS? Thanks a lot.

As I said before, you need to identify the type of uninstaller and find a suitable switch which does what _?= does in NSIS uninstallers. And I don't mean to write NSIS script to do the conversion lol... you need to follow the tasks the 3rd party uninstaller does and do those tasks in your NSIS uninstall script. Run the 3rd party uninstaller from a sandbox such as Sandboxie. That is what I have done in the past.

Stu


There is one related issue with using _?= option. Since _?= stops uninstaller from copying itself to the temporary directory, as the result, the uninstaller couldn't be removed(it couldn't remove itself). Since the uninstaller couldn't be removed, the folder where the uninstaller is located couldn't be removed. I wonder if there is way to keep two good things at the same time. One good thing is allow ExecWait to wait for the uninstaller to finish. Another good thing is still allow users to remove the whole folder where the uninstaller is located.


Copy the uninstaller to $PLUGINSDIR and then run it from there with _?=$INSTDIR.

Stu