1. 程式人生 > >NSIS 自定義安裝介面準確獲取安裝進度完美解決方案

NSIS 自定義安裝介面準確獲取安裝進度完美解決方案



友情提醒:隨著7zip版本快速更新,nsis7z外掛已經不能全面相容新版,使用本例子請將7zip版本降至9.2x以下並下載最新版nsis7z.dll!

----------------------------------------------------------------------------------------------------------------

幾乎所有玩過nsis的人在製作安裝進度頁面時都會遇到一個比較棘手的問題,畫出進度條容易,但準確掌握檔案釋放進度,同時再去配合進度條的進度在nsis看來幾乎是個無法逾越的障礙,因為迄今為止NSIS尚無可直接使用的指令或者函式來獲取相關資料。網路上解決這個問題大部分做法都是大約分為若干段,20%...40%...80%...100%這樣大概做個進度的樣子,其實與釋放的檔案幾乎沒什麼聯絡,並且誤差非常大,我這個辦法可以盡最大可能的讓進度條進度與檔案釋放進度相匹配,腳本里面使用到兩個nsis外掛:

官方下載:

NSIS7Z plug-in

http://nsis.sourceforge.net/Nsis7z_plug-in

BgWorker plug-in

http://nsis.sourceforge.net/BgWorker_plug-in

將你要封裝的檔案按照部署的結構用7zip壓縮備用

原理:自定義介面設定計數器啟動後臺執行緒,然後獲取7z外掛的回撥函式資料。

封裝指令碼:

Outfile "customProgressBar.exe"

!include nsDialogs.nsh
!define /math PBM_SETRANGE32 ${WM_USER} #定義nsis未包含的進度條相關常量
#編寫:水晶石

InstallDir "C:\test"
page custom custompage

Function custompage
nsDialogs::Create 1018
  
Pop $0
  ${NSD_CreateLabel}
100 100 10030"開始安裝..."
  
Pop $9
  
SetCtlColors $9  0x000000 0xECE9D8
  
${NSD_CreateProgressBar} 0 50 10020 ""
  
Pop $8
  ${NSD_CreateTimer}
OnDialogTimer 50 
nsDialogs::Show
FunctionEnd

Function
OnDialogTimer
  
${NSD_KillTimer} OnDialogTimer
  
SendMessage $8 ${PBM_SETRANGE32} 1 100
  
GetFunctionAddress $0 Extractfunc
  BgWorker::CallAndWait #啟動一個低優先順序的後臺執行緒
FunctionEnd

Function
Extractfunc
  
SetOutPath $INSTDIR
  
File "test.7z"
  
GetFunctionAddress $R9 Callback
  
Nsis7z::ExtractWithCallback "test.7z" $R9
  
Delete "$OUTDIR\test.7z"
FunctionEnd

Function
Callback
  
Pop $R8
  
Pop $R9
  
System::Int64Op $R8 100
  
Pop $R0
  
System::Int64Op $R0 $R9
  
Pop $R3
  
SendMessage $8 ${PBM_SETPOS} $R3 0
  
${NSD_SetText} $9 "已經安裝$R3%"
  
${if} $R8 $R9
  ${NSD_SetText} $9
"安裝完成"
  
#由於計算方式的四捨五入特性,進度條到安裝完成時會有位元組級別的誤差,此處消除。
  
SendMessage $8 ${PBM_SETPOS} 100 0
  
System::Call "user32::InvalidateRect(i$hwndparent,i0,i 1)"
  
${endif}
FunctionEnd

Section
DetailPrint
"..."
SectionEnd