NSIS静默安装(通过代码开始) [英] NSIS silent install ( started via code )

查看:380
本文介绍了NSIS静默安装(通过代码开始)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to build an NSIS installer that will do the following:

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

1 When run normaly it will install the application with a installer with the usual choices.

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

2 When the installer is run with /S switch it silent installs, it's ok if it shows UI. But it should be automatic.

在我看来,安装程序在运行时会运行",然后再次正确启动该应用程序.但是它没有更新任何内容,几乎就像它在运行一样,但是不会复制任何文件.

It seems to me that the installer "works", as it runs and then correctly starts the application again. But it has not updated anything, it's almost as if it runs, but does not copy any files.

以静默方式安装时,将通过以下代码启动(应用程序自行更新)

When it's a silent install, it's started by the following code ( Application updates itself)

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

NSIS脚本主要(如果需要ppl,我可以发布自定义的NSIS支持脚本)

NSIS script main ( I can post support scripts for NSIS that are custom if ppl desire )

; 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

推荐答案

StrCmp $ 0 1 0 +3是错误的,它应该是+2(此示例中的+3可能是未定义的行为,因为您正在跳过隐藏的返回指令)

StrCmp $0 1 0 +3 is wrong, it should be +2 (+3 in this example is probably undefined behavior since you are skipping the hidden return instruction).

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

Using relative jumps is error prone, you should use a label or rewrite it using the logic lib:

!include LogicLib.nsh
...
Function .onInit
  Call GetDotNet

  ${If} ${Silent}
    call SilentInstall
  ${EndIf}
FunctionEnd

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

But putting the silent install logic in a separate function doubles your work when the normal install logic is almost equal. You should be able to remove the SilentInstall function and just use a hidden section to execute during silent installs:

Section "${_AppName} (required)"
#shared install code
SectionEnd

Section "Start Menu Shortcuts"
#shared startmenu code
SectionEnd

Section
${If} ${Silent}
    Exec ${_AppExe}
${EndIf}
Section

很难说为什么不更新文件,但是如果您使用共享代码,则可以在没有/S的情况下运行它并检查详细日志.我唯一的猜测是InstallDirRegKey正在拾取非默认的installdir,而您正在查看错误的文件.您可以进程监视器来监视安装.

It is hard to say why your files are not updated, but if you use shared code you can run it without /S and check the detail log. My only guess is that InstallDirRegKey is picking up a non default installdir and you are looking at the wrong files. You can Process Monitor to monitor the install.

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

Your code has some other unrelated issues:

  • RequestExecutionLevel管理员还不够,您需要关闭UAC处理NT5和NT6( UserInfo :: GetAccountType )
  • 当快捷方式图标与目标程序相同时,您无需指定快捷方式图标
  • 您应在调用Exec时引用路径:Exec '"$instdir\${_AppExe}"'
  • 将UAC/runas/RequestExecutionLevel admin与Exec混合会出现问题,因为您最终可能会以错误的用户身份运行该程序.
  • RequestExecutionLevel admin is not enough, you need to deal with NT5 and NT6 with UAC off (UserInfo::GetAccountType)
  • You don't have to specify the shortcut icon when the icon is the same as the target program
  • You should quote the path when calling Exec: Exec '"$instdir\${_AppExe}"'
  • Mixing UAC/runas/RequestExecutionLevel admin with Exec is problematic since you can end up running the program as the wrong user.

这篇关于NSIS静默安装(通过代码开始)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆