No announcement yet.

Help with getting installer/uninstaller to wait for an external program

  • Filter
  • Time
  • Show
Clear All
new posts

  • Help with getting installer/uninstaller to wait for an external program

    I am trying to get my NSIS installer/uninstaller to wait for an external program called by the installer to complete. I have tried ExecWait as well as ExecDos and the ExecWaitJob macro, and whatever I try, the installer will not wait (or in the case of the ExecWaitJob macro either doesn't wait or freezes before calling the external program). I have tried directly running the executable I need to run, as well as running it via a batch file. With the batch file, I made sure to start the file with @Echo off, and end with cls per instructions in the wiki. I also tried dumping the EXE's output to a file, since it does print messags, and no luck. The main problem is on the uninstall, as files I need for the external program get deleted before the program can run. I suspect the external program is the culprit, but I can't modify it. Any suggestions to get around this with NSIS? Thanks.

    The batch file is just:
    @echo off

    Or I've tried:
    @echo off
    start /wait [program.exe]. (both with and without /b switch)

  • #2
    ExecWait always waits for the child process, when you say it does not wait then it means that this child process starts child processes of its own and ExecWait does not wait for those. First you should investigate if the thing you are running supports some type of command line parameter that makes it "waitable" and if it does not have one then the only solution is NT job objects.

    Show me how you call the macro and I'll take a look this weekend...
    IntOp $PostCount $PostCount + 1


    • #3
      I have tried using a cmd file as below:
      ExecWait '"c:\program files\[company name]\usbdriver\uninst64.cmd"
      as well as
      ExecWait '"c:\program files\[company name]\usbdriver\wdreg.exe -inf file.inf -silent -delete_files uninstall"'

      and what always happens is that the installer deletes the files before they can run even though the delete commands come after the ExecWait commands.

      Because the program I am calling always prints out its version when it starts, I tried piping the output to a file (i.e. wdreg.exe ... >>file.txt, and that doesn't help either. I did find the source for that program, and even tried commenting out the print line in it, without luck. As far as I can tell from that program, it doesn't call any other programs. As I said before, I suspect that that particular program is the issue, as start /wait doesn't work with it either. I should note that the wdreg.exe program is a console mode application.

      Unfortunately, the program does not have a wait option, either. To be honest, I am not sure what NT job objects are.

      I've attached a copy of my cmd file, renamed with a .txt extension, as well as a copy of the nsi file with names redacted.

      Thank you very much for your help.
      Attached Files


      • #4
        ExecWait '"c:\program files\company name\usbdriver\wdreg.exe -inf usb64.inf -silent -delete_files uninstall"' has broken quotes, it should be ExecWait '"c:\program files\company name\usbdriver\wdreg.exe" -inf usb64.inf -silent -delete_files uninstall'.

        I still need to see how you use ExecWaitJob if you want me to investigate that.

        It might also be a good idea if you download Process Monitor and log the process and thread activity. Pressing Ctrl+T will show a process tree and you should be able to tell if there are any child processes that you are not waiting for.
        IntOp $PostCount $PostCount + 1


        • #5
          I fixed the broken quotes per your instructions, and unfortunately, execwait is still not waiting. Below is how I tried to use ExecWaitJob. In my test, it appears that by the time wdreg.exe is even called, either via ExecWait or ExecWaitJob, the delete stuff below has already happened. I then get the message that wdreg couldn't be found.

          StrCpy $8 'cmd /k start "" "c:\program files\[companyname]\usbdriver\uninst64.cmd"'
          !insertmacro ExecWaitJob r8


          • #6
            What is r8 used for? If it's a variable, it should be $8.
            "Only a MouseHelmet will save you from a MouseTrap" -Jason Ross (Me)
            NSIS 3 POSIX Ninja
            Wiki Profile


            • #7
              Originally Posted by JasonFriday13 View Post
              What is r8 used for? If it's a variable, it should be $8.
              No r8 is correct because that macro is weird IIRC.
              IntOp $PostCount $PostCount + 1


              • #8
                I also forgot to mention that I've called ExecWaitJob with the exe itself as in:
                StrCpy $8 'cmd /k start "" "c:\program files\[company name]\usbdriver\wdreg.exe -inf file.inf -silent -delete_files uninstall"'
                !insertmacro ExecWaitJob r8

                Without luck as well. Any suggestions? Thanks.


                • #9
                  I already told you that you need to use the double quotes correctly, you quote the filename/path but not the parameters. Also, you don't need cmd.exe to run another .exe!
                  IntOp $PostCount $PostCount + 1


                  • #10
                    Actually, I tried it both with and without the call to cmd, and with the correct quotes without luck. I didn't check the quotes when I pasted it. I also tried calling my .cmd file, as below:

                    StrCpy $8 'cmd /k start "" "c:\program files\[companyname]\usbdriver\driveruninst64.cmd"'

                    without luck.

                    I did go back and try again with the correct quotes with ExecWaitjob, calling the executable, and it seems to work now. I thought I tried the current iteration, including options to the executable, with correct quotes before, but I must not have. See below:

                    StrCpy $8 'cmd /k start "c:\program files\[company name]\usbdriver\wdreg.exe" -inf usb64_drv.inf -silent -delete_files uninstall'
                    !insertmacro ExecWaitJob r8

                    I am just glad it appears to be fixed now. I'd have preferred calling my cmd file, as it hides things a bit better, but I will go with what works. Thanks for the help.


                    • #11
                      I still don't understand why you insist on using cmd.exe to start a .exe and don't use /k, use /c if you must.
                      IntOp $PostCount $PostCount + 1


                      • #12
                        Well, whatever the reason, the last two code lines I pasted *finally* actually wait, even though I shouldn't need the cmd /k in there. I just tried it again without the cmd, with the below code, and it works also.

                        StrCpy $8 '"c:\program files\[company name]\usbdriver\wdreg.exe" -inf usb64_drv.inf -silent -delete_files uninstall'
                        !insertmacro ExecWaitJob r8

                        I was sure I went back and tried ExecWaitJob with correct quotes before, but I must've either just tried with the .cmd file. In any case, it is finally working, so I'm happy. Thanks.


                        • #13
                          Sorry for my stupid question, but I have some problems to convert this macro to a function. I don't understand completely why we copy the path to the variable $8 and then we give like a parameter to the macro R8 instead of $8. When I make a function based on this macro it doesn't work and I think that this is exactly because I done give the parameter correctly. Some help, please...


                          • #14
                            I solved my problem. I have to get the parameter with Pop $8, but in the lines that the value must be used I have to write:
                            System::Call 'kernel32::CreateProcess(i0,t r8,i0,i0,i0,i 0x01000004,i0,i0,i $4,i $0)i.r3'
                            It works now!


                            • #15
                              It's not waiting any more no matter what I do. I also tried updating to NSIS v3.03.