3

我是小型企业管理局的程序员。SBA 创建并向借款人和贷款人免费提供一些程序。下面的安装代码是我们为最终用户机器提供的免费程序之一。

我花了一周的时间寻找解决问题的方法,然后决定我需要学习如何编程我需要的东西。我是 Pascal 和 Inno Setup 的新手。我窃取了代码并测试了这个站点和其他站点中的所有示例。感谢所有的帮助。我一遍又一遍地修改和测试。下面是我的代码。

注意:我提供这个是希望它对其他人有用,但它并没有按计划工作。希望在其他人的帮助下发布一个工作版本。我提供了完整的代码来帮助其他人理解我努力学习的内容。;-)

问题:安装工作完美,除了 [代码] 部分重复。在到达 [Files] 部分中的 {code:GetInstallDirectory} 调用之前,它至少运行一次

它运行一次 Word 14 的 If 语句,然后运行一次 [Files] 部分。我的消息“MsgBox ('1. Setup...”出现了两次。以前它出现了 3 或 4 次,但我做了一个我不记得的更改,现在它只运行了两次。

谁能帮我找到问题?也许它与 If,Then,Else 语句有关。再一次,它可能是语句的顺序。提前致谢。

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
; Script written by Daniel H. Smith, Lead Programmer/Analyst, Base Technologies
;                   Washington, DC

#define MyAppName "IDAP mini-Wizard"
#define MyAppVersion "v 2013"
#define MyAppPublisher "Small Business Administration"
#define MyAppURL "http://www.sba.gov/"
#define MyAppExeName "IDAPv2013.exe"
#define MyAppCopyright "(c) 2013-2014"

[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{459E8784-C110-4348-A294-229C58CB00D2}
AppName={#MyAppPublisher}'s {#MyAppName} {#MyAppVersion}
AppVersion={#MyAppVersion}
AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
AppCopyright={#MyAppCopyright}
DefaultDirName={app}
CreateAppDir=false
OutputDir=C:\Users\Dan\Documents\IDAP Development\Setup
OutputBaseFilename=IDAPv2013Setup
SetupIconFile=C:\Users\Dan\Documents\My Shapes\_private\folder.ico
Compression=lzma
SolidCompression=true
UsePreviousGroup=false
UsePreviousAppDir=false
InfoBeforeFile=C:\Users\Dan\Documents\IDAP Development\Setup\IDAPInfo.txt
WizardImageFile=compiler:WizModernImage-IS.bmp
WizardSmallImageFile=compiler:WizModernSmallImage-IS.bmp
InfoAfterFile=C:\Users\Dan\Documents\IDAP Development\Setup\IDAPWord.txt
AppContact=Auth-IDAP@sba.gov
PrivilegesRequired=none
RestartIfNeededByRun=False
VersionInfoVersion=1.0
VersionInfoCompany={#MyAppPublisher}
VersionInfoCopyright={#MyAppCopyright}

[Languages]
Name: english; MessagesFile: compiler:Default.isl

[Files]
Source: "C:\Users\Dan\Documents\IDAP Development\IDAP 2013 Boilerplate_V10.Clean.pdf"; DestDir: "{userdocs}\IDAP Documents"; Flags: ignoreversion
Source: "C:\Users\Dan\Documents\IDAP Development\IDAP Borrower Certification (9-25-12)(initials) final.docx"; DestDir: "{userdocs}\IDAP Documents"; Flags: ignoreversion
Source: "C:\Users\Dan\Documents\IDAP Development\IDAP Loan Note (Draft July 25).docx"; DestDir: "{userdocs}\IDAP Documents"; Flags: ignoreversion
Source: "C:\Users\Dan\AppData\Roaming\Microsoft\Templates\IDAPLoan2013.dotm"; DestDir: "{code:GetInstallDirectory}"; DestName: "IDAPWizard2013v111.dotm"; Flags: confirmoverwrite

[Messages]
// define wizard title and tray status msg
// both are normally defined in innosetup's default.isl (install folder)
SetupAppTitle = Install {#MyAppName} {#MyAppVersion}
SetupWindowTitle = Install {#MyAppName} {#MyAppVersion} -- {#MyAppPublisher}

[Run]
//Opens Word if User leaves checkbox checked on Finish
  Filename: "{code:GetWordDirectory}"; Flags: postinstall; Description: "Open Word after Finish"; StatusMsg: "Opening Word ..."

[Code]
function GetWordDirectory(S: string) : String;
Begin
  IF RegKeyExists(HKCU, 'Software\Microsoft\Office\14.0\Common\General') THEN BEGIN
    Result := ExpandConstant('{pf32}\Microsoft Office\Office14\winword.exe');
  end Else begin
    Result := ExpandConstant('{pf32}\Microsoft Office\Office12\winword.exe');
  end;
End;
//--------
function GetInstallDirectory(S: String) : String;
var installDirectory : String;
    Version: TWindowsVersion;
Begin
//Word 14 Start
IF RegKeyExists(HKCU, 'Software\Microsoft\Office\14.0\Common\General') THEN BEGIN
    GetWindowsVersionEx(Version);
    if RegQueryStringValue(HKCU, 'Software\Microsoft\Office\14.0\Common\General', 'UserTemplates', installDirectory) then begin
    //Successfully read the registry value
        If (Version.Major = 6) and (Version.Minor = 1) and (Version.ProductType = VER_NT_WORKSTATION) //Windows 7
          then begin
            MsgBox ('1. Setup is installing to Word User Templates directory for:      '+#10+#13+#10+#13+'---> Word 2010 and Windows 7 <---', mbInformation, MB_OK);
            Result := installDirectory
          end else begin //begin c2
        //FAILED READING USERTEMPLATES DIRECTORY
        //Windows <= 6.0 Not Windows 7 and above
        If (Version.Major = 6) and (Version.Minor = 0) and (Version.ProductType = VER_NT_WORKSTATION)  //Windows Vista or XP
          then begin
            MsgBox ('2. Setup is installing to Word default template directory for:      '+#10+#13+#10+#13+'---> Word 2010 and Windows 7 <---', mbInformation, MB_OK);
            Result := ExpandConstant('C:\Users\{username}\AppData\Roaming\Microsoft\Templates');
          end else
            MsgBox ('3. Setup is installing to Word default template directory for:      '+#10+#13+#10+#13+'---> Word 2010 and Windows Vista/XP <---', mbInformation, MB_OK);
            Result := ExpandConstant('C:\Documents and Settings\{username}\Application Data\Microsoft\Templates');
        end;
    end;
//End Word 14
//Start Word 12
END ELSE IF RegKeyExists(HKCU, 'Software\Microsoft\Office\12.0\Common\General') THEN     BEGIN
    GetWindowsVersionEx(Version);
    if RegQueryStringValue(HKCU, 'Software\Microsoft\Office\12.0\Common\General', 'UserTemplates', installDirectory) then begin  
//    Successfully read the value
      If (Version.Major = 6) and (Version.Minor = 0) and (Version.ProductType = VER_NT_WORKSTATION)  //Windows 7
      then begin //c3
        MsgBox ('4. Setup is installing to Word User Templates directory for:      '+#10+#13+#10+#13+'---> Word 2007 and Windows 7 <---', mbInformation, MB_OK);
        Result := installDirectory
      end else begin //begin c4
      //FAILED READING VALUE
      If (Version.Major = 6) and (Version.Minor = 0) and (Version.ProductType = VER_NT_WORKSTATION)  //Windows Vista/XP
      then begin
        MsgBox ('5. Setup is installing to Word User Templates directory for:      '+#10+#13+#10+#13+'---> Word 2007 and Windows 7 <---', mbInformation, MB_OK);
        Result := ExpandConstant('C:\Users\{username}\AppData\Roaming\Microsoft\Templates');
      end else
        MsgBox ('6. Setup is installing to Word default templates directory for:      '+#10+#13+#10+#13+'---> Word 2007 and Windows XP or Vista <---', mbInformation, MB_OK);
        Result := ExpandConstant('C:\Documents and Settings\{username}\Application Data\Microsoft\Templates');
      end;
    end;
END;
//End Word 12
end;  //Function GetInstallDirectory end
//End All
//------------------------------------------------------------------------------
//Following are reference notes
//How to code a if-elseif-else
//  if condition then begin
    // ...
//  end else if condition then begin
    // ...
//  end else begin
    // ...
//  end;
//+------------+------------+-------+-------+---------+
//| Version    | PlatformId | Major | Minor | Release |
//+------------+------------+-------+-------+---------+
//| Win32s     |      0     |   ?   |   ?   |         |
//| Win95      |      1     |   4   |   0   | 1995 08 |
//| Win98      |      1     |   4   |  10   | 1998 06 |
//| WinME      |      1     |   4   |  90   | 2000 09 |
//| WinNT351   |      2     |   3   |  51   | 1995 04 |
//| WinNT4     |      2     |   4   |   0   | 1996 07 |
//| Win2000    |      2     |   5   |   0   | 2000 02 |
//| WinXP      |      2     |   5   |   1   | 2001 10 |
//| Win2003    |      2     |   5   |   2   | 2003 04 |
//| WinXPx64   |      2     |   5   |   2   | 2003 03 |
//| WinCE      |      3     |   ?   |   ?   |         |
//| Vista      |      2     |   6   |   0   | 2007 01 |
//| Win2008    |      2     |   6   |   0   | 2008 02 |
//| Win2008R2  |      2     |   6   |   1   | 2009 10 |
//| Win7       |      2     |   6   |   1   | 2009 10 |
//+------------+------------+-------+-------+---------+
//Word Templates default subdirectory before Windows 7
//C:\Documents and Settings\"user name"\Application Data\Microsoft\Templates\  
//Word Templates default subdirectory after Windows 7
//C:\Users\"username"\AppData\Roaming\Microsoft\Templates\
//
//For MS Word WinWord.Exe location and registry entry
//HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\Word\Options
//C:\Program Files (x86)\Microsoft Office\Office14\ -- For Word 14
//MS Word 14 UserTemplates registry
//HKCU, 'Software\Microsoft\Office\14.0\Common\General', 'UserTemplates'
//MS Word 12 UserTemplates registry
//HKCU, 'Software\Microsoft\Office\12.0\Common\General', 'UserTemplates'
//------------------------------------------------------------------------------
4

1 回答 1

0

更新:

没错,从DestDir参数调用的代码函数被调用了两次。第一次是在准备安装时,第二次是在处理文件时。我不知道原因(它在源代码中很深),但您实际上并不需要关心这一点。该参数函数过去只是用于获取目标目录,而不是用于任何类型的用户交互,因此您不必担心它会被调用两次。

尽管我已经对您的代码进行了审查。请注意,它未经测试是从下面列出的资源中编写的。需要指出的一点:

  • 使用常量,更容易维护一个常量而不是脚本中的许多地方
  • 不要依赖于所有用户都会在默认的 Program Files 目录中安装 Office
  • 默认模板目录在用户的应用程序数据中,在 InnoSetup 中,您可以用{userappdata}常量替换它,在您的情况下可以安全使用,因为您正在使用 运行设置PrivilegesRequired=none,因此强制管理员用户差异没有风险
  • 如果您的用户必须至少安装一个 Word 版本,请检查在您显示向导表单之前,请参阅InitializeSetup下面的事件功能

...

[Run]
; the Check parameter here use only when you remove the InitializeSetup event
; function (see below), otherwise it's useless because the setup won't even start 
; when there's not at least Word 2007 or 2010 version installed
Filename: "{code:GetLatestWordAppPath}"; Flags: postinstall; Description: "Open Word after Finish"; StatusMsg: "Opening Word ..."; Check: IsWordInstalled('12.0') or IsWordInstalled('14.0');

[Code]
// better for maintenance is to use constants
const  
  PathDefaultUserTemplates = '{userappdata}\Microsoft\Templates';
  RegKeyOfficeTemplatesPath = 'SOFTWARE\Microsoft\Office\%s\Common\General';
  RegKeyWordInstallRootPath = 'SOFTWARE\Microsoft\Office\%s\Word\InstallRoot';

// helper function for checking if the Word version specified by the input parameter
// is installed or not; inspired by https://stackoverflow.com/a/3267832/960757
function IsWordInstalled(const Version: string): Boolean;
begin
  Result := RegValueExists(HKEY_LOCAL_MACHINE, 
    Format(RegKeyWordInstallRootPath, [Version]), 'Path');
end;

// this is used for the application path for the check box from the [Run] section
// you shouldn't rely on that everyone installs Office to Program Files directory
function GetLatestWordAppPath(S: string): string;
begin
  Result := '';
  if not RegQueryStringValue(HKEY_LOCAL_MACHINE, 
    Format(RegKeyWordInstallRootPath, ['14.0']), 'Path', Result) 
  then
    RegQueryStringValue(HKEY_LOCAL_MACHINE, 
      Format(RegKeyWordInstallRootPath, ['12.0']), 'Path', Result);
end;

// helper function for getting the Office user templates path (if available)
function GetUserTemplatesPath(const Version: string; var Path: string): Boolean;
begin
  Result := RegQueryStringValue(HKEY_CURRENT_USER, 
    Format(RegKeyOfficeTemplatesPath, [Version]), 'UserTemplates', Path);
end;

// function returning target installation directory
function GetInstallDirectory(S: string): string;
var 
  InstallDirectory: string;
begin
  // initialize the Result first
  Result := '';
  // check if Word 2010 application is installed and if so, then...
  if IsWordInstalled('14.0') then
  begin
    // try to get the Office 2010 user templates location from registry, if succeed then...
    if GetUserTemplatesPath('14.0', InstallDirectory) then 
    begin
      Result := InstallDirectory;
      MsgBox('Office 2010 user templates directory was found in registry!' + #10#13 + #10#13 +
        Result, mbInformation, MB_OK);
    end
    else
    // the Office 2010 user templates location was not found in registry, so...
    begin
      // you're running your setup with PrivilegesRequired=none, so you can safely use {userappdata}
      // constant with no risk of getting different user path (forced administrator)
      Result := ExpandConstant(PathDefaultUserTemplates);
      MsgBox('Office 2010 user templates directory was not found in registry!' + #10#13 + #10#13 +
        Result, mbInformation, MB_OK);
    end;
  end
  else
  // Word 2010 was not found, check for Word 2007 and if it's found, then...
  if IsWordInstalled('12.0') then
  begin
    // try to get the Office 2007 user templates location from registry, if succeed then...
    if GetUserTemplatesPath('12.0', InstallDirectory) then 
    begin
      Result := InstallDirectory;
      MsgBox('Office 2007 user templates directory was found in registry!' + #10#13 + #10#13 +
        Result, mbInformation, MB_OK);
    end
    else
    // the Office 2007 user templates location was not found in registry, so...
    begin
      // you're running your setup with PrivilegesRequired=none, so you can safely use {userappdata}
      // constant with no risk of getting different user path (forced administrator)
      Result := ExpandConstant(PathDefaultUserTemplates);
      MsgBox('Office 2007 user templates directory was not found in registry!' + #10#13 + #10#13 +
        Result, mbInformation, MB_OK);
    end;
  end;
end;

// this event function is for the first check before the wizard form is shown if you 
// return False to this event function, the setup will exit, what is here conditioned 
// by presence of Word 2007 or Word 2010
function InitializeSetup: Boolean;
begin
  Result := IsWordInstalled('12.0') or IsWordInstalled('14.0');
  if not Result then
    MsgBox('You don''t have installed neither Word 2007 nor Word 2010.' + #10#13 +
      'Setup will now exit.', mbCriticalError, MB_OK);
end;
于 2012-11-24T17:16:04.163 回答