2013-02-27 21 views
0

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

我的问题是,我怎么能调用子安装程序,从而:
一)用户将与UAC对话框(如果启用UAC)提示,并
b)儿童安装程序,如果被终止用户在给定的时间段内不会单击“是”或“否”。

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

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

我得到很失望在这里 - 任何帮助,将不胜感激。

回答

0

UAC没有被设计为支持这一点,任何试图做这应该被视为一个黑客!问题的

部分原因是,在的ShellExecuteEx的过程是提升操作的一部分,因此它不能而不杀死线程或进程被杀死。为了解决这个问题,我允许安装程序充当一个可以杀死的中间人。这种设计的一个缺陷是UAC对话框在超时终止进程后仍然存在(UAC GUI处于以system身份运行的consent.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)的情况下才运行子级。