2012-12-18 124 views
0

當下載.exe安裝文件(NSIS安裝)並通過chrome打開它以執行它時,ExecWait不起作用。通過Chrome瀏覽器安裝安裝文件時,NSIS ExecWait無法等待

我運行一個批處理文件,從而殺滅安裝的瀏覽器裏面的過程, 因爲我通過瀏覽器(下載管理器)打開exe文件的ExecWait認爲,執行已經結束,因此這麼想的等待下一個ExecWait將調用執行該批處理文件的行。它認爲chrome是父進程,所以它會退出安裝。

有沒有辦法讓ExecWait知道盡管我終止了Chrome瀏覽器(或任何其他瀏覽器)的進程來繼續安裝?並只等待我通過NSIS腳本執行的.exe文件?

P.S - 當從瀏覽器(下載管理器)安裝.exe文件時,它工作正常。

EDIT(我已經包括代碼):

# 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 

和INSTALL.EXE的內部(其一個bat文件的I編譯成.exe文件)這樣的代碼:

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

如果您通過chrome下載setup.exe並從底欄(下載管理器)執行setup.exe,它將執行install.exe(關閉chrome.exe),但會跳過下列行:

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

你的症狀很奇怪。你能用'ExecWait'來發表一些代碼來顯示nsis的部分嗎? – Seki

+0

我已經包含了nsis代碼和說明。謝謝! –

+0

爲什麼使用重命名批處理文件到.exe的巨大黑客攻擊? – Anders

回答

0

ExecWait 總是等待子進程就開始,但它不會等待孫子。如果你需要這樣做,你可以嘗試this macro。如果他們正在做一些重要的選項?如果他們正在做一些重要的事情,那麼你應該讓用戶關閉它。

+0

爲什麼這個孫子孫女? execwait住在setup.exe的右邊? isnt install.exe和test.exe是孩子嗎?那麼爲什麼execwait連接到Chrome瀏覽器?是的install.exe和test.exe是孫子進程,但我不明白爲什麼你用你提到的方式連接execwait .. –

+1

當你使用ExecWait $ INSTDIR \ install.exe時,它只會等待install.exe而不是東西由install.exe啓動。嘗試用「call taskkill ...」替換「taskkill ...」或者在taskkill後添加「ping localhost」。或者,也許使用一個插件來殺死進程:http://nsis.sourceforge.net/Category:Plugins – Anders

+0

我用KillProcDLL :: KillProc和它的工作!非常感謝您的幫助! –

0

所以,如果我理解正確的話:

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

因此,要回答你的問題:沒有沒有故意讓Chrome所開始建立抵禦力殺(因爲它實際上是殺害/T參數會使用子進程殺死整個進程子樹)。你只是削減你站在:)

分支如果你需要殺死瀏覽器,我建議儘量從自身產卵的downloaded_setup.exe的第二個副本,但是從調用進程分離(見CreateProcess flags)。

在設置的第二個實例中,您可以使用get process info macros測試它的父級(父級PID的進程名稱是否爲chrome)來檢查您是否是第二級進程。


編輯:我錯誤地解釋了DETACHED_PROCESS標誌的含義爲CreateProcess:它的用途是控制檯程序,不要讓他們使用由他們的父母繼承的控制檯。

實際上,要使一個進程與其父A分離,唯一的方法是啓動一個進程B,它將啓動一個進程C並退出進程B.然後進程C不再是A的後代,並且如果你殺A,C會保持活力。

爲了概念proff的樂趣,這裏是一個NSIS腳本,如果由Chrome啓動,它將自行重建。如果您在消息框顯示時使用ProcessExplorer或ProcessHacker查看過程,您將看到可見的設置不是chrome的子節點。由於安德斯幫助我的號召調試到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 
+0

那裏有一個nsis腳本示例嗎?它似乎很難..如何創建一個從鉻樹分離的新進程..? –

+0

我搜索了並找不到任何建議如何從setup.exe創建分離進程的任何內容。如果您能爲我解決此問題設定一個方向,我將非常感激,謝謝! –

+0

當問題得到解答時,爲了好玩,我做了一個關於如何使用NSIS創建分離過程的概念證明。看我的編輯。 – Seki

0

你有沒有試過直接調用taskkill?

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