【问题标题】:NSIS ExecWait dosen't wait when installing the setup file via chrome browser通过 chrome 浏览器安装设置文件时,NSIS ExecWait 不会等待
【发布时间】:2012-12-20 18:57:30
【问题描述】:

当下载 .exe 安装文件(NSIS 安装)并通过 chrome 打开它以执行它时,ExecWait 不起作用。

我正在运行一个批处理文件,它会在安装过程中杀死浏览器进程, 因为我通过 chrome(下载管理器)打开了 exe 文件,所以 ExecWait 认为执行已经结束,因此不要等待下一个 ExecWait 调用,该调用位于调用执行批处理文件的行之后。它认为chrome是父进程,所以它退出了安装。

有没有办法让 ExecWait 知道尽管我终止了 chrome 浏览器(或任何其他浏览器)进程以继续安装?并且只等待我通过 NSIS 脚本执行的 .exe 文件?

P.S - 从浏览器(下载管理器)安装 .exe 文件时,它工作正常。

编辑(我已包含代码):

# 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 文件,我编译成一个 .exe 文件)内部,这段代码:

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

如果您通过 chrome 下载 setup.exe 并从底部栏(下载管理器)执行它,它将执行 install.exe(关闭 chrome.exe)但会跳过以下行:

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

【问题讨论】:

  • 你的症状很奇怪。你能用ExecWait发布一些显示nsis部分的代码吗?
  • 我已经包含了 nsis 代码和描述。谢谢!
  • 为什么要使用像将批处理文件重命名为 .exe 这样的大技巧?
  • 如果用户有另一个程序也叫 chrome.exe 怎么办?

标签: installation nsis


【解决方案1】:

ExecWait 总是等待它启动的子进程,但它不等待孙子进程。如果你需要这样做,你可以试试this macro

恕我直言,像这样杀死浏览器并不酷(如果他们在选项卡中执行重要操作怎么办?),您应该要求用户关闭它。

【讨论】:

  • 为什么是孙子? execwait 位于 setup.exe 中,对吗?不是 install.exe 和 test.exe 是孩子吗?那么为什么 execwait 连接到 chrome 浏览器呢?是的 install.exe 和 test.exe 是孙进程,但我不明白为什么 execwait 以你提到的方式连接..
  • 当你使用 ExecWait $INSTDIR\install.exe 时,它​​只会等待 install.exe 而不是 install.exe 启动的东西。尝试用“call taskkill ...”替换“taskkill ...”或在taskkill之后添加“ping localhost”。或者使用插件杀死进程:nsis.sourceforge.net/Category:Plugins
  • 我使用了 KillProcDLL::KillProc 并且它成功了!非常感谢您的帮助!
【解决方案2】:

你试过直接调用taskkill吗?

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

【讨论】:

    【解决方案3】:

    所以,如果我理解正确的话:

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

    所以回答你的问题:不,没有办法让 Chrome 启动的设置抵抗强制终止(它实际上是因为 /T 参数杀死了带有子进程的整个进程子树)。你只是在砍你站在的树枝:)

    如果您确实需要杀死 Chrome,我建议尝试从其自身生成第二个 downloaded_setup.exe 副本,但与调用进程分离(请参阅 CreateProcess flags)。

    在设置的第二个实例中,您可以通过使用 get process info macros 测试其父进程(父 pid 的进程名称是否为 chrome)来检查您是否是第二个进程。


    编辑:我错误地解释了CreateProcessDETACHED_PROCESS 标志的含义:它的用途是用于控制台程序,而不是让它们使用父级继承的控制台。

    实际上,要使进程与其父进程 A 分离,唯一的方法是启动进程 B,该进程将启动进程 C 并退出进程 B。然后进程 C 不再是 A 的后代,如果你杀死A、C 会活着。

    为了概念的乐趣,这里有一个 NSIS 脚本,如果由 Chrome 启动,它将自行重生。如果您在消息框显示时使用 ProcessExplorer 或 ProcessHacker 查看进程,您将看到可见设置不是 chrome 的子级...感谢 Anders 帮助我调试对 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
    

    【讨论】:

    • 那里有 nsis 脚本示例吗?这似乎很困难..如何创建一个与 chrome 树分离的新进程..?
    • 我搜索并找不到任何建议如何从 setup.exe 创建分离进程的内容。如果您能给我一个解决这个问题的方向,我将不胜感激,谢谢!
    • 在回答问题时,为了好玩,我对如何使用 NSIS 创建分离进程进行了概念验证。查看我的编辑。
    猜你喜欢
    • 1970-01-01
    • 2015-12-13
    • 2018-01-12
    • 1970-01-01
    • 2012-01-25
    • 1970-01-01
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多