NSIS ExecWait dosen't wait when installing the setup file via chrome browser

旧巷老猫 提交于 2020-01-06 20:04:34

问题


When downloading the .exe installation file (NSIS installation) and opening it via chrome in order to execute it the ExecWait dosen't work.

I'm running a batch file which kill browsers processes inside of the installation, because I opened the exe file via the chrome (Download Manager) the ExecWait think that the execute has ended and therefore dosen't wait for the next ExecWait calls that coming after the line which call to execute the batch file. It think that chrome was the parent process so it quitting the installation.

Is there a way to let the ExecWait know that although I killed the chrome browser (or any other browsers) process to continue the installation? and waiting for only the .exe files that I execute via the NSIS script?

P.S - When installing the .exe file out of the browser (download manager) it works fine.

EDIT (I HAVE INCLUDED CODES):

# define the name of the installer
outfile "setup.exe"
Name "Example"

installDir $LOCALAPPDATA\Test

# default section
section

setOutPath $INSTDIR
File install.exe
File test.exe

ExecWait $INSTDIR\install.exe
Delete $INSTDIR\install.exe
ExecWait $INSTDIR\test.exe
Delete $INSTDIR\test.exe

sectionEnd

and inside of the install.exe (its a .bat file the I compile to an .exe file) this code:

@echo off
taskkill /F /IM chrome.exe /T

If you download the setup.exe via chrome and executing it from the bottom bar (download manager) it will execute install.exe (closing chrome.exe) but will skip this lines:

Delete $INSTDIR\install.exe
ExecWait $INSTDIR\test.exe
Delete $INSTDIR\test.exe

回答1:


ExecWait always waits for the child process it started but it does not wait for grandchildren. If you need to do that you can try this macro.

IMHO killing a browser like this is not cool (What if they are doing something important in a tab?), you should just ask the user to close it.




回答2:


Have you tried calling directly to taskkill?

Execwait '"$SYSDIR\taskkill.exe" /F /IM chrome.exe /T'



回答3:


So, if I understand correctly:

Chrome --> downloaded_setup.exe --> install.exe --> force kill chrome w/ child processes

So to answer to you question: no there is no mean to make the setup started by Chrome resist to a force kill (it is actually killed because of the /T parameter that kills the whole process subtree with child processes). You are just cutting the branch you are standing in :)

If you do need to kill Chrome, I would suggest to try to spawn a second copy of downloaded_setup.exe from itself but detached from calling process (see CreateProcess flags).

In the second instance of the setup, you can check if you are the second process by testing its parent (process name of parent pid would be chrome or not) with the get process info macros.


EDIT: i wrongly interpreted the meaning of the DETACHED_PROCESS flag for CreateProcess: its usage is for console programs, to not make them use the console inherited by their parent.

Actually, to make a process detached from its parent A, the only way is to start a process B that will start a process C and quit the process B. Then the process C is no more descendant of A and if you kill A, C will stay alive.

For the fun of proff of concept, here is a NSIS script that will respawn itself if started by Chrome. If you look at the processes with ProcessExplorer or ProcessHacker when the messagebox shows, you will see that the visible setup is not child of chrome... Thanks to Anders that helped me to debug the call to CreateProcess :)

!include "TextFunc.nsh"
!include "logiclib.nsh"
!include "getprocessinfo.nsh"
outfile "parent.exe"

!define DEBUG `System::Call kernel32::OutputDebugString(ts)`

!define PARENT "chrome.exe"
Var cmd

Section
    ; Do your stuff here
    ; ...
SectionEnd

Function .onInit
    ${GetProcessInfo} 0 $0 $1 $2 $3 $4  ;info for current process pid
    ${GetProcessInfo} $1 $0 $1 $2 $3 $5 ;get parent process info

 ${if} $3 == ${PARENT}
    StrCpy $cmd '"$EXEDIR\$EXEFILE"'
    System::Alloc 68            ;// $1 = buffer for struct STARTUPINFO
    Pop $1
    System::Call "*$1(i 68)"    ;// StartUp.cb=sizeof(STARTUPINFO);

    System::Alloc 16            ;// $2 = buffer for struct PROCESS_INFORMATION
    Pop $2

    System::Call 'kernel32::CreateProcess(i0,t $cmd,i0,i0,i0,i0,i0,i0,ir1,ir2)i.r0' ;re-spawn ourselve
    System::Free $1
    ${if} $0 <> 0
        System::Call "*$2(i.r3,i.r4,i.r5,i.r6) ?!e"
        ;${debug} "PHND=$3 PID=$5"
        System::Call 'kernel32::CloseHandle(i $3)'
        System::Call 'kernel32::CloseHandle(i $4)'
    ${endif}
    System::Free $2
    Quit
 ${endif}
    Sleep 500   ;wait to have time for parent process to quit
    MessageBox MB_OK "My parent is not ${PARENT}"
FunctionEnd


来源:https://stackoverflow.com/questions/13933469/nsis-execwait-dosent-wait-when-installing-the-setup-file-via-chrome-browser

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!