NSIS tutorial (9): NSIS+duilib QQ like installation package

Keywords: Windows xml zlib

In this paper NSIS tutorial (8): installation package interface based on third-party interface library On the basis of this, share the process of how to use NSIS in combination with duilib high imitation QQ installation package.

Let's start with the renderings!

Full NSIS script

# ======================Custom macro==============================
!define PRODUCT_NAME           "tencent QQ"
!define EXE_NAME               "QQ.exe"
!define PRODUCT_VERSION        "1.0.0.1"
!define PRODUCT_PUBLISHER      "Tencent"
!define PRODUCT_LEGAL          "Copyright (C) 1999-2014 Tencent, All Rights Reserved"


# =====================External plug-ins and macros=============================
!include "LogicLib.nsh"
!include "nsDialogs.nsh"
!include "..\..\include\common.nsh"

# =====================Installation package version=============================
VIProductVersion                    "${PRODUCT_VERSION}"
VIAddVersionKey "ProductVersion"    "${PRODUCT_VERSION}"
VIAddVersionKey "ProductName"       "${PRODUCT_NAME}"
VIAddVersionKey "CompanyName"       "${PRODUCT_PUBLISHER}"
VIAddVersionKey "FileVersion"       "${PRODUCT_VERSION}"
VIAddVersionKey "InternalName"      "${EXE_NAME}"
VIAddVersionKey "FileDescription"   "${PRODUCT_NAME}"
VIAddVersionKey "LegalCopyright"    "${PRODUCT_LEGAL}"

# ====================NSIS properties================================

#SetCompressor zlib

; Installation package name.
Name "${PRODUCT_NAME}"

# Installer filename
OutFile "QQ Setup.exe"

# Default installation location
InstallDir "$PROGRAMFILES\Tencent\${PRODUCT_NAME}"


# Request permission for the UAC of Vista and win7
# RequestExecutionLevel none|user|highest|admin
RequestExecutionLevel admin

# Install and uninstall programs icon
Icon              "image\logo.ico"
UninstallIcon     "image\logo.ico"

# Custom page
Page custom DUIPage

# Uninstaller display progress
UninstPage instfiles

# =======================Duelib custom page=========================
Var hInstallDlg

Function DUIPage
    !insertmacro Trace "$TEMP $PLUGINSDIR"
    nsDui::InitDUISetup
    Pop $hInstallDlg

    # License page
    nsDui::FindControl "btnLicenseClose"
    Pop $0
    ${If} $0 == 0
        GetFunctionAddress $0 OnExitDUISetup
        nsDui::OnControlBindNSISScript "btnLicenseClose" $0
    ${EndIf}

    nsDui::FindControl "btnLicenseMin"
    Pop $0
    ${If} $0 == 0
        GetFunctionAddress $0 OnBtnMin
        nsDui::OnControlBindNSISScript "btnLicenseMin" $0
    ${EndIf}

    nsDui::FindControl "btnLicenseNext"
    Pop $0
    ${If} $0 == 0
        GetFunctionAddress $0 OnBtnLicenseNextClick
        nsDui::OnControlBindNSISScript "btnLicenseNext" $0
    ${EndIf}

    # Directory selection page
    nsDui::FindControl "btnDirClose"
    Pop $0
    ${If} $0 == 0
        GetFunctionAddress $0 OnExitDUISetup
        nsDui::OnControlBindNSISScript "btnDirClose" $0
    ${EndIf}

    nsDui::FindControl "btnDirMin"
    Pop $0
    ${If} $0 == 0
        GetFunctionAddress $0 OnBtnMin
        nsDui::OnControlBindNSISScript "btnDirMin" $0
    ${EndIf}

    nsDui::FindControl "btnSelectDir"
    Pop $0
    ${If} $0 == 0
        GetFunctionAddress $0 OnBtnSelectDir
        nsDui::OnControlBindNSISScript "btnSelectDir" $0
    ${EndIf}

    nsDui::FindControl "btnDirPre"
    Pop $0
    ${If} $0 == 0
        GetFunctionAddress $0 OnBtnDirPre
        nsDui::OnControlBindNSISScript "btnDirPre" $0
    ${EndIf}

    nsDui::FindControl "btnDirCancel"
    Pop $0
    ${If} $0 == 0
        GetFunctionAddress $0 OnBtnCancel
        nsDui::OnControlBindNSISScript "btnDirCancel" $0
    ${EndIf}

    nsDui::FindControl "btnDirInstall"
    Pop $0
    ${If} $0 == 0
        GetFunctionAddress $0 OnBtnInstall
        nsDui::OnControlBindNSISScript "btnDirInstall" $0
    ${EndIf}



    # Installation progress page
    nsDui::FindControl "btnDetailClose"
    Pop $0
    ${If} $0 == 0
        GetFunctionAddress $0 OnExitDUISetup
        nsDui::OnControlBindNSISScript "btnDetailClose" $0
    ${EndIf}

    nsDui::FindControl "btnDetailMin"
    Pop $0
    ${If} $0 == 0
        GetFunctionAddress $0 OnBtnMin
        nsDui::OnControlBindNSISScript "btnDetailMin" $0
    ${EndIf}

    # Installation completion page
    nsDui::FindControl "btnFinished"
    Pop $0
    ${If} $0 == 0
        GetFunctionAddress $0 OnFinished
        nsDui::OnControlBindNSISScript "btnFinished" $0
    ${EndIf}

    nsDui::FindControl "btnFinishedMin"
    Pop $0
    ${If} $0 == 0
        GetFunctionAddress $0 OnBtnMin
        nsDui::OnControlBindNSISScript "btnFinishedMin" $0
    ${EndIf}

    nsDui::FindControl "btnFinishedClose"
    Pop $0
    ${If} $0 == 0
        GetFunctionAddress $0 OnExitDUISetup
        nsDui::OnControlBindNSISScript "btnFinishedClose" $0
    ${EndIf}

    nsDui::ShowPage
FunctionEnd

Function OnBtnLicenseNextClick
    nsDui::GetCheckboxStatus "chkAgree"
    Pop $0
    ${If} $0 == "1"
        nsDui::SetDirValue "$INSTDIR"
        nsDui::NextPage "wizardTab"
    ${EndIf}
FunctionEnd

# Start installation
Function OnBtnInstall
    nsDui::GetDirValue
    Pop $0
    StrCmp $0 "" InstallAbort 0
    StrCpy $INSTDIR "$0"
    nsDui::NextPage "wizardTab"
    nsDui::SetSliderRange "slrProgress" 0 100

    # Specify files not to be overwritten when overriding the installation
    # Staging these files to a temporary directory
    CreateDirectory "$TEMP\qq_file_translate"
    CopyFiles /SILENT "$INSTDIR\gf-config.xml" "$TEMP\qq_file_translate"

    #Start a low priority background thread
    GetFunctionAddress $0 ExtractFunc
    BgWorker::CallAndWait

    # After the file is released, restore the temporary file
    CopyFiles /SILENT "$TEMP\qq_file_translate\gf-config.xml" "$INSTDIR"
    RMDir /r "$TEMP\qq_file_translate"

    Call CreateShortcut
    Call CreateUninstall
InstallAbort:
FunctionEnd

Function ExtractFunc
    SetOutPath $INSTDIR
    File "app\app.7z"
    GetFunctionAddress $R9 ExtractCallback
    Nsis7z::ExtractWithCallback "$INSTDIR\app.7z" $R9
    #Delete "$INSTDIR\app.7z"
FunctionEnd


Function ExtractCallback
    Pop $1
    Pop $2
    System::Int64Op $1 * 100
    Pop $3
    System::Int64Op $3 / $2
    Pop $0

    nsDui::SetSliderValue "slrProgress" $0

    ${If} $1 == $2
        nsDui::SetSliderValue "slrProgress" 100
        nsDui::NextPage "wizardTab"
    ${EndIf}
FunctionEnd


Function OnExitDUISetup
    nsDui::ExitDUISetup
FunctionEnd

Function OnBtnMin
    SendMessage $hInstallDlg ${WM_SYSCOMMAND} 0xF020 0
FunctionEnd

Function OnBtnCancel
FunctionEnd

Function OnFinished
    # Start up
    nsDui::GetCheckboxStatus "chkBootStart"
    Pop $R0
    ${If} $R0 == "1"
        SetShellVarContext all
        CreateShortCut "$SMSTARTUP\QQ.lnk" "$INSTDIR\Bin\QQ.exe"
    ${EndIf}

    # restart now
    nsDui::GetCheckboxStatus "chkStartNow"
    Pop $R0
    ${If} $R0 == "1"
        Exec "$INSTDIR\Bin\QQ.exe"
    ${EndIf}

    # Set home page
    nsDui::GetCheckboxStatus "chkSetHomePage"
    Pop $R0
    ${If} $R0 == "1"
        WriteRegStr HKCU "Software\Microsoft\Internet Explorer\Main" "Start Page" "http://www.qq.com"
    ${EndIf}

    # Show new features
    nsDui::GetCheckboxStatus "chkShowFeature"
    Pop $R0
    ${If} $R0 == "1"
        ExecShell "open" "$INSTDIR\QQWhatsnew.txt"
    ${EndIf}

    Call OnExitDUISetup
FunctionEnd

Function OnBtnSelectDir
    nsDui::SelectInstallDir
    Pop $0
FunctionEnd

Function OnBtnDirPre
    nsDui::PrePage "wizardTab"
FunctionEnd


# =========================Installation procedure===============================

Function CreateShortcut
  SetShellVarContext all
  CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
  CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\Bin\${EXE_NAME}"
  CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\uninstall${PRODUCT_NAME}.lnk" "$INSTDIR\uninst.exe"
  CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\Bin\${EXE_NAME}"
  SetShellVarContext current
FunctionEnd

Function CreateUninstall
    # Build uninstaller
    WriteUninstaller "$INSTDIR\uninst.exe"

    # Add uninstall information to control panel
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayName" "${PRODUCT_NAME}"
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "UninstallString" "$INSTDIR\uninst.exe"
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayIcon" "$INSTDIR\${EXE_NAME}"
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "Publisher" "$INSTDIR\${PRODUCT_PUBLISHER}"
FunctionEnd

# Add an empty Section to prevent the compiler from reporting errors
Section "None"
SectionEnd


# Unload section
Section "Uninstall"

  ; remove shortcuts
  SetShellVarContext all
  Delete "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk"
  Delete "$SMPROGRAMS\${PRODUCT_NAME}\uninstall${PRODUCT_NAME}.lnk"
  RMDir "$SMPROGRAMS\${PRODUCT_NAME}\"
  Delete "$DESKTOP\${PRODUCT_NAME}.lnk"
  SetShellVarContext current

  SetOutPath "$INSTDIR"

  ; Remove installed files
  Delete "$INSTDIR\*.*"

  SetOutPath "$DESKTOP"

  RMDir /r "$INSTDIR"
  RMDir "$INSTDIR"

  SetAutoClose true
SectionEnd

# ==============================Callback function====================================

# Function names starting with "." are generally reserved as callback functions
# The function with the function name beginning with "un." will be created in the uninstaller. Therefore, the normal installation section and function cannot call the uninstallation function, and the uninstallation section and uninstallation function cannot call the normal function.

Function .onInit

FunctionEnd


# After successful installation
Function .onInstSuccess

FunctionEnd

# It is called when the user clicks the "Cancel" button after the installation failure
Function .onInstFailed
    MessageBox MB_ICONQUESTION|MB_YESNO "Installation succeeded!" /SD IDYES IDYES +2 IDNO +1
FunctionEnd


# This code is called every time the user changes the installation path
Function .onVerifyInstDir

FunctionEnd

# Before unloading operation
Function un.onInit
    MessageBox MB_ICONQUESTION|MB_YESNO "Are you sure you want to uninstall${PRODUCT_NAME}Do you?" /SD IDYES IDYES +2 IDNO +1
    Abort
FunctionEnd

# After successful uninstallation
Function un.onUninstSuccess

FunctionEnd

nsDui::InitDUISetup, nsDui::FindControl and other functions are provided by the nsDui plug-in developed by ourselves. Based on duilib, the plug-in provides functions such as interface display, control response, etc.

The BgWorker plug-in is used in the script to enable the background worker thread to perform the decompression process:

 GetFunctionAddress $0 ExtractFunc
 BgWorker::CallAndWait

Use the nsis7z plug-in to extract the 7z file, and obtain the decompression progress by passing in the function ExtractCallback as a callback function:

GetFunctionAddress $R9 ExtractCallback
Nsis7z::ExtractWithCallback "$INSTDIR\app.7z" $R9

Need to pay attention NSIS tutorial (8): installation package interface based on third-party interface library The nsis7z mentioned in cannot be decompressed because the version is too old.

Download address of nsDui project:
http://download.csdn.net/download/china_jeffery/10214488
Or from http://download.csdn.net/download/china_jeffery/10214582 Download the complete project, including plug-ins, scripts, image resources, etc.

Posted by DataRater on Sun, 03 May 2020 17:44:29 -0700