【问题标题】:Calling an embedded installer in NSIS on UAC with timeout在 UAC 上调用 NSIS 中的嵌入式安装程序并超时
【发布时间】:2013-02-12 21:42:04
【问题描述】:

我有一个具有“RequestExecutionLevel 用户”的 NSIS 安装程序。该安装程序包含一个具有“RequestExecutionLevel admin”的嵌入式 NSIS 安装程序。此子安装程序仅在某些情况下被调用。这样做是为了让某些管理操作可以包含在子安装程序中,并且只有在必要时才会提示用户进行 UAC 批准。

我的问题是,如何调用子安装程序以便:
a) 将使用 UAC 对话框提示用户(如果启用了 UAC),并且
b) 如果用户在给定的时间段内没有单击是或否,子安装程序将被终止。

我一直在使用 ShellExecWait (http://nsis.sourceforge.net/ShellExecWait),效果很好,但没有提供指定超时值的选项(即它将永远等待)。

请注意,我已经尝试使用以下 NSIS 函数:
* ShellExecWait - 不允许超时
* ExecWait - 子安装程序失败,因为它继承了父安装程序的执行级别。
* ExecShell - 不允许超时
* nsExec::Exec - 子安装程序失败,因为它继承了父安装程序的执行级别。

我在这里变得非常绝望 - 任何帮助将不胜感激。

【问题讨论】:

    标签: timeout nsis uac


    【解决方案1】:

    UAC 并非旨在支持这一点,任何这样做的尝试都应被视为黑客攻击!

    部分问题是您的进程中的 ShellExecuteEx 是提升操作的一部分,因此如果不终止线程或进程就无法终止它。为了解决这个问题,我允许设置充当我们可以杀死的中间人。这种设计的一个缺陷是 UAC 对话框在超时终止进程后仍然存在(UAC GUI 在以系统身份运行的许可.exe 中)这意味着用户可以在主安装程序消失后提升子安装程序!我只在 Win7 上对此进行了测试,如果父级消失了,UAC 不会启动新进程,但这可能是一个错误,或者至少该行为没有记录在 AFAIK 中,并且可能不应该在生产代码中使用!

    Outfile "test.exe"
    RequestExecutionlevel User
    
    !include LogicLib.nsh
    !include WinMessages.nsh
    !include FileFunc.nsh
    
    Page Instfiles
    
    !macro ElevateWithTimeout_OnInit
    ${GetParameters} $0
    ${GetOptions} $0 '--ExecTimer' $1
    ${If} $1 != ""
        StrCpy $1 $0 "" 12
        ExecShell 'runas' $1 ;RunAs is not really required as long as the .exe has a manifest that requests elevation...
        Quit
    ${EndIf}
    !macroend
    Function ElevateWithTimeout
    InitPluginsDir
    System::Call '*(&i60,tsr1)i.r0'
    StrCpy $1 "--ExecTimer $1"
    System::Call '*$0(i 60,i 0x40,i $HwndParent,i0,t"$ExePath",tr1,to,i1)i.r0'
    System::Call 'shell32::ShellExecuteEx(ir0)i.r1'
    System::Call '*$0(i,i,i,i,i,i,i,i,i,i,i,i,i,i,i.r2)'
    System::Free $0
    Pop $0 ; Timeout (MS)
    ${If} $1 <> 0
        System::Call 'kernel32::WaitForSingleObject(ir2,ir0)i.r0'
        ${If} 0x102 = $0 ;WAIT_TIMEOUT
            System::Call 'kernel32::TerminateProcess(ir2,i666)'
        ${EndIf}
        System::Call 'kernel32::CloseHandle(ir2)'
    ${EndIf}
    FunctionEnd
    
    Function .onInit
    !insertmacro ElevateWithTimeout_OnInit
    FunctionEnd
    
    Section
    Push 30000
    Push "regedit.exe"
    call ElevateWithTimeout
    SectionEnd
    

    为了创建一个更安全、更强大的解决方案,子安装程序必须在游戏中并知道如果父程序不在,何时自行中止,但在纯 NSIS 代码中执行此操作的工作量太大。

    我可能会建议您放弃超时要求并在外部安装程序中使用 RequestExecutionlevel highest,并且仅在您是管理员 (UserInfo::GetAccountType) 时运行子级。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-21
      • 2020-03-26
      • 1970-01-01
      • 2016-08-29
      • 1970-01-01
      • 2010-12-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多