2013-02-27 96 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)的情況下才運行子級。