【问题标题】:Can I get NSIS to make a single installer that handles local deployment and system deployment?我可以让 NSIS 制作一个处理本地部署和系统部署的安装程序吗?
【发布时间】:2016-07-11 04:17:37
【问题描述】:

Chrome 有一个安装程序,可用于在系统范围内安装,或者如果用户不是管理员,则可以安装到用户的主目录。当您在企业环境中进行部署时,这非常有用,您仍然希望允许潜在用户安装,即使他们不一定有权限。

NSIS 可以用来创建这样的安装程序吗?

【问题讨论】:

    标签: windows installation nsis


    【解决方案1】:

    事实证明可以。重要的部分是:

    • RequestExecutionLevel highest:这确保安装程序获得用户帐户可用的最高权限。即如果他们在管理员组中,安装程序将要求提升权限。
    • 确定用户是否是管理员。这是使用 UserInfo 插件实现的。这很简单。
    • SetShellVarContext all|current:这决定了特殊注册表根键SHCTX 的值。对于all,它的含义与HKLM(系统范围)相同,对于current,它的结果是HKCUSetShellVarContext 还影响 $SMPROGRAMS 的值是指系统范围的开始菜单还是仅指用户的层次结构。

    这是一个安装程序的框架,它可以在系统范围内或本地部署,具体取决于用户帐户的权限。它使用 C:\Windows\write.exe 作为其有效负载,并可选择安装开始菜单项和桌面快捷方式。它还在注册表中放置了对卸载程序的引用,以便它显示在“添加/删除程序”对话框中。我使用 NSIS 3.0(测试版)来构建它,但我看不出有任何明显的原因为什么它不能与最近的 2.x 一起使用。

    !include "MUI2.nsh"
    
    !define PRODUCT_NAME "DummyProduct"
    !define VERSION "0.0.1"
    
    Var INSTDIR_BASE
    
    Name "${PRODUCT_NAME}"
    OutFile "${PRODUCT_NAME} Installer.exe"
    
    InstallDir ""
    
    ; Take the highest execution level available
    ; This means that if it's possible to, we become an administrator
    RequestExecutionLevel highest
    
    !macro ONINIT un
        Function ${un}.onInit
            ; The value of SetShellVarContext detetmines whether SHCTX is HKLM or HKCU
            ; and whether SMPROGRAMS refers to all users or just the current user
            UserInfo::GetAccountType
            Pop $0
            ${If} $0 == "Admin"
                ; If we're an admin, default to installing to C:\Program Files
                SetShellVarContext all
                StrCpy $INSTDIR_BASE "$PROGRAMFILES64"
            ${Else}
                ; If we're just a user, default to installing to ~\AppData\Local
                SetShellVarContext current
                StrCpy $INSTDIR_BASE "$LOCALAPPDATA"
            ${EndIf}
    
            ${If} $INSTDIR == ""
                ; This only happens in the installer, because the uninstaller already knows INSTDIR
                ReadRegStr $0 SHCTX "Software\${PRODUCT_NAME}" ""
    
                ${If} $0 != ""
                    ; If we're already installed, use the existing directory
                    StrCpy $INSTDIR "$0"
                ${Else}
                    StrCpy $INSTDIR "$INSTDIR_BASE\${PRODUCT_NAME}"
                ${Endif}
            ${Endif}
        FunctionEnd
    !macroend
    
    ; Define the function twice, once for the installer and again for the uninstaller
    !insertmacro ONINIT ""
    !insertmacro ONINIT "un"
    
    !define MUI_ABORTWARNING
    
    !define MUI_COMPONENTSPAGE_NODESC
    !insertmacro MUI_PAGE_COMPONENTS
    
    !insertmacro MUI_PAGE_DIRECTORY
    
    Var STARTMENU_FOLDER
    !define MUI_STARTMENUPAGE_REGISTRY_ROOT "SHCTX"
    !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\${PRODUCT_NAME}"
    !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
    !insertmacro MUI_PAGE_STARTMENU ${PRODUCT_NAME} $STARTMENU_FOLDER
    
    !insertmacro MUI_PAGE_INSTFILES
    !insertmacro MUI_UNPAGE_CONFIRM
    !insertmacro MUI_UNPAGE_INSTFILES
    
    !insertmacro MUI_LANGUAGE "English"
    
    Section "-Main Component"
        SetOutPath "$INSTDIR"
    
        File "C:\Windows\write.exe"
    
        WriteRegStr SHCTX "Software\${PRODUCT_NAME}" "" $INSTDIR
    
        ; These registry entries are necessary for the program to show up in the Add/Remove programs dialog
        WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayName" "${PRODUCT_NAME}"
        WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "UninstallString" '"$INSTDIR\Uninstall.exe"'
        WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoModify" 1
        WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoRepair" 1
    
        WriteUninstaller "$INSTDIR\Uninstall.exe"
    
        !insertmacro MUI_STARTMENU_WRITE_BEGIN ${PRODUCT_NAME}
            CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER\"
            CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\${PRODUCT_NAME}.lnk" "$INSTDIR\write.exe"
        !insertmacro MUI_STARTMENU_WRITE_END
    SectionEnd
    
    Section "Desktop shortcut"
        CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\write.exe"
    SectionEnd
    
    Section "Uninstall"
        Delete "$INSTDIR\write.exe"
    
        Delete "$INSTDIR\Uninstall.exe"
    
        RMDir /r "$INSTDIR"
    
        !insertmacro MUI_STARTMENU_GETFOLDER ${PRODUCT_NAME} $STARTMENU_FOLDER
        Delete "$SMPROGRAMS\$STARTMENU_FOLDER\${PRODUCT_NAME}.lnk"
        RMDir /r "$SMPROGRAMS\$STARTMENU_FOLDER"
    
        Delete "$DESKTOP\${PRODUCT_NAME}.lnk"
    
        DeleteRegKey /ifempty SHCTX "Software\${PRODUCT_NAME}"
    
        DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
    SectionEnd
    

    【讨论】:

    • 这看起来不错,但您可以使用 SHCTX 作为卸载 HKEY,因为 Windows 确实支持每个用户的条目。只有在安装 64 位应用程序时才应使用 $PROGRAMFILES64。如果您想要一个带有单选按钮的页面来选择安装类型,您还可以查看 NSIS 附带的多用户头文件。最后,Windows 指南规定您不应在开始菜单中创建卸载快捷方式。
    • 啊哈,我不知道。我会测试并修改我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-02
    • 2015-07-31
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 2016-09-15
    • 2010-11-06
    相关资源
    最近更新 更多