【问题标题】:NSIS silent install ( started via code )NSIS 静默安装(通过代码启动)
【发布时间】:2011-08-19 06:46:09
【问题描述】:

我正在尝试构建一个 NSIS 安装程序,它将执行以下操作:

1 正常运行时,它将使用带有通常选择的安装程序安装应用程序。

2 当安装程序使用 /S 开关运行时,它会静默安装,如果它显示 UI 就可以了。但它应该是自动的。

在我看来,安装程序“工作”,因为它运行,然后再次正确启动应用程序。但是它没有更新任何东西,它几乎就像它运行一样,但没有复制任何文件。

当它是静默安装时,它由以下代码启动(应用程序自行更新)

    ProcessStartInfo Pro = new ProcessStartInfo();
    Pro.Verb = "runas";
    Pro.UseShellExecute = true;
    Pro.FileName = gDownloadedFileName;
    Pro.Arguments = "/S";
    Pro.WindowStyle = ProcessWindowStyle.Normal;
    Pro.CreateNoWindow = true;

NSIS 脚本主要(如果人们愿意,我可以发布自定义的 NSIS 支持脚本)

; example2.nsi
;
; This script is based on example1.nsi, but it remember the directory, 
; has uninstall support and (optionally) installs start menu shortcuts.
;
; It will install example2.nsi into a directory that the user selects,
!include MUI.nsh
!include fileassoc.nsh
!include Silent.nsh


!define _AppName "My application"
!define _AppExe "My application.exe"
!define _AppVersion "1.0.0.0"

;--------------------------------------------------------------------- Dont edit beloow

; The name of the installer
Name "${_AppName}"

; The file to write
OutFile "DFOInfo_Setup_beta.exe"

; The default installation directory
InstallDir "$PROGRAMFILES\${_AppName}"

; Registry key to check for directory (so if you install again, it will 
; overwrite the old one automatically)
InstallDirRegKey HKLM "Software\TheXSoft.com\${_AppName}" "Install_Dir"

RequestExecutionLevel admin

Function .onInit
  Call GetDotNet

  Call IsSilent
  Pop $0
  StrCmp $0 1 0 +3
    Call SilentInstall

FunctionEnd

Function GetDotNet
  IfFileExists "$WINDIR\Microsoft.NET\Framework\v4.0.30319\installUtil.exe" NextStep
  MessageBox MB_OK|MB_ICONEXCLAMATION "You must have the Microsoft .NET Framework 4.0 Installed to use this application. $\n$\n The installer will now open the Microsft .NET Framework 4.0 webpage$\n$\n$\n$\nRemember this program will not function until you have installed the .NET Framework 4 ( You will get a error message if you try to start it)"
  ExecShell Open "http://www.microsoft.com/downloads/en/details.aspx?FamilyID=9cfb2d51-5ff4-4491-b0e5-b386f32c0992&displaylang=en" SW_SHOWNORMAL
  Quit
NextStep:
FunctionEnd

Section
SectionEnd
;--------------------------------

; Pages shown on none silent installer

;!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES

# These indented statements modify settings for MUI_PAGE_FINISH

;If we want to display a run app function
!define MUI_FINISHPAGE_NOAUTOCLOSE
!define MUI_FINISHPAGE_RUN_TEXT "Run ${_AppName}"
!define MUI_FINISHPAGE_RUN_CHECKED
!define MUI_FINISHPAGE_RUN "$INSTDIR\${_AppExe}"
!insertmacro MUI_PAGE_FINISH

!insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "German"
!insertmacro MUI_LANGUAGE "French"


UninstPage uninstConfirm
UninstPage instfiles

;--------------------------------

; The stuff to install
Section "${_AppName} (required)"
  SectionIn RO

  ; Set output path to the installation directory.
  SetOutPath $INSTDIR

  ; Put file there
  File /R "Current\*.*"

  ; Write the installation path into the registry
  WriteRegStr HKLM "Software\TheXSoft.com\${_AppName}" "Install_Dir" "$INSTDIR"

  ; Write the uninstall keys for Windows
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${_AppName}" "DisplayName" "${_AppName} ( Remove only)"
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${_AppName}" "UninstallString" '"$INSTDIR\uninstall.exe"'
  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${_AppName}" "NoModify" 1
  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${_AppName}" "NoRepair" 1
  WriteUninstaller "uninstall.exe"

SectionEnd

; Optional section (can be disabled by the user)
Section "Start Menu Shortcuts"

  SetShellVarContext all

  CreateDirectory "$SMPROGRAMS\${_AppName}"
  CreateShortCut "$SMPROGRAMS\${_AppName}\TheXSoft.com - Software page.url" "$INSTDIR\TheXSoft.com - Software page.url"
  CreateShortCut "$SMPROGRAMS\${_AppName}\GuildStats.NET - Get the stats for your MMO.url" "$INSTDIR\GuildStats.NET - Get the stats for your MMO.url"
  CreateShortCut "$SMPROGRAMS\${_AppName}\${_AppName}.lnk" "$INSTDIR\${_AppExe}" "" "$INSTDIR\${_AppExe}" 0

SectionEnd


;--------------------------------

; Uninstaller

Section "Uninstall"

  ; Remove registry keys
  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${_AppName}"
  DeleteRegKey HKLM "SOFTWARE\${_AppName}"

  ; Remove files and uninstaller
  Delete "$INSTDIR\*.exe"
  Delete $INSTDIR\uninstall.exe

  ; Remove shortcuts, if any
  Delete "$SMPROGRAMS\${_AppName}\*.*"

  ; Remove directories used
  RMDir "$INSTDIR"

SectionEnd


;--------------------------------
; Silent install logic

Function SilentInstall
  ; Set output path to the installation directory.
  SetOutPath $INSTDIR

  ; Put file there
  File /R "Current\*.*"

  ; Write the installation path into the registry
  WriteRegStr HKLM "Software\TheXSoft.com\${_AppName}" "Install_Dir" "$INSTDIR"

  ; Write the uninstall keys for Windows
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${_AppName}" "DisplayName" "${_AppName} ( Remove only)"
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${_AppName}" "UninstallString" '"$INSTDIR\uninstall.exe"'
  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${_AppName}" "NoModify" 1
  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${_AppName}" "NoRepair" 1
  WriteUninstaller "uninstall.exe"


  SetShellVarContext all

  CreateDirectory "$SMPROGRAMS\${_AppName}"
  CreateShortCut "$SMPROGRAMS\${_AppName}\TheXSoft.com - Software page.url" "$INSTDIR\TheXSoft.com - Software page.url"
  CreateShortCut "$SMPROGRAMS\${_AppName}\GuildStats.NET - Get the stats for your MMO.url" "$INSTDIR\GuildStats.NET - Get the stats for your MMO.url"
  CreateShortCut "$SMPROGRAMS\${_AppName}\${_AppName}.lnk" "$INSTDIR\${_AppExe}" "" "$INSTDIR\${_AppExe}" 0

  Exec ${_AppExe}
  Quit
FunctionEnd

【问题讨论】:

    标签: c# installation nsis


    【解决方案1】:

    StrCmp $0 1 0 +3 是错误的,它应该是 +2(在这个例子中 +3 可能是未定义的行为,因为你跳过了隐藏的返回指令)。

    使用相对跳转容易出错,你应该使用标签或使用逻辑库重写它:

    !include LogicLib.nsh
    ...
    Function .onInit
      Call GetDotNet
    
      ${If} ${Silent}
        call SilentInstall
      ${EndIf}
    FunctionEnd
    

    但是当正常安装逻辑几乎相等时,将静默安装逻辑放在单独的函数中会使您的工作加倍。您应该能够删除 SilentInstall 功能并在静默安装期间使用隐藏部分来执行:

    Section "${_AppName} (required)"
    #shared install code
    SectionEnd
    
    Section "Start Menu Shortcuts"
    #shared startmenu code
    SectionEnd
    
    Section
    ${If} ${Silent}
        Exec ${_AppExe}
    ${EndIf}
    Section
    

    很难说为什么您的文件没有更新,但是如果您使用共享代码,您可以在不使用 /S 的情况下运行它并检查详细日志。我唯一的猜测是 InstallDirRegKey 正在选择一个非默认安装目录,而您正在查看错误的文件。您可以Process Monitor 监控安装。


    您的代码还有一些其他不相关的问题:

    • RequestExecutionLevel admin 不够用,需要在关闭 UAC 的情况下处理 NT5 和 NT6 (UserInfo::GetAccountType)
    • 图标与目标程序相同时,不必指定快捷方式图标
    • 调用 Exec 时应引用路径:Exec '"$instdir\${_AppExe}"'
    • 将 UAC/runas/RequestExecutionLevel admin 与 Exec 混合使用是有问题的,因为您最终可能会以错误的用户身份运行程序。

    【讨论】:

    • 是否可以在其他静默安装程序中具有非静默部分或功能。假设我想显示下载进度但没有其他步骤。
    • @foobar 可以,但是不能设置静默标志,必须在页面预回调函数中调用Abort手动跳过所有其他页面。
    【解决方案2】:

    这是一个棘手的问题。我正在使用相同的方法来更新我的应用程序,静默调用 NSIS 安装程序。就我而言,问题不在于 NSIS 脚本,而是我使用 WebClient 类将包含我的安装程序的 zip 文件下载到临时目录,然后将其解压缩到那里,然后从那里运行它。问题是如果提取的安装文件存在,ZipFile 类会生成一个异常,因此旧的安装程序仍然存在,并且程序目录中除了卸载可执行文件之外什么都没有更新。

    对我来说,解决方案是在下载新文件之前清理旧的 zip 和 exe 文件(在 VB.NET 中):

        If File.Exists(Path.Combine(Path.GetTempPath(), "Setup.zip")) Then
            File.Delete(Path.Combine(Path.GetTempPath(), "Setup.zip"))
        End If
        If File.Exists(Path.Combine(Path.GetTempPath(), "Setup.exe")) Then
            File.Delete(Path.Combine(Path.GetTempPath(), "Setup.exe"))
        End If
    

    【讨论】:

      猜你喜欢
      • 2012-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-11
      • 1970-01-01
      • 2016-01-11
      • 1970-01-01
      • 2013-05-25
      相关资源
      最近更新 更多