Create a registry entry called vpyfile instead of vsfile to make more sense

#define AppName = 'VapourSynth'
#define Version = 'R33'

[Setup]
OutputDir=Compiled
OutputBaseFilename=VapourSynth-{#= Version}
Compression=lzma2/max
InternalCompressLevel=max
SolidCompression=yes
LZMAUseSeparateProcess=yes
VersionInfoDescription={#= AppName} {#= Version} Installer
AppId={#= AppName}
AppName={#= AppName} {#= Version}
AppVersion={#= Version}
AppVerName={#= AppName} {#= Version}
AppPublisher=Fredrik Mellbin
AppPublisherURL=http://www.vapoursynth.com/
AppSupportURL=http://www.vapoursynth.com/
AppUpdatesURL=http://www.vapoursynth.com/
VersionInfoVersion=1.33.0.0
DefaultDirName={pf32}\VapourSynth
DefaultGroupName=VapourSynth
AllowCancelDuringInstall=no
AllowNoIcons=yes
AllowUNCPath=no
MinVersion=6.0
PrivilegesRequired=admin
FlatComponentsList=yes
ArchitecturesAllowed=x86 x64
ArchitecturesInstallIn64BitMode=x64

[Languages]
Name: "en"; MessagesFile: "compiler:Default.isl"

[Types]
Name: Full; Description: Full installation; Flags: iscustom

[Components]
Name: "vs64"; Description: "VapourSynth 64bit"; Types: Full; Check: HasPython64; Flags: disablenouninstallwarning
Name: "vs32"; Description: "VapourSynth 32bit"; Types: Full; Check: HasPython32; Flags: disablenouninstallwarning
Name: "sdk"; Description: "VapourSynth SDK"; Flags: fixed; Types: Full

[Tasks]
Name: newvpyfile; Description: "Add 'New VapourSynth Python Script' option to shell context menu"; GroupDescription: "New File Shortcuts:"; Components: vs32 vs64

[Files]
;core binaries
Source: template.vpy; DestDir: {app}; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32 vs64
Source: vapoursynth.pth; DestDir: {code:GetPythonPath32}\Lib\site-packages; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: vapoursynth.pth; DestDir: {code:GetPythonPath64}\Lib\site-packages; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\vapoursynth.cp35-win32.pyd; DestDir: {code:GetPythonPath32}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\vapoursynth.cp35-win_amd64.pyd; DestDir: {code:GetPythonPath64}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vapoursynth.dll; DestDir: {code:GetPythonPath32}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vapoursynth.dll; DestDir: {code:GetPythonPath64}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\Release\vapoursynth.dll; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\vapoursynth.pdb; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vapoursynth.dll; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\vapoursynth.pdb; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\avfs.exe; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\avfs.exe; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vspipe.exe; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vspipe.exe; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vsvfw.dll; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vsvfw.dll; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vsscript.dll; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vsscript.dll; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\Release\vsscript.dll; DestDir: {sys}; Flags: uninsrestartdelete restartreplace 32bit; Components: vs32
Source: ..\msvc_project\x64\Release\vsscript.dll; DestDir: {sys}; Flags: uninsrestartdelete restartreplace 64bit; Components: vs64

;sdk
Source: ..\include\VapourSynth.h; DestDir: {app}\sdk\include\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\include\VSHelper.h; DestDir: {app}\sdk\include\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\include\VSScript.h; DestDir: {app}\sdk\include\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\Release\vsscript.lib; DestDir: {app}\sdk\lib32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\x64\Release\vsscript.lib; DestDir: {app}\sdk\lib64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\Release\vapoursynth.lib; DestDir: {app}\sdk\lib32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\x64\Release\vapoursynth.lib; DestDir: {app}\sdk\lib64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\sdk\filter_skeleton.c; DestDir: {app}\sdk\examples; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\sdk\invert_example.c; DestDir: {app}\sdk\examples; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\sdk\vsscript_example.c; DestDir: {app}\sdk\examples; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk

;bundled plugins
Source: x86\plugins\*; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\AvsCompat.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\EEDI3.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\RemoveGrainVS.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\Vinverse.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\VIVTC.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32

Source: x64\plugins\*; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\AvsCompat.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\EEDI3.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\RemoveGrainVS.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\Vinverse.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\VIVTC.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

; Create the general autoload directory
[Dirs]
Name: "{app}\plugins32"; Flags: uninsalwaysuninstall; Components: vs32
Name: "{app}\plugins64"; Flags: uninsalwaysuninstall; Components: vs64

[Icons]
Name: {group}\VapourSynth Website; Filename: http://www.vapoursynth.com/
Name: {group}\Documentation; Filename: http://www.vapoursynth.com/doc/
Name: {group}\Global Autoload Directory (32bit); Filename: {app}\plugins32; Components: vs32
Name: {group}\Global Autoload Directory (64bit); Filename: {app}\plugins64; Components: vs64
Name: {group}\VapourSynth SDK; Filename: {app}\sdk; Components: sdk

[Registry]
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Version"; ValueData: {#= Version}; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Version"; ValueData: {#= Version}; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Path"; ValueData: "{app}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Path"; ValueData: "{app}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins"; ValueData: "{app}\core32\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins"; ValueData: "{app}\core64\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins"; ValueData: "{app}\plugins32"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins"; ValueData: "{app}\plugins64"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VapourSynthDLL"; ValueData: "{app}\core32\vapoursynth.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VapourSynthDLL"; ValueData: "{app}\core64\vapoursynth.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VSScriptDLL"; ValueData: "{app}\core32\vsscript.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "PythonPath"; ValueData: "{code:GetPythonPath32}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VSScriptDLL"; ValueData: "{app}\core64\vsscript.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "PythonPath"; ValueData: "{code:GetPythonPath64}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

; legacy entries, will one day be removed
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins32"; ValueData: "{app}\core32\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins64"; ValueData: "{app}\core64\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins32"; ValueData: "{app}\plugins32"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins64"; ValueData: "{app}\plugins64"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

; new vpy file shortcut task
Root: HKLM; Subkey: SOFTWARE\Classes\.vpy\ShellNew; ValueType: string; ValueName: "FileName"; ValueData: "{app}\template.vpy"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: newvpyfile

; 32bit vfw
Root: HKLM32; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}; ValueType: string; ValueName: ""; ValueData: "VapourSynth"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: ""; ValueData: "{app}\core32\vsvfw.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: "ThreadingModel"; ValueData: "Apartment"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: ""; ValueData: ""; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: "Source Filter"; ValueData: "{{D3588AB0-0781-11CE-B03A-0020AF0BA770}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\.vpy; ValueType: string; ValueName: ""; ValueData: "vpyfile"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\vpyfile; ValueType: string; ValueName: ""; ValueData: "VapourSynth Python Script"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\vpyfile\DefaultIcon; ValueType: string; ValueName: ""; ValueData: "{app}\core32\vsvfw.dll,0"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\AVIFile\Extensions\VPY; ValueType: string; ValueName: ""; ValueData: "{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32

; 64bit vfw
Root: HKLM64; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}; ValueType: string; ValueName: ""; ValueData: "VapourSynth"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: ""; ValueData: "{app}\core64\vsvfw.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: "ThreadingModel"; ValueData: "Apartment"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: ""; ValueData: ""; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: "Source Filter"; ValueData: "{{D3588AB0-0781-11CE-B03A-0020AF0BA770}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\.vpy; ValueType: string; ValueName: ""; ValueData: "vpyfile"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\vpyfile; ValueType: string; ValueName: ""; ValueData: "VapourSynth Python Script"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\vpyfile\DefaultIcon; ValueType: string; ValueName: ""; ValueData: "{app}\core64\vsvfw.dll,0"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\AVIFile\Extensions\VPY; ValueType: string; ValueName: ""; ValueData: "{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

[Code]
#include "scripts\products.iss"
#include "scripts\products\msiproduct.iss"
#include "scripts\products\vcredist2013.iss"
#include "scripts\products\vcredist2015.iss"

type
  TPythonPath = record
    DisplayName: string;
    InstallPath: string;
    Bitness: Integer;
  end;

var
  Runtimes32Added: Boolean;
  Runtimes64Added: Boolean;
  PythonInstallations: array of TPythonPath;
  PythonPage: TWizardPage;
  PythonList: TNewCheckListBox;
  Python32Path: string;
  Python64Path: string;

function HasPython32: Boolean;
var
  Counter: Integer;
begin
  Result := False;
  for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
    if PythonInstallations[Counter].Bitness = 32 then
      Result := True;
end;

function HasPython64: Boolean;
var
  Counter: Integer;
begin
  Result := False;
  for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
    if PythonInstallations[Counter].Bitness = 64 then
      Result := True;
end;

procedure GetPythonInstallations2(RegRoot: Integer; RegPath: string; AssumeBitness: Integer);
var
  Names, Tags: TArrayOfString;
  Nc, Tc: Integer;
  RegPathTemp: string;
  Temp: string;
  DisplayName, InstallPath: string;
  Bitness: Integer;
begin
  if RegGetSubkeyNames(RegRoot, RegPath, Names) then
  begin
    for Nc := 0 to GetArrayLength(Names) - 1 do
    begin
      if RegGetSubkeyNames(RegRoot, RegPath + '\' + Names[Nc], Tags) then
      begin
        for Tc := 0 to GetArrayLength(Tags) - 1 do
        begin
          RegPathTemp := RegPath + '\' + Names[Nc] + '\' + Tags[Tc];
          Bitness := AssumeBitness;
          if (not RegQueryStringValue(RegRoot, RegPathTemp, 'SysVersion', Temp)) or (Temp <> '3.5') then
            continue;
          if RegQueryStringValue(RegRoot, RegPathTemp, 'SysArchitecture', Temp) then
          begin
            if Temp = '32bit' then
              Bitness := 32
            else if Temp = '64bit' then
              Bitness := 64;
          end;

          if RegQueryStringValue(RegRoot, RegPathTemp, 'DisplayName', DisplayName) and RegQueryStringValue(RegRoot, RegPathTemp + '\InstallPath', '', InstallPath) then
          begin
             SetArrayLEngth(PythonInstallations, GetArrayLength(PythonInstallations) + 1);
             PythonInstallations[GetArrayLength(PythonInstallations) - 1].DisplayName := DisplayName;
             PythonInstallations[GetArrayLength(PythonInstallations) - 1].InstallPath := InstallPath;
             PythonInstallations[GetArrayLength(PythonInstallations) - 1].Bitness := Bitness;
          end;
        end;
      end;
    end;
  end;
end;

procedure GetPythonInstallations;
var
  Success: Boolean;
  PythonPath32: string;
  PythonPath64: string;
begin
  Success := RegQueryStringValue(HKCU32, 'SOFTWARE\Python\PythonCore\3.5-32\InstallPath', '', PythonPath32);
  if not Success then
    RegQueryStringValue(HKLM32, 'SOFTWARE\Python\PythonCore\3.5-32\InstallPath', '', PythonPath32);

  if Is64BitInstallMode then
  begin
    Success := RegQueryStringValue(HKCU, 'SOFTWARE\Python\PythonCore\3.5\InstallPath', '', PythonPath64);
    if not Success then
      RegQueryStringValue(HKLM, 'SOFTWARE\Python\PythonCore\3.5\InstallPath', '', PythonPath64);
  end;

  if PythonPath32 <> '' then
  begin
    SetArrayLEngth(PythonInstallations, GetArrayLength(PythonInstallations) + 1);
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].DisplayName := 'Python 3.5 (32-bit)';
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].InstallPath := PythonPath32;
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].Bitness := 32;
  end;

  if PythonPath64 <> '' then
  begin
    SetArrayLEngth(PythonInstallations, GetArrayLength(PythonInstallations) + 1);
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].DisplayName := 'Python 3.5 (64-bit)';
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].InstallPath := PythonPath64;
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].Bitness := 64;
  end;

  GetPythonInstallations2(HKCU, 'SOFTWARE\Python', 0);
  GetPythonInstallations2(HKLM32, 'SOFTWARE\Python', 32);
  if Is64BitInstallMode then
    GetPythonInstallations2(HKLM, 'SOFTWARE\Python', 64);
end;

procedure PopulatePythonInstallations(List: TNewCheckListBox);
var
  Counter: Integer;
  First: Boolean;
begin
  List.Items.Clear;

  if IsComponentSelected('vs32') then
  begin
    First := True;
    List.AddGroup('Python Environments (32-bit)', '', 0, nil);
    for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
      if PythonInstallations[Counter].Bitness = 32 then
        with PythonInstallations[Counter] do
        begin
          List.AddRadioButton(DisplayName, '(' + InstallPath + ')', 1, First, True, TObject(Counter));
          First := False;
        end;
  end;

  if IsComponentSelected('vs64') then
  begin
    First := True;
    List.AddGroup('Python Environments (64-bit)', '', 0, nil);
    for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
      if PythonInstallations[Counter].Bitness = 64 then
        with PythonInstallations[Counter] do
        begin
          List.AddRadioButton(DisplayName, '(' + InstallPath + ')', 1, First, True, TObject(Counter));
          First := False;
        end;
  end;
end;

function InitializeSetup: Boolean;
begin
  Runtimes32Added := False;
  Runtimes64Added := False;
  PythonList := nil;
  GetPythonInstallations;
  Result := True;
end;

procedure InitializeWizard();
begin
  PythonPage := CreateCustomPage(wpSelectComponents, 'Select Python Installations', 'Select one or more Python installations to use');
  PythonList := TNewCheckListBox.Create(PythonPage);

  with PythonList do
  begin
    Parent := PythonPage.Surface;
    Left := ScaleX(0);
    Top := ScaleY(0);
    Width := PythonPage.Surface.Width - ScaleX(0) * 2;
    Height := PythonPage.Surface.Height;
  end;
end;

function GetPythonPath32(Param: string): String;
begin
  Result := Python32Path;
end;

function GetPythonPath64(Param: String): String;
begin
  Result := Python64Path;
end;

// copied from the internets

/////////////////////////////////////////////////////////////////////
function GetUninstallString: String;
var
  sUnInstPath: String;
  sUnInstallString: String;
begin
  sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
  sUnInstallString := '';
  if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
    RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
  Result := sUnInstallString;
end;

/////////////////////////////////////////////////////////////////////
function IsUpgrade: Boolean;
begin
  Result := (GetUninstallString() <> '');
end;

/////////////////////////////////////////////////////////////////////
function UnInstallOldVersion: Integer;
var
  sUnInstallString: String;
  iResultCode: Integer;
begin
// Return Values:
// 1 - uninstall string is empty
// 2 - error executing the UnInstallString
// 3 - successfully executed the UnInstallString

  // default return value
  Result := 0;

  // get the uninstall string of the old app
  sUnInstallString := GetUninstallString();
  if sUnInstallString <> '' then begin
    sUnInstallString := RemoveQuotes(sUnInstallString);
    if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
      Result := 3
    else
      Result := 2;
  end
  else
    Result := 1;
end;

/////////////////////////////////////////////////////////////////////
procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep=ssInstall then
  begin
    if IsUpgrade() then
      UnInstallOldVersion();
  end;
end;

/////////////////////////////////////////////////////////////////////
function NextButtonClick(CurPageID: Integer): Boolean;
var
  Counter: Integer;
  Idx: Integer;
begin
  Result := True;
  if CurPageID = PythonPage.ID then
  begin
    for Counter := 0 to PythonList.Items.Count - 1 do
    begin
      if (PythonList.Checked[Counter]) and (PythonList.ItemLevel[Counter] = 1) then
      begin
        Idx := Integer(PythonList.ItemObject[Counter]);
        with PythonInstallations[Idx] do
        begin
          if Bitness = 64 then
            Python64Path := InstallPath
          else if Bitness = 32 then
            Python32Path := InstallPath;
        end;
      end;
    end;
  end
  else if CurPageID = wpSelectComponents then
  begin
    if not IsComponentSelected('vs32 or vs64') then
    begin
      Result := False;
      MsgBox('At least one version of the core library has to be installed.', mbCriticalError, MB_OK)
    end;

    PopulatePythonInstallations(PythonList);
  end
  else if CurPageID = wpReady then
  begin
    if IsComponentSelected('vs32') and not Runtimes32Added then
    begin
      SetForceX86(True);
      vcredist2013();
      vcredist2015();
      SetForceX86(False);
      Runtimes32Added := True;
    end;
    if IsComponentSelected('vs64') and not Runtimes64Added then
    begin
      vcredist2013();
      vcredist2015();
      Runtimes64Added := True;
    end;
    Result := NextButtonClick2(CurPageID);
  end;
end;

#define AppName = 'VapourSynth'
#define Version = 'R33'

[Setup]
OutputDir=Compiled
OutputBaseFilename=VapourSynth-{#= Version}
Compression=lzma2/max
InternalCompressLevel=max
SolidCompression=yes
LZMAUseSeparateProcess=yes
VersionInfoDescription={#= AppName} {#= Version} Installer
AppId={#= AppName}
AppName={#= AppName} {#= Version}
AppVersion={#= Version}
AppVerName={#= AppName} {#= Version}
AppPublisher=Fredrik Mellbin
AppPublisherURL=http://www.vapoursynth.com/
AppSupportURL=http://www.vapoursynth.com/
AppUpdatesURL=http://www.vapoursynth.com/
VersionInfoVersion=1.33.0.0
DefaultDirName={pf32}\VapourSynth
DefaultGroupName=VapourSynth
AllowCancelDuringInstall=no
AllowNoIcons=yes
AllowUNCPath=no
MinVersion=6.0
PrivilegesRequired=admin
FlatComponentsList=yes
ArchitecturesAllowed=x86 x64
ArchitecturesInstallIn64BitMode=x64

[Languages]
Name: "en"; MessagesFile: "compiler:Default.isl"

[Types]
Name: Full; Description: Full installation; Flags: iscustom

[Components]
Name: "vs64"; Description: "VapourSynth 64bit"; Types: Full; Check: HasPython64; Flags: disablenouninstallwarning
Name: "vs32"; Description: "VapourSynth 32bit"; Types: Full; Check: HasPython32; Flags: disablenouninstallwarning
Name: "sdk"; Description: "VapourSynth SDK"; Flags: fixed; Types: Full

[Tasks]
Name: newvpyfile; Description: "Add 'New VapourSynth Python Script' option to shell context menu"; GroupDescription: "New File Shortcuts:"; Components: vs32 vs64

[Files]
;core binaries
Source: template.vpy; DestDir: {app}; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32 vs64
Source: vapoursynth.pth; DestDir: {code:GetPythonPath32}\Lib\site-packages; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: vapoursynth.pth; DestDir: {code:GetPythonPath64}\Lib\site-packages; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\vapoursynth.cp35-win32.pyd; DestDir: {code:GetPythonPath32}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\vapoursynth.cp35-win_amd64.pyd; DestDir: {code:GetPythonPath64}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vapoursynth.dll; DestDir: {code:GetPythonPath32}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vapoursynth.dll; DestDir: {code:GetPythonPath64}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\Release\vapoursynth.dll; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\vapoursynth.pdb; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vapoursynth.dll; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\vapoursynth.pdb; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\avfs.exe; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\avfs.exe; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vspipe.exe; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vspipe.exe; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vsvfw.dll; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vsvfw.dll; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vsscript.dll; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vsscript.dll; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\Release\vsscript.dll; DestDir: {sys}; Flags: uninsrestartdelete restartreplace 32bit; Components: vs32
Source: ..\msvc_project\x64\Release\vsscript.dll; DestDir: {sys}; Flags: uninsrestartdelete restartreplace 64bit; Components: vs64

;sdk
Source: ..\include\VapourSynth.h; DestDir: {app}\sdk\include\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\include\VSHelper.h; DestDir: {app}\sdk\include\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\include\VSScript.h; DestDir: {app}\sdk\include\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\Release\vsscript.lib; DestDir: {app}\sdk\lib32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\x64\Release\vsscript.lib; DestDir: {app}\sdk\lib64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\Release\vapoursynth.lib; DestDir: {app}\sdk\lib32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\x64\Release\vapoursynth.lib; DestDir: {app}\sdk\lib64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\sdk\filter_skeleton.c; DestDir: {app}\sdk\examples; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\sdk\invert_example.c; DestDir: {app}\sdk\examples; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\sdk\vsscript_example.c; DestDir: {app}\sdk\examples; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk

;bundled plugins
Source: x86\plugins\*; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\AvsCompat.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\EEDI3.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\RemoveGrainVS.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\Vinverse.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\VIVTC.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32

Source: x64\plugins\*; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\AvsCompat.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\EEDI3.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\RemoveGrainVS.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\Vinverse.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\VIVTC.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

; Create the general autoload directory
[Dirs]
Name: "{app}\plugins32"; Flags: uninsalwaysuninstall; Components: vs32
Name: "{app}\plugins64"; Flags: uninsalwaysuninstall; Components: vs64

[Icons]
Name: {group}\VapourSynth Website; Filename: http://www.vapoursynth.com/
Name: {group}\Documentation; Filename: http://www.vapoursynth.com/doc/
Name: {group}\Global Autoload Directory (32bit); Filename: {app}\plugins32; Components: vs32
Name: {group}\Global Autoload Directory (64bit); Filename: {app}\plugins64; Components: vs64
Name: {group}\VapourSynth SDK; Filename: {app}\sdk; Components: sdk

[Registry]
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Version"; ValueData: {#= Version}; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Version"; ValueData: {#= Version}; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Path"; ValueData: "{app}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Path"; ValueData: "{app}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins"; ValueData: "{app}\core32\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins"; ValueData: "{app}\core64\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins"; ValueData: "{app}\plugins32"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins"; ValueData: "{app}\plugins64"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VapourSynthDLL"; ValueData: "{app}\core32\vapoursynth.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VapourSynthDLL"; ValueData: "{app}\core64\vapoursynth.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VSScriptDLL"; ValueData: "{app}\core32\vsscript.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "PythonPath"; ValueData: "{code:GetPythonPath32}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VSScriptDLL"; ValueData: "{app}\core64\vsscript.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "PythonPath"; ValueData: "{code:GetPythonPath64}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

; legacy entries, will one day be removed
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins32"; ValueData: "{app}\core32\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins64"; ValueData: "{app}\core64\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins32"; ValueData: "{app}\plugins32"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins64"; ValueData: "{app}\plugins64"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

; new vpy file shortcut task
Root: HKLM; Subkey: SOFTWARE\Classes\.vpy\ShellNew; ValueType: string; ValueName: "FileName"; ValueData: "{app}\template.vpy"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: newvpyfile

; 32bit vfw
Root: HKLM32; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}; ValueType: string; ValueName: ""; ValueData: "VapourSynth"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: ""; ValueData: "{app}\core32\vsvfw.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: "ThreadingModel"; ValueData: "Apartment"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: ""; ValueData: ""; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: "Source Filter"; ValueData: "{{D3588AB0-0781-11CE-B03A-0020AF0BA770}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\.vpy; ValueType: string; ValueName: ""; ValueData: "vsfile"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\vsfile; ValueType: string; ValueName: ""; ValueData: "VapourSynth Python Script"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\vsfile\DefaultIcon; ValueType: string; ValueName: ""; ValueData: "{app}\core32\vsvfw.dll,0"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\AVIFile\Extensions\VPY; ValueType: string; ValueName: ""; ValueData: "{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32

; 64bit vfw
Root: HKLM64; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}; ValueType: string; ValueName: ""; ValueData: "VapourSynth"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: ""; ValueData: "{app}\core64\vsvfw.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: "ThreadingModel"; ValueData: "Apartment"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: ""; ValueData: ""; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: "Source Filter"; ValueData: "{{D3588AB0-0781-11CE-B03A-0020AF0BA770}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\.vpy; ValueType: string; ValueName: ""; ValueData: "vsfile"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\vsfile; ValueType: string; ValueName: ""; ValueData: "VapourSynth Python Script"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\vsfile\DefaultIcon; ValueType: string; ValueName: ""; ValueData: "{app}\core64\vsvfw.dll,0"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\AVIFile\Extensions\VPY; ValueType: string; ValueName: ""; ValueData: "{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

[Code]
#include "scripts\products.iss"
#include "scripts\products\msiproduct.iss"
#include "scripts\products\vcredist2013.iss"
#include "scripts\products\vcredist2015.iss"

type
  TPythonPath = record
    DisplayName: string;
    InstallPath: string;
    Bitness: Integer;
  end;

var
  Runtimes32Added: Boolean;
  Runtimes64Added: Boolean;
  PythonInstallations: array of TPythonPath;
  PythonPage: TWizardPage;
  PythonList: TNewCheckListBox;
  Python32Path: string;
  Python64Path: string;

function HasPython32: Boolean;
var
  Counter: Integer;
begin
  Result := False;
  for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
    if PythonInstallations[Counter].Bitness = 32 then
      Result := True;
end;

function HasPython64: Boolean;
var
  Counter: Integer;
begin
  Result := False;
  for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
    if PythonInstallations[Counter].Bitness = 64 then
      Result := True;
end;

procedure GetPythonInstallations2(RegRoot: Integer; RegPath: string; AssumeBitness: Integer);
var
  Names, Tags: TArrayOfString;
  Nc, Tc: Integer;
  RegPathTemp: string;
  Temp: string;
  DisplayName, InstallPath: string;
  Bitness: Integer;
begin
  if RegGetSubkeyNames(RegRoot, RegPath, Names) then
  begin
    for Nc := 0 to GetArrayLength(Names) - 1 do
    begin
      if RegGetSubkeyNames(RegRoot, RegPath + '\' + Names[Nc], Tags) then
      begin
        for Tc := 0 to GetArrayLength(Tags) - 1 do
        begin
          RegPathTemp := RegPath + '\' + Names[Nc] + '\' + Tags[Tc];
          Bitness := AssumeBitness;
          if (not RegQueryStringValue(RegRoot, RegPathTemp, 'SysVersion', Temp)) or (Temp <> '3.5') then
            continue;
          if RegQueryStringValue(RegRoot, RegPathTemp, 'SysArchitecture', Temp) then
          begin
            if Temp = '32bit' then
              Bitness := 32
            else if Temp = '64bit' then
              Bitness := 64;
          end;

          if RegQueryStringValue(RegRoot, RegPathTemp, 'DisplayName', DisplayName) and RegQueryStringValue(RegRoot, RegPathTemp + '\InstallPath', '', InstallPath) then
          begin
             SetArrayLEngth(PythonInstallations, GetArrayLength(PythonInstallations) + 1);
             PythonInstallations[GetArrayLength(PythonInstallations) - 1].DisplayName := DisplayName;
             PythonInstallations[GetArrayLength(PythonInstallations) - 1].InstallPath := InstallPath;
             PythonInstallations[GetArrayLength(PythonInstallations) - 1].Bitness := Bitness;
          end;
        end;
      end;
    end;
  end;
end;

procedure GetPythonInstallations;
var
  Success: Boolean;
  PythonPath32: string;
  PythonPath64: string;
begin
  Success := RegQueryStringValue(HKCU32, 'SOFTWARE\Python\PythonCore\3.5-32\InstallPath', '', PythonPath32);
  if not Success then
    RegQueryStringValue(HKLM32, 'SOFTWARE\Python\PythonCore\3.5-32\InstallPath', '', PythonPath32);

  if Is64BitInstallMode then
  begin
    Success := RegQueryStringValue(HKCU, 'SOFTWARE\Python\PythonCore\3.5\InstallPath', '', PythonPath64);
    if not Success then
      RegQueryStringValue(HKLM, 'SOFTWARE\Python\PythonCore\3.5\InstallPath', '', PythonPath64);
  end;

  if PythonPath32 <> '' then
  begin
    SetArrayLEngth(PythonInstallations, GetArrayLength(PythonInstallations) + 1);
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].DisplayName := 'Python 3.5 (32-bit)';
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].InstallPath := PythonPath32;
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].Bitness := 32;
  end;

  if PythonPath64 <> '' then
  begin
    SetArrayLEngth(PythonInstallations, GetArrayLength(PythonInstallations) + 1);
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].DisplayName := 'Python 3.5 (64-bit)';
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].InstallPath := PythonPath64;
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].Bitness := 64;
  end;

  GetPythonInstallations2(HKCU, 'SOFTWARE\Python', 0);
  GetPythonInstallations2(HKLM32, 'SOFTWARE\Python', 32);
  if Is64BitInstallMode then
    GetPythonInstallations2(HKLM, 'SOFTWARE\Python', 64);
end;

procedure PopulatePythonInstallations(List: TNewCheckListBox);
var
  Counter: Integer;
  First: Boolean;
begin
  List.Items.Clear;

  if IsComponentSelected('vs32') then
  begin
    First := True;
    List.AddGroup('Python Environments (32-bit)', '', 0, nil);
    for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
      if PythonInstallations[Counter].Bitness = 32 then
        with PythonInstallations[Counter] do
        begin
          List.AddRadioButton(DisplayName, '(' + InstallPath + ')', 1, First, True, TObject(Counter));
          First := False;
        end;
  end;

  if IsComponentSelected('vs64') then
  begin
    First := True;
    List.AddGroup('Python Environments (64-bit)', '', 0, nil);
    for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
      if PythonInstallations[Counter].Bitness = 64 then
        with PythonInstallations[Counter] do
        begin
          List.AddRadioButton(DisplayName, '(' + InstallPath + ')', 1, First, True, TObject(Counter));
          First := False;
        end;
  end;
end;

function InitializeSetup: Boolean;
begin
  Runtimes32Added := False;
  Runtimes64Added := False;
  PythonList := nil;
  GetPythonInstallations;
  Result := True;
end;

procedure InitializeWizard();
begin
  PythonPage := CreateCustomPage(wpSelectComponents, 'Select Python Installations', 'Select one or more Python installations to use');
  PythonList := TNewCheckListBox.Create(PythonPage);

  with PythonList do
  begin
    Parent := PythonPage.Surface;
    Left := ScaleX(0);
    Top := ScaleY(0);
    Width := PythonPage.Surface.Width - ScaleX(0) * 2;
    Height := PythonPage.Surface.Height;
  end;
end;

function GetPythonPath32(Param: string): String;
begin
  Result := Python32Path;
end;

function GetPythonPath64(Param: String): String;
begin
  Result := Python64Path;
end;

// copied from the internets

/////////////////////////////////////////////////////////////////////
function GetUninstallString: String;
var
  sUnInstPath: String;
  sUnInstallString: String;
begin
  sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
  sUnInstallString := '';
  if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
    RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
  Result := sUnInstallString;
end;

/////////////////////////////////////////////////////////////////////
function IsUpgrade: Boolean;
begin
  Result := (GetUninstallString() <> '');
end;

/////////////////////////////////////////////////////////////////////
function UnInstallOldVersion: Integer;
var
  sUnInstallString: String;
  iResultCode: Integer;
begin
// Return Values:
// 1 - uninstall string is empty
// 2 - error executing the UnInstallString
// 3 - successfully executed the UnInstallString

  // default return value
  Result := 0;

  // get the uninstall string of the old app
  sUnInstallString := GetUninstallString();
  if sUnInstallString <> '' then begin
    sUnInstallString := RemoveQuotes(sUnInstallString);
    if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
      Result := 3
    else
      Result := 2;
  end
  else
    Result := 1;
end;

/////////////////////////////////////////////////////////////////////
procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep=ssInstall then
  begin
    if IsUpgrade() then
      UnInstallOldVersion();
  end;
end;

/////////////////////////////////////////////////////////////////////
function NextButtonClick(CurPageID: Integer): Boolean;
var
  Counter: Integer;
  Idx: Integer;
begin
  Result := True;
  if CurPageID = PythonPage.ID then
  begin
    for Counter := 0 to PythonList.Items.Count - 1 do
    begin
      if (PythonList.Checked[Counter]) and (PythonList.ItemLevel[Counter] = 1) then
      begin
        Idx := Integer(PythonList.ItemObject[Counter]);
        with PythonInstallations[Idx] do
        begin
          if Bitness = 64 then
            Python64Path := InstallPath
          else if Bitness = 32 then
            Python32Path := InstallPath;
        end;
      end;
    end;
  end
  else if CurPageID = wpSelectComponents then
  begin
    if not IsComponentSelected('vs32 or vs64') then
    begin
      Result := False;
      MsgBox('At least one version of the core library has to be installed.', mbCriticalError, MB_OK)
    end;

    PopulatePythonInstallations(PythonList);
  end
  else if CurPageID = wpReady then
  begin
    if IsComponentSelected('vs32') and not Runtimes32Added then
    begin
      SetForceX86(True);
      vcredist2013();
      vcredist2015();
      SetForceX86(False);
      Runtimes32Added := True;
    end;
    if IsComponentSelected('vs64') and not Runtimes64Added then
    begin
      vcredist2013();
      vcredist2015();
      Runtimes64Added := True;
    end;
    Result := NextButtonClick2(CurPageID);
  end;
end;


added Pillow

added Pillow

; Script generated by the Inno Script Studio Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "AvNav"
#define MyAppVersion "1.0"
#define MyAppPublisher "Andreas Vogel"
#define MyAppURL "http://www.wellenvogel.de/software/avnav"
#define MyAppExeName "AvChartConvert.exe"
#define RegKey "SOFTWARE\AvNav"
#define PythonMSI "python-2.7.10.msi"
#define PythonCode "{{E2B51919-207A-43EB-AE78-733F9C6797C2}"
#define PythonDir "python"
#define GdalMSI "gdal-111-1500-core.msi"
#define GdalCode "{{A811F26E-D8EE-4DDB-8E23-ED5386E98695}"
#define GdalDir "gdal"
#define GdalPythonMSI "GDAL-1.11.0.win32-py2.7.msi"
#define GdalPythonCode "{{B086ED88-4BB5-46E0-9CDA-8AA8ED2BF906}"
#define PillowWhl "Pillow-3.0.0-cp27-none-win32.whl"
#define KeyInstalledPython "installedPython"
#define KeyInstalledGdal "installedGdal"
#define KeyUnistallBase "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"

[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={{832C93A9-F8FA-4EE4-9447-2645D4340A13}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName={#MyAppName}
AllowNoIcons=yes
;OutputDir=C:\Users\andreas\Documents\GitHub\avnav\windows\installer
OutputBaseFilename=AvNavSetup
Compression=lzma
SolidCompression=yes

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

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked

[Files]
Source: "..\AvChartConvert.exe"; DestDir: "{app}"; Flags: ignoreversion
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
Source: "..\avnav_server_home.xml"; DestDir: "{app}"; DestName: "avnav_server.xml"
Source: "..\..\server\*.py"; DestDir: "{app}\scripts"
Source: "..\..\chartconvert\*.py"; DestDir: "{app}\scripts"
Source: "library\{#PythonMSI}"; DestDir: "{tmp}"
Source: "library\{#GdalMSI}"; DestDir: "{tmp}"
Source: "library\{#GdalPythonMSI}"; DestDir: "{tmp}"
Source: "library\{#PillowWhl}"; DestDir: "{tmp}"
Source: "..\..\viewer\avnav_min.js"; DestDir: "{app}\viewer"
Source: "..\..\viewer\loader.js"; DestDir: "{app}\viewer"
Source: "..\..\viewer\version.js"; DestDir: "{app}\viewer"
Source: "..\..\viewer\avnav_viewer.html"; DestDir: "{app}\viewer"
Source: "..\..\viewer\avnav_viewer.less"; DestDir: "{app}\viewer"
Source: "..\..\viewer\base.js"; DestDir: "{app}\viewer"
Source: "..\..\viewer\images\*.png"; DestDir: "{app}\viewer\images"
Source: "..\..\libraries\*"; DestDir: "{app}\libraries"; Flags: recursesubdirs; Excludes: "*.pyc,*debug.js"

[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon

[Run]
Filename: "{app}\{#MyAppExeName}"; Flags: nowait postinstall skipifsilent; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"
Filename: "msiexec.exe"; Parameters: "/i ""{tmp}\{#PythonMSI}"" /qb TARGETDIR=""{app}\{#PythonDir}"""; WorkingDir: "{tmp}"; Check: checkInstallPython
Filename: "msiexec.exe"; Parameters: "/i ""{tmp}\{#GdalMSI}"" /qb TARGETDIR=""{app}\{#GdalDir}"" INSTALLDIR=""{app}\{#GdalDir}"""; WorkingDir: "{tmp}"; Check: checkInstallGdal
Filename: "msiexec.exe"; Parameters: "/i ""{tmp}\{#GdalPythonMSI}"" /qb TARGETDIR=""{app}\{#GdalDir}"" INSTALLDIR=""{app}\{#GdalDir}"""; WorkingDir: "{tmp}"; Check: checkInstallGdal

[Registry]
Root: "HKLM"; Subkey: "{#RegKey}"; ValueType: string; ValueName: "InstallDir"; ValueData: "{app}"; Flags: createvalueifdoesntexist  uninsdeletekey
Root: "HKLM"; Subkey: "{#RegKey}"; ValueType: string; ValueName: "{#KeyInstalledPython}"; ValueData: "true"; Flags: createvalueifdoesntexist uninsdeletekey; Check: checkInstallPython
Root: "HKLM"; Subkey: "{#RegKey}"; ValueType: string; ValueName: "{#KeyInstalledGdal}"; ValueData: "true"; Flags: createvalueifdoesntexist uninsdeletekey; Check: checkInstallGdal

[Code]

function findPip(): string;
var
val: string;
pip: string;
spos: integer;
begin
  Result:='';
  if RegQueryStringValue(HKEY_CLASSES_ROOT,'Python.File\shell\open\command','',val) then begin
       spos:=Pos('" ',val);
       if spos > 0 then begin
         val:=copy(val,1,spos);
       end;
       val:=RemoveQuotes(val);
       Log('val='+val);
       pip:=ExtractFilePath(val)+'\scripts\pip.exe';
       //MsgBox('found pip at '+pip,mbError, MB_OK);
       Result:=pip;
  end;
end;

function BoolToStr(ip:Boolean): string;
begin
  if ip then
  begin
    Result:='true';
  end else begin
    Result:='false';
  end;
end;

function isProductInstalled(ProductCode: String): Boolean;
var rkey:string;
begin
  rkey:=ExpandConstant('{#KeyUnistallBase}')+ProductCode;
  Log('isProductInstalled '+rkey);
  Result:=RegKeyExists(HKEY_LOCAL_MACHINE,rkey);
end;

var
OptionPage: TInputOptionWizardPage;
uninstallPython: Boolean;
uninstallGdal: Boolean;
procedure InitializeWizard;
var
subcap:String;
pythonInstalled:Boolean;
gdalInstalled: Boolean;

begin
  { Create the pages }
  subcap:='If select to install python/gdal the embedded python/gdal will become your default';
  pythonInstalled:=isProductInstalled(ExpandConstant('{#PythonCode}'));
  Log('pythonInstalled: '+BoolToStr(pythonInstalled));
  gdalInstalled:=isProductInstalled(ExpandConstant('{#GdalCode}'));
  Log('gdalInstalled: '+BoolToStr(gdalInstalled));
  if pythonInstalled then begin
    subcap:=subcap+#13+'HINT: Python 2.7 is already installed';
  end;
  if gdalInstalled then begin
    subcap:=subcap+#13+'HINT: gdal is already installed';
  end;
  OptionPage := CreateInputOptionPage(wpWelcome,
    'Install Python/GDAL', 'Select if you want to install the embedded python/gdal',
    subcap,
    True, False);
  OptionPage.AddEx('Install Python',0,false);
  OptionPage.AddEx('Install GDAL',0,false);
  OptionPage.Values[0]:= not pythonInstalled;
  OptionPage.Values[1]:= not gdalInstalled;
end;

function checkInstall(index:integer): Boolean;
begin
  Result:=OptionPage.Values[index];
end;

function checkInstallPython(): Boolean;
begin
  Result:=checkInstall(0);
end;

function checkInstallGdal(): Boolean;
begin
  Result:=checkInstall(1);
end;

procedure CurStepChanged(CurStep: TSetupStep);
var
pip:string;
ResultCode: integer;
begin
  if CurStep = ssPostInstall then begin
    pip:=findPip();
    Log('pip found at '+pip);
    if FileExists(pip) then begin
       Exec(pip,'install "'+ExpandConstant('{tmp}\{#PillowWhl}')+'"','',SW_SHOW,ewWaitUntilTerminated, ResultCode);
       if ResultCode <> 0 then begin
         MsgBox('error during installing Pillow ',mbError, MB_OK);
       end
    end else begin
      MsgBox('unable to find pip for python, cannot install Pillow ',mbError, MB_OK);
    end;
  end;
end;

//check if a feature was installed by us
function CheckFeature(Name:String;Key:String): Boolean;
var
  path: String;
  isInstalledByUs: string;
  dirpath: string;
  rkey: string;
begin
  Result:= False;
  rkey:=ExpandConstant('{#RegKey}');
  if RegQueryStringValue(HKEY_LOCAL_MACHINE,rkey,Key,isInstalledByUs) then begin
    if isInstalledByUs = 'true' then begin
      if RegQueryStringValue(HKEY_LOCAL_MACHINE, rkey,'InstallDir', path) then  begin
        dirpath:=path+'\'+Name;
        Result:=DirExists(dirpath);
      end;
    end;
  end;
end;

//Deinstall functions
procedure DeinstallFeature(fkey:String);
var
  ResultCode: Integer;
begin
    Exec('msiexec.exe', '/x '+fkey+' /qb', '', SW_SHOW,
     ewWaitUntilTerminated, ResultCode)
    Log('Deinstall for '+fkey+' ended with '+IntToStr(ResultCode));
end;

function InitializeUninstall(): Boolean;
begin
  Result:=true;
  uninstallPython:=checkFeature(ExpandConstant('{#PythonDir}'),ExpandConstant('{#KeyInstalledPython}'));
  uninstallGdal:=checkFeature(ExpandConstant('{#GdalDir}'),ExpandConstant('{#KeyInstalledGdal}'));
end;
//take the uninstall id from the properties of the MSI
//getmsiinfo.py library\python-2.7.10.msi "ProductCode"
//would be better to check for the python install dir...
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
  if CurUninstallStep = usPostUninstall then begin
    if uninstallPython then
    begin
      DeinstallFeature(ExpandConstant('{#PythonCode}'));
    end;
    if uninstallGdal then
    begin
      DeinstallFeature(ExpandConstant('{#GdalCode}'));
      DeinstallFeature(ExpandConstant('{#GdalPythonCode}'));
    end;
  end;
end;

; Script generated by the Inno Script Studio Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "AvNav"
#define MyAppVersion "1.0"
#define MyAppPublisher "Andreas Vogel"
#define MyAppURL "http://www.wellenvogel.de/software/avnav"
#define MyAppExeName "AvChartConvert.exe"
#define RegKey "SOFTWARE\AvNav"
#define PythonMSI "python-2.7.10.msi"
#define PythonCode "{{E2B51919-207A-43EB-AE78-733F9C6797C2}"
#define PythonDir "python"
#define GdalMSI "gdal-111-1500-core.msi"
#define GdalCode "{{A811F26E-D8EE-4DDB-8E23-ED5386E98695}"
#define GdalDir "gdal"
#define GdalPythonMSI "GDAL-1.11.0.win32-py2.7.msi"
#define GdalPythonCode "{{B086ED88-4BB5-46E0-9CDA-8AA8ED2BF906}"
#define KeyInstalledPython "installedPython"
#define KeyInstalledGdal "installedGdal"
#define KeyUnistallBase "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"

[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={{832C93A9-F8FA-4EE4-9447-2645D4340A13}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName={#MyAppName}
AllowNoIcons=yes
;OutputDir=C:\Users\andreas\Documents\GitHub\avnav\windows\installer
OutputBaseFilename=AvNavSetup
Compression=lzma
SolidCompression=yes

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

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked

[Files]
Source: "..\AvChartConvert.exe"; DestDir: "{app}"; Flags: ignoreversion
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
Source: "..\avnav_server_home.xml"; DestDir: "{app}"; DestName: "avnav_server.xml"
Source: "..\..\server\*.py"; DestDir: "{app}\scripts"
Source: "..\..\chartconvert\*.py"; DestDir: "{app}\scripts"
Source: "library\{#PythonMSI}"; DestDir: "{tmp}"
Source: "library\{#GdalMSI}"; DestDir: "{tmp}"
Source: "library\{#GdalPythonMSI}"; DestDir: "{tmp}"
Source: "..\..\viewer\avnav_min.js"; DestDir: "{app}\viewer"
Source: "..\..\viewer\loader.js"; DestDir: "{app}\viewer"
Source: "..\..\viewer\version.js"; DestDir: "{app}\viewer"
Source: "..\..\viewer\avnav_viewer.html"; DestDir: "{app}\viewer"
Source: "..\..\viewer\avnav_viewer.less"; DestDir: "{app}\viewer"
Source: "..\..\viewer\base.js"; DestDir: "{app}\viewer"
Source: "..\..\viewer\images\*.png"; DestDir: "{app}\viewer\images"
Source: "..\..\libraries\*"; DestDir: "{app}\libraries"; Flags: recursesubdirs; Excludes: "*.pyc,*debug.js"

[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon

[Run]
Filename: "{app}\{#MyAppExeName}"; Flags: nowait postinstall skipifsilent; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"
Filename: "msiexec.exe"; Parameters: "/i ""{tmp}\{#PythonMSI}"" /qb TARGETDIR=""{app}\{#PythonDir}"""; WorkingDir: "{tmp}"; Check: checkInstallPython
Filename: "msiexec.exe"; Parameters: "/i ""{tmp}\{#GdalMSI}"" /qb TARGETDIR=""{app}\{#GdalDir}"" INSTALLDIR=""{app}\{#GdalDir}"""; WorkingDir: "{tmp}"; Check: checkInstallGdal
Filename: "msiexec.exe"; Parameters: "/i ""{tmp}\{#GdalPythonMSI}"" /qb TARGETDIR=""{app}\{#GdalDir}"" INSTALLDIR=""{app}\{#GdalDir}"""; WorkingDir: "{tmp}"; Check: checkInstallGdal

[Registry]
Root: "HKLM"; Subkey: "{#RegKey}"; ValueType: string; ValueName: "InstallDir"; ValueData: "{app}"; Flags: createvalueifdoesntexist  uninsdeletekey
Root: "HKLM"; Subkey: "{#RegKey}"; ValueType: string; ValueName: "{#KeyInstalledPython}"; ValueData: "true"; Flags: createvalueifdoesntexist uninsdeletekey; Check: checkInstallPython
Root: "HKLM"; Subkey: "{#RegKey}"; ValueType: string; ValueName: "{#KeyInstalledGdal}"; ValueData: "true"; Flags: createvalueifdoesntexist uninsdeletekey; Check: checkInstallGdal

[Code]
function BoolToStr(ip:Boolean): string;
begin
  if ip then
  begin
    Result:='true';
  end else begin
    Result:='false';
  end;
end;

function isProductInstalled(ProductCode: String): Boolean;
var rkey:string;
begin
  rkey:=ExpandConstant('{#KeyUnistallBase}')+ProductCode;
  Log('isProductInstalled '+rkey);
  Result:=RegKeyExists(HKEY_LOCAL_MACHINE,rkey);
end;

var
OptionPage: TInputOptionWizardPage;
uninstallPython: Boolean;
uninstallGdal: Boolean;
procedure InitializeWizard;
var
subcap:String;
pythonInstalled:Boolean;
gdalInstalled: Boolean;

begin
  { Create the pages }
  subcap:='If select to install python/gdal the embedded python/gdal will become your default';
  pythonInstalled:=isProductInstalled(ExpandConstant('{#PythonCode}'));
  Log('pythonInstalled: '+BoolToStr(pythonInstalled));
  gdalInstalled:=isProductInstalled(ExpandConstant('{#GdalCode}'));
  Log('gdalInstalled: '+BoolToStr(gdalInstalled));
  if pythonInstalled then begin
    subcap:=subcap+#13+'HINT: Python 2.7 is already installed';
  end;
  if gdalInstalled then begin
    subcap:=subcap+#13+'HINT: gdal is already installed';
  end;
  OptionPage := CreateInputOptionPage(wpWelcome,
    'Install Python/GDAL', 'Select if you want to install the embedded python/gdal',
    subcap,
    True, False);
  OptionPage.AddEx('Install Python',0,false);
  OptionPage.AddEx('Install GDAL',0,false);
  OptionPage.Values[0]:= not pythonInstalled;
  OptionPage.Values[1]:= not gdalInstalled;
end;

function checkInstall(index:integer): Boolean;
begin
  Result:=OptionPage.Values[index];
end;

function checkInstallPython(): Boolean;
begin
  Result:=checkInstall(0);
end;

function checkInstallGdal(): Boolean;
begin
  Result:=checkInstall(1);
end;

//check if a feature was installed by us
function CheckFeature(Name:String;Key:String): Boolean;
var
  path: String;
  isInstalledByUs: string;
  dirpath: string;
  rkey: string;
begin
  Result:= False;
  rkey:=ExpandConstant('{#RegKey}');
  if RegQueryStringValue(HKEY_LOCAL_MACHINE,rkey,Key,isInstalledByUs) then begin
    if isInstalledByUs = 'true' then begin
      if RegQueryStringValue(HKEY_LOCAL_MACHINE, rkey,'InstallDir', path) then  begin
        dirpath:=path+'\'+Name;
        Result:=DirExists(dirpath);
      end;
    end;
  end;
end;

procedure DeinstallFeature(fkey:String);
var
  ResultCode: Integer;
begin
    Exec('msiexec.exe', '/x '+fkey+' /qb', '', SW_SHOW,
     ewWaitUntilTerminated, ResultCode)
    Log('Deinstall for '+fkey+' ended with '+IntToStr(ResultCode));
end;

function InitializeUninstall(): Boolean;
begin
  Result:=true;
  uninstallPython:=checkFeature(ExpandConstant('{#PythonDir}'),ExpandConstant('{#KeyInstalledPython}'));
  uninstallGdal:=checkFeature(ExpandConstant('{#GdalDir}'),ExpandConstant('{#KeyInstalledGdal}'));
end;
//take the uninstall id from the properties of the MSI
//getmsiinfo.py library\python-2.7.10.msi "ProductCode"
//would be better to check for the python install dir...
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
  if CurUninstallStep = usPostUninstall then begin
    if uninstallPython then
    begin
      DeinstallFeature(ExpandConstant('{#PythonCode}'));
    end;
    if uninstallGdal then
    begin
      DeinstallFeature(ExpandConstant('{#GdalCode}'));
      DeinstallFeature(ExpandConstant('{#GdalPythonCode}'));
    end;
  end;
end;


Bump to v1.3.2

Bump to v1.3.2

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "Boot2Docker for Windows"
#define MyAppVersion "1.3.2"
#define MyAppPublisher "Docker Inc"
#define MyAppURL "https://docker.com"
#define MyAppContact "https://docs.docker.com"

#define b2dIso ".\Boot2Docker\boot2docker.iso"
#define b2dCli ".\Boot2Docker\boot2docker.exe"

; https://msysgit.github.io
; or https://github.com/msysgit/msysgit/releases/latest
#define msysGit ".\msysGit\Git-1.9.4-preview20140929.exe"

; https://www.virtualbox.org/wiki/Downloads
; Then, run "VirtualBox-x.x.x-xxx-Win.exe --extract --path ."
#define virtualBoxCommon ".\VirtualBox\common.cab"
#define virtualBoxMsi ".\VirtualBox\VirtualBox-4.3.18-r96516-MultiArch_amd64.msi"

[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={{05BD04E9-4AB5-46AC-891E-60EA8FD57D56}
AppCopyright={#MyAppPublisher}
AppContact={#MyAppContact}
AppComments={#MyAppURL}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
ArchitecturesAllowed=x64
ArchitecturesInstallIn64BitMode=x64
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName=Docker
; lets not be annoying
;InfoBeforeFile=.\LICENSE
;DisableFinishedPage
;InfoAfterFile=
OutputBaseFilename=docker-install
Compression=lzma
SolidCompression=yes
WizardImageFile=logo-docker-side.bmp
WizardSmallImageFile=logo-docker-small.bmp
WizardImageStretch=no
WizardImageBackColor=$325461

; in the installer itself:
SetupIconFile=boot2docker.ico
; in the "Add/Remove" list:
UninstallDisplayIcon={app}\boot2docker.ico

SignTool=ksign /d $q{#MyAppName}$q /du $q{#MyAppURL}$q $f

; for modpath.iss
ChangesEnvironment=true

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

[Types]
Name: "full"; Description: "Full installation"
Name: "upgrade"; Description: "Upgrade Boot2Docker only"
Name: "custom"; Description: "Custom installation"; Flags: iscustom

[Tasks]
Name: desktopicon; Description: "{cm:CreateDesktopIcon}"
Name: modifypath; Description: "Add boot2docker.exe to &PATH"
Name: rebootwindows; Description: "&Reboot Windows at the end of installation"; Flags: restart unchecked

[Components]
Name: "Boot2Docker"; Description: "Boot2Docker management tool and ISO" ; Types: full upgrade
Name: "VirtualBox"; Description: "VirtualBox"; Types: full
Name: "MSYS"; Description: "MSYS-git UNIX tools"; Types: full

[Files]
Source: ".\boot2docker.ico"; DestDir: "{app}"; Flags: ignoreversion

; Boot2Docker
Source: "{#b2dIso}"; DestDir: "{app}"; Flags: ignoreversion; Components: "Boot2Docker"
Source: "{#b2dCli}"; DestDir: "{app}"; Flags: ignoreversion; Components: "Boot2Docker"
Source: ".\start.sh"; DestDir: "{app}"; Flags: ignoreversion; Components: "Boot2Docker"
Source: ".\delete.sh"; DestDir: "{app}"; Flags: ignoreversion; Components: "Boot2Docker"

; msys-Git
Source: "{#msysGit}"; DestDir: "{app}\installers\msys-git"; DestName: "msys-git.exe"; AfterInstall: RunInstallMSYS();  Components: "MSYS"

; VirtualBox
Source: "{#virtualBoxCommon}"; DestDir: "{app}\installers\virtualbox"; Components: "VirtualBox"
Source: "{#virtualBoxMsi}"; DestDir: "{app}\installers\virtualbox"; DestName: "virtualbox.msi"; AfterInstall: RunInstallVirtualBox(); Components: "VirtualBox"

; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
Name: "{group}\Boot2Docker Start"; WorkingDir: "{app}"; Filename: "{app}\start.sh"; IconFilename: "{app}/boot2docker.ico"
Name: "{commondesktop}\Boot2Docker Start"; WorkingDir: "{app}"; Filename: "{app}\start.sh"; IconFilename: "{app}/boot2docker.ico"; Tasks: desktopicon
Name: "{commonprograms}\Boot2Docker Start"; WorkingDir: "{app}"; Filename: "{app}\start.sh"; IconFilename: "{app}/boot2docker.ico"
Name: "{group}\Delete Boot2Docker VM"; WorkingDir: "{app}"; Filename: "{app}\delete.sh"

[UninstallRun]
Filename: "{app}\delete.sh"

[Code]
var
	restart: boolean;
// http://stackoverflow.com/questions/9238698/show-licenseagreement-link-in-innosetup-while-installation
	DockerInstallDocs: TLabel;

const
	UninstallKey = 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{#SetupSetting("AppId")}_is1';
//  32 bit on 64  HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall

function IsUpgrade: Boolean;
var
	Value: string;
begin
	Result := (
		RegQueryStringValue(HKLM, UninstallKey, 'UninstallString', Value)
		or
		RegQueryStringValue(HKCU, UninstallKey, 'UninstallString', Value)
	) and (Value <> '');
end;

function NeedRestart(): Boolean;
begin
	Result := restart;
end;

function NeedToInstallVirtualBox(): Boolean;
begin
	Result := (
		(GetEnv('VBOX_INSTALL_PATH') = '')
		and
		(GetEnv('VBOX_MSI_INSTALL_PATH') = '')
	);
end;

function NeedToInstallMSYS(): Boolean;
begin
	Result := not RegKeyExists(HKEY_LOCAL_MACHINE, 'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Git_is1');
end;

procedure DocLinkClick(Sender: TObject);
var
	ErrorCode: Integer;
begin
	ShellExec('', 'https://docs.docker.com/installation/windows/', '', '', SW_SHOW, ewNoWait, ErrorCode);
end;

procedure InitializeWizard;
begin
	DockerInstallDocs := TLabel.Create(WizardForm);
	DockerInstallDocs.Parent := WizardForm;
	DockerInstallDocs.Left := 8;
	DockerInstallDocs.Top := WizardForm.ClientHeight - DockerInstallDocs.ClientHeight - 8;
	DockerInstallDocs.Cursor := crHand;
	DockerInstallDocs.Font.Color := clBlue;
	DockerInstallDocs.Font.Style := [fsUnderline];
	DockerInstallDocs.Caption := '{#MyAppName} installation documentation';
	DockerInstallDocs.OnClick := @DocLinkClick;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
	DockerInstallDocs.Visible := True;

	WizardForm.FinishedLabel.AutoSize := True;
	WizardForm.FinishedLabel.Caption :=
		'{#MyAppName} installation completed.' + \
		#13#10 + \
		#13#10 + \
		'Run using the `Boot2Docker Start` icon on your desktop or in [Program Files] - then start a test container with:' + \
		#13#10 + \
		'         `docker run hello-world`' + \
		#13#10 + \
		#13#10 + \
		// TODO: it seems making hyperlinks is hard :/
		//'To save and share container images, automate workflows, and more sign-up for a free Docker Hub account.' + \
		#13#10 + \
		#13#10 +
		'You can upgrade your existing Boot2Docker VM without data loss by running:' + \
		#13#10 + \
		'         `boot2docker upgrade`' + \
		#13#10 + \
		#13#10 + \
		'For further information, please see the {#MyAppName} installation documentation link.'
	;
	//if CurPageID = wpSelectDir then
		// to go with DisableReadyPage=yes and DisableProgramGroupPage=yes
		//WizardForm.NextButton.Caption := SetupMessage(msgButtonInstall)
	//else
		//WizardForm.NextButton.Caption := SetupMessage(msgButtonNext);
	//if CurPageID = wpFinished then
		//WizardForm.NextButton.Caption := SetupMessage(msgButtonFinish)
		if CurPageID = wpSelectComponents then
		begin
			if IsUpgrade() then
			begin
				Wizardform.TypesCombo.ItemIndex := 2
			end;
			Wizardform.ComponentsList.Checked[1] := NeedToInstallVirtualBox();
			Wizardform.ComponentsList.Checked[2] := NeedToInstallMSYS();
		end;
end;

procedure RunInstallVirtualBox();
var
	ResultCode: Integer;
begin
	WizardForm.FilenameLabel.Caption := 'installing VirtualBox'
	if Exec(ExpandConstant('msiexec'), ExpandConstant('/qn /i "{app}\installers\virtualbox\virtualbox.msi" /norestart'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
	begin
		// handle success if necessary; ResultCode contains the exit code
		//MsgBox('virtualbox install OK', mbInformation, MB_OK);
	end
	else begin
		// handle failure if necessary; ResultCode contains the error code
		MsgBox('virtualbox install failure', mbInformation, MB_OK);
	end;
	//restart := True;
end;

procedure RunInstallMSYS();
var
	ResultCode: Integer;
begin
	WizardForm.FilenameLabel.Caption := 'installing MSYS Git'
	if Exec(ExpandConstant('{app}\installers\msys-git\msys-git.exe'), '/sp- /verysilent /norestart', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
	begin
		// handle success if necessary; ResultCode contains the exit code
		//MsgBox('msys installed OK', mbInformation, MB_OK);
	end
	else begin
		// handle failure if necessary; ResultCode contains the error code
		MsgBox('msys install failure', mbInformation, MB_OK);
	end;
end;

const
	ModPathName = 'modifypath';
	ModPathType = 'user';

function ModPathDir(): TArrayOfString;
begin
	setArrayLength(Result, 1);
	Result[0] := ExpandConstant('{app}');
end;
#include "modpath.iss"

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "Boot2Docker for Windows"
#define MyAppVersion "1.3.1"
#define MyAppPublisher "Docker Inc"
#define MyAppURL "https://docker.com"
#define MyAppContact "https://docs.docker.com"

#define b2dIso ".\Boot2Docker\boot2docker.iso"
#define b2dCli ".\Boot2Docker\boot2docker.exe"

; https://msysgit.github.io
; or https://github.com/msysgit/msysgit/releases/latest
#define msysGit ".\msysGit\Git-1.9.4-preview20140929.exe"

; https://www.virtualbox.org/wiki/Downloads
; Then, run "VirtualBox-x.x.x-xxx-Win.exe --extract --path ."
#define virtualBoxCommon ".\VirtualBox\common.cab"
#define virtualBoxMsi ".\VirtualBox\VirtualBox-4.3.18-r96516-MultiArch_amd64.msi"

[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={{05BD04E9-4AB5-46AC-891E-60EA8FD57D56}
AppCopyright={#MyAppPublisher}
AppContact={#MyAppContact}
AppComments={#MyAppURL}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
ArchitecturesAllowed=x64
ArchitecturesInstallIn64BitMode=x64
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName=Docker
; lets not be annoying
;InfoBeforeFile=.\LICENSE
;DisableFinishedPage
;InfoAfterFile=
OutputBaseFilename=docker-install
Compression=lzma
SolidCompression=yes
WizardImageFile=logo-docker-side.bmp
WizardSmallImageFile=logo-docker-small.bmp
WizardImageStretch=no
WizardImageBackColor=$325461

; in the installer itself:
SetupIconFile=boot2docker.ico
; in the "Add/Remove" list:
UninstallDisplayIcon={app}\boot2docker.ico

SignTool=ksign /d $q{#MyAppName}$q /du $q{#MyAppURL}$q $f

; for modpath.iss
ChangesEnvironment=true

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

[Types]
Name: "full"; Description: "Full installation"
Name: "upgrade"; Description: "Upgrade Boot2Docker only"
Name: "custom"; Description: "Custom installation"; Flags: iscustom

[Tasks]
Name: desktopicon; Description: "{cm:CreateDesktopIcon}"
Name: modifypath; Description: "Add boot2docker.exe to &PATH"
Name: rebootwindows; Description: "&Reboot Windows at the end of installation"; Flags: restart unchecked

[Components]
Name: "Boot2Docker"; Description: "Boot2Docker management tool and ISO" ; Types: full upgrade
Name: "VirtualBox"; Description: "VirtualBox"; Types: full
Name: "MSYS"; Description: "MSYS-git UNIX tools"; Types: full

[Files]
Source: ".\boot2docker.ico"; DestDir: "{app}"; Flags: ignoreversion

; Boot2Docker
Source: "{#b2dIso}"; DestDir: "{app}"; Flags: ignoreversion; Components: "Boot2Docker"
Source: "{#b2dCli}"; DestDir: "{app}"; Flags: ignoreversion; Components: "Boot2Docker"
Source: ".\start.sh"; DestDir: "{app}"; Flags: ignoreversion; Components: "Boot2Docker"
Source: ".\delete.sh"; DestDir: "{app}"; Flags: ignoreversion; Components: "Boot2Docker"

; msys-Git
Source: "{#msysGit}"; DestDir: "{app}\installers\msys-git"; DestName: "msys-git.exe"; AfterInstall: RunInstallMSYS();  Components: "MSYS"

; VirtualBox
Source: "{#virtualBoxCommon}"; DestDir: "{app}\installers\virtualbox"; Components: "VirtualBox"
Source: "{#virtualBoxMsi}"; DestDir: "{app}\installers\virtualbox"; DestName: "virtualbox.msi"; AfterInstall: RunInstallVirtualBox(); Components: "VirtualBox"

; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
Name: "{group}\Boot2Docker Start"; WorkingDir: "{app}"; Filename: "{app}\start.sh"; IconFilename: "{app}/boot2docker.ico"
Name: "{commondesktop}\Boot2Docker Start"; WorkingDir: "{app}"; Filename: "{app}\start.sh"; IconFilename: "{app}/boot2docker.ico"; Tasks: desktopicon
Name: "{commonprograms}\Boot2Docker Start"; WorkingDir: "{app}"; Filename: "{app}\start.sh"; IconFilename: "{app}/boot2docker.ico"
Name: "{group}\Delete Boot2Docker VM"; WorkingDir: "{app}"; Filename: "{app}\delete.sh"

[UninstallRun]
Filename: "{app}\delete.sh"

[Code]
var
	restart: boolean;
// http://stackoverflow.com/questions/9238698/show-licenseagreement-link-in-innosetup-while-installation
	DockerInstallDocs: TLabel;

const
	UninstallKey = 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{#SetupSetting("AppId")}_is1';
//  32 bit on 64  HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall

function IsUpgrade: Boolean;
var
	Value: string;
begin
	Result := (
		RegQueryStringValue(HKLM, UninstallKey, 'UninstallString', Value)
		or
		RegQueryStringValue(HKCU, UninstallKey, 'UninstallString', Value)
	) and (Value <> '');
end;

function NeedRestart(): Boolean;
begin
	Result := restart;
end;

function NeedToInstallVirtualBox(): Boolean;
begin
	Result := (
		(GetEnv('VBOX_INSTALL_PATH') = '')
		and
		(GetEnv('VBOX_MSI_INSTALL_PATH') = '')
	);
end;

function NeedToInstallMSYS(): Boolean;
begin
	Result := not RegKeyExists(HKEY_LOCAL_MACHINE, 'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Git_is1');
end;

procedure DocLinkClick(Sender: TObject);
var
	ErrorCode: Integer;
begin
	ShellExec('', 'https://docs.docker.com/installation/windows/', '', '', SW_SHOW, ewNoWait, ErrorCode);
end;

procedure InitializeWizard;
begin
	DockerInstallDocs := TLabel.Create(WizardForm);
	DockerInstallDocs.Parent := WizardForm;
	DockerInstallDocs.Left := 8;
	DockerInstallDocs.Top := WizardForm.ClientHeight - DockerInstallDocs.ClientHeight - 8;
	DockerInstallDocs.Cursor := crHand;
	DockerInstallDocs.Font.Color := clBlue;
	DockerInstallDocs.Font.Style := [fsUnderline];
	DockerInstallDocs.Caption := '{#MyAppName} installation documentation';
	DockerInstallDocs.OnClick := @DocLinkClick;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
	DockerInstallDocs.Visible := True;

	WizardForm.FinishedLabel.AutoSize := True;
	WizardForm.FinishedLabel.Caption :=
		'{#MyAppName} installation completed.' + \
		#13#10 + \
		#13#10 + \
		'Run using the `Boot2Docker Start` icon on your desktop or in [Program Files] - then start a test container with:' + \
		#13#10 + \
		'         `docker run hello-world`' + \
		#13#10 + \
		#13#10 + \
		// TODO: it seems making hyperlinks is hard :/
		//'To save and share container images, automate workflows, and more sign-up for a free Docker Hub account.' + \
		#13#10 + \
		#13#10 +
		'You can upgrade your existing Boot2Docker VM without data loss by running:' + \
		#13#10 + \
		'         `boot2docker upgrade`' + \
		#13#10 + \
		#13#10 + \
		'For further information, please see the {#MyAppName} installation documentation link.'
	;
	//if CurPageID = wpSelectDir then
		// to go with DisableReadyPage=yes and DisableProgramGroupPage=yes
		//WizardForm.NextButton.Caption := SetupMessage(msgButtonInstall)
	//else
		//WizardForm.NextButton.Caption := SetupMessage(msgButtonNext);
	//if CurPageID = wpFinished then
		//WizardForm.NextButton.Caption := SetupMessage(msgButtonFinish)
		if CurPageID = wpSelectComponents then
		begin
			if IsUpgrade() then
			begin
				Wizardform.TypesCombo.ItemIndex := 2
			end;
			Wizardform.ComponentsList.Checked[1] := NeedToInstallVirtualBox();
			Wizardform.ComponentsList.Checked[2] := NeedToInstallMSYS();
		end;
end;

procedure RunInstallVirtualBox();
var
	ResultCode: Integer;
begin
	WizardForm.FilenameLabel.Caption := 'installing VirtualBox'
	if Exec(ExpandConstant('msiexec'), ExpandConstant('/qn /i "{app}\installers\virtualbox\virtualbox.msi" /norestart'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
	begin
		// handle success if necessary; ResultCode contains the exit code
		//MsgBox('virtualbox install OK', mbInformation, MB_OK);
	end
	else begin
		// handle failure if necessary; ResultCode contains the error code
		MsgBox('virtualbox install failure', mbInformation, MB_OK);
	end;
	//restart := True;
end;

procedure RunInstallMSYS();
var
	ResultCode: Integer;
begin
	WizardForm.FilenameLabel.Caption := 'installing MSYS Git'
	if Exec(ExpandConstant('{app}\installers\msys-git\msys-git.exe'), '/sp- /verysilent /norestart', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
	begin
		// handle success if necessary; ResultCode contains the exit code
		//MsgBox('msys installed OK', mbInformation, MB_OK);
	end
	else begin
		// handle failure if necessary; ResultCode contains the error code
		MsgBox('msys install failure', mbInformation, MB_OK);
	end;
end;

const
	ModPathName = 'modifypath';
	ModPathType = 'user';

function ModPathDir(): TArrayOfString;
begin
	setArrayLength(Result, 1);
	Result[0] := ExpandConstant('{app}');
end;
#include "modpath.iss"


Update slim seup for updater work

Update slim seup for updater work

; Script generated by the Inno Script Studio Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "Imperial Splendour"
#define MyAppVersion "2.0"
#define MyAppPublisher "Imperial Splendour"
#define MyAppURL "https://imperialsplendour.com/"
#define MyAppExeName "ImperialSplendour.exe"
#define TmpFolder "ImperialSplendour"
#define DownloadLink "https://www.moddb.com/downloads/mirror/175422/120/3fac5f37002048a03404b3345e0240af"
#define UninstallDir "IS_Uninstall"
#define UninstallHelperExe "deactivator.exe"
#define SetupName "ImperialSplendourSetup"
#define ETWDefaultPath "steam\steamapp\common\Empire Total War"

[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={{DC820B8B-AE7B-4555-AB8A-C1399266A06F}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DisableDirPage=yes
DefaultDirName={reg:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{#AppId}_is1,InstallLocation}
AlwaysShowDirOnReadyPage=yes
DefaultGroupName={#MyAppName}
OutputBaseFilename={#SetupName}
Compression=lzma
SolidCompression=yes
; 10GB = 10,737,418,240
ExtraDiskSpaceRequired=10737418240
DirExistsWarning=yes
SetupIconFile=appicon.ico
UninstallDisplayIcon={app}\{#MyAppExeName}
UninstallFilesDir={app}\{#UninstallDir}

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

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked

[Files]
Source: "{tmp}\{#TmpFolder}\*.*"; DestDir: "{app}"; Flags: external recursesubdirs

[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon

[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

[UninstallRun]
Filename: "{app}\{#UninstallDir}\{#UninstallHelperExe}"; WorkingDir: "{app}"

[CustomMessages]
english.NewerVersionExists=A newer version of {#AppName} is already installed.%n%nInstaller version: {#AppVersion}%nCurrent version:

[Code]

var ExpectedPath: String;
var HasInstallation: Boolean;
var
  StartupInfoPage: TInputQueryWizardPage;
  InputDirPage:    TInputDirWizardPage;
  DownloadPage:    TDownloadWizardPage;

// --- Custom Functions ---

function OnDownloadProgress(const Url, FileName: String; const Progress, ProgressMax: Int64): Boolean;
begin
  if Progress = ProgressMax then
    Log(Format('Successfully downloaded file to {tmp}: %s', [FileName]));
  Result := True;
end;

procedure unzip(ZipFile, TargetFldr: PAnsiChar);
var
 shellobj: variant;
 ZipFileV, TargetFldrV: variant;
 SrcFldr, DestFldr: variant;
 shellfldritems: variant;
begin
 if FileExists(ZipFile) then begin
   ForceDirectories(TargetFldr);
   shellobj := CreateOleObject('Shell.Application');
   ZipFileV := string(ZipFile);
   TargetFldrV := string(TargetFldr);
   SrcFldr := shellobj.NameSpace(ZipFileV);
   DestFldr := shellobj.NameSpace(TargetFldrV);
   shellfldritems := SrcFldr.Items;
   DestFldr.CopyHere(shellfldritems);
 end;
end;

procedure ExtractSomething(src, target : AnsiString);
begin
  log('extracting ' + ExpandConstant(src) + ' to ' + ExpandConstant(target))
  unzip(ExpandConstant(src), ExpandConstant(target));
end;

// --- HOOKS ---

function InitializeSetup: Boolean;
var Version: String;
var Location: String;
begin
  HasInstallation := RegValueExists(HKEY_LOCAL_MACHINE,'Software\Microsoft\Windows\CurrentVersion\Uninstall\{#AppId}_is1', 'DisplayVersion')
  if not HasInstallation then
    Result := True;
    Exit;
  end;

  RegQueryStringValue(HKEY_LOCAL_MACHINE,'Software\Microsoft\Windows\CurrentVersion\Uninstall\{#AppId}_is1', 'DisplayVersion', Version);
  if Version > '{#AppVersion}' then
    MsgBox(ExpandConstant('{cm:NewerVersionExists} '+Version), mbInformation, MB_OK);
    Result := False;
    Exit;

  RegQueryStringValue(HKEY_LOCAL_MACHINE,'Software\Microsoft\Windows\CurrentVersion\Uninstall\{#AppId}_is1', 'InstallLocation', Location);
  WizardForm.DirEdit.Text := Location
  Result := True;
end;

procedure InitializeWizard;
begin
  ExpectedPath := ExpandConstant('{commonpf}\{#ETWDefaultPath}');

  StartupInfoPage:= CreateInputQueryPage(wpWelcome,
    'Welcome',
    'Please read the following important information before continuing',
    'Requirements:'#13#10 +
    '- an Empire: Total War installation through Steam'#13#10 +
    '- at least 10GB of hard drive space'#13#10 +
    ''#13#10 +
    'NOTE: Having a different mod installed alongside Imperial Splendour can lead to issues when using the launcher. In this case, you can still use the installer but we recommend to switch between mods manually.');

  InputDirPage := CreateInputDirPage(StartupInfoPage.ID,
    'Select existing Empire: Total War Installation Location',
    '',
    'Imperial Splendour will be installed inside the following Empire: Total War folder.'#13#10 +
    ''#13#10 +
    'To continue, click Next. If you would like to select a different folder, click Browse.',
    False, '');
  InputDirPage.Add('');
  if DirExists(ExpectedPath) then
    InputDirPage.Values[0] := ExpectedPath
  else
    InputDirPage.Values[0] := '';

  DownloadPage := CreateDownloadPage(SetupMessage(msgWizardPreparing), SetupMessage(msgPreparingDesc), @OnDownloadProgress);
end;

function NextButtonClick(CurPageID: Integer): Boolean;
begin
  if CurPageID = StartupInfoPage.ID then
    if InputDirPage.Values[0] = '' then
      MsgBox('Couldn''t find your Empire Total War installation. Please make sure you have it installed correctly and manually select the install folder.', mbError, MB_OK);

    Result := true;
    Exit;

  if CurPageID = InputDirPage.ID then
    WizardForm.DirEdit.Text := InputDirPage.Values[0];
    Exit;

  if CurPageID = wpReady then begin
    if MsgBox('Downloading and installing all mod files may take a while. Continue?', mbConfirmation, MB_OKCANCEL) = IDCANCEL then
      Result := false;

    DownloadPage.Clear;
    DownloadPage.Add(ExpandConstant('{#DownloadLink}'), '{#TmpFolder}.zip', '');
    DownloadPage.Show;

    // double-try to ignore error when trying to extract non-downloaded files
    try
      try
        DownloadPage.Download; // This downloads the files to {tmp}
        Result := True;
      except
        // NOTE: This does not work in Inno Setup 6.1.2
        //if DownloadPage.AbortedByUser then
        //  Log('Aborted by user.')
        //else
        SuppressibleMsgBox(AddPeriod(GetExceptionMessage), mbCriticalError, MB_OK, IDOK);
        Result := False;
      end;
    finally
      ExtractSomething('{tmp}\{#TmpFolder}.zip', '{tmp}\{#TmpFolder}')
      DownloadPage.Hide;
    end;
  end else
    // you need this otherwise it'll try to install files it hasn't downloaded
    Result := True;

end;

function ShouldSkipPage(PageID: Integer): Boolean
begin
  if PageID = InputDirPage.ID and HasInstallation then
    Result := True
  else
    Result := False;
end;

function PrepareToInstall(var NeedsRestart: Boolean): String;
var ResultCode: Integer;
begin
  if not Exec(ExpandConstant('{#UninstallDir}\{#UninstallHelperExe}'), '-strict', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then
    Result := "There was an error preparing the upgrade. Please delete any remaining Imperial Splendour files manually and try again."
  else
    Result := ""
end;

; Script generated by the Inno Script Studio Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "Imperial Splendour"
#define MyAppVersion "2.0"
#define MyAppPublisher "Imperial Splendour"
#define MyAppURL "https://imperialsplendour.com/"
#define MyAppExeName "ImperialSplendour.exe"
#define TmpFolder "ImperialSplendour"
#define DownloadLink "https://www.moddb.com/downloads/mirror/175422/120/3fac5f37002048a03404b3345e0240af"
#define UninstallDir "IS_Uninstall"
#define UninstallHelperExe "deactivator.exe"
#define SetupName "ImperialSplendourSetup"
#define ETWDefaultPath "steam\steamapp\common\Empire Total War"

[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={{DC820B8B-AE7B-4555-AB8A-C1399266A06F}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DisableDirPage=yes
DefaultDirName={commonpf}
AlwaysShowDirOnReadyPage=yes
DefaultGroupName={#MyAppName}
OutputBaseFilename={#SetupName}
Compression=lzma
SolidCompression=yes
; 10GB = 10,737,418,240
ExtraDiskSpaceRequired=10737418240
DirExistsWarning=yes
SetupIconFile=appicon.ico
UninstallDisplayIcon={app}\{#MyAppExeName}
UninstallFilesDir={app}\{#UninstallDir}

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

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked

[Files]
Source: "{tmp}\{#TmpFolder}\*.*"; DestDir: "{app}"; Flags: external recursesubdirs

[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon

[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

[UninstallRun]
Filename: "{app}\{#UninstallDir}\{#UninstallHelperExe}"; WorkingDir: "{app}"

[Code]

var ExpectedPath: String;
var
  StartupInfoPage: TInputQueryWizardPage;
  InputDirPage:    TInputDirWizardPage;
  DownloadPage:    TDownloadWizardPage;

// --- Custom Functions ---

function OnDownloadProgress(const Url, FileName: String; const Progress, ProgressMax: Int64): Boolean;
begin
  if Progress = ProgressMax then
    Log(Format('Successfully downloaded file to {tmp}: %s', [FileName]));
  Result := True;
end;

procedure unzip(ZipFile, TargetFldr: PAnsiChar);
var
 shellobj: variant;
 ZipFileV, TargetFldrV: variant;
 SrcFldr, DestFldr: variant;
 shellfldritems: variant;
begin
 if FileExists(ZipFile) then begin
   ForceDirectories(TargetFldr);
   shellobj := CreateOleObject('Shell.Application');
   ZipFileV := string(ZipFile);
   TargetFldrV := string(TargetFldr);
   SrcFldr := shellobj.NameSpace(ZipFileV);
   DestFldr := shellobj.NameSpace(TargetFldrV);
   shellfldritems := SrcFldr.Items;
   DestFldr.CopyHere(shellfldritems);
 end;
end;

procedure ExtractSomething(src, target : AnsiString);
begin
  log('extracting ' + ExpandConstant(src) + ' to ' + ExpandConstant(target))
  unzip(ExpandConstant(src), ExpandConstant(target));
end;

// --- HOOKS ---

procedure InitializeWizard;
begin
  ExpectedPath := ExpandConstant('{commonpf}\{#ETWDefaultPath}');

  StartupInfoPage:= CreateInputQueryPage(wpWelcome,
    'Welcome',
    'Please read the following important information before continuing',
    'Requirements:'#13#10 +
    '- an Empire: Total War installation through Steam'#13#10 +
    '- at least 10GB of hard drive space'#13#10 +
    ''#13#10 +
    'NOTE: Having a different mod installed alongside Imperial Splendour can lead to issues when using the launcher. In this case, you can still use the installer but we recommend to switch between mods manually.');

  InputDirPage := CreateInputDirPage(StartupInfoPage.ID,
    'Select existing Empire: Total War Installation Location',
    '',
    'Imperial Splendour will be installed inside the following Empire: Total War folder.'#13#10 +
    ''#13#10 +
    'To continue, click Next. If you would like to select a different folder, click Browse.',
    False, '');
  InputDirPage.Add('');
  if DirExists(ExpectedPath) then
    InputDirPage.Values[0] := ExpectedPath
  else
    InputDirPage.Values[0] := '';

  DownloadPage := CreateDownloadPage(SetupMessage(msgWizardPreparing), SetupMessage(msgPreparingDesc), @OnDownloadProgress);

end;

function NextButtonClick(CurPageID: Integer): Boolean;
begin
  if CurPageID = StartupInfoPage.ID then
    if InputDirPage.Values[0] = '' then
      MsgBox('Couldn''t find your Empire Total War installation. Please make sure you have it installed correctly and manually select the install folder.', mbError, MB_OK);

    Result := true;

  if CurPageID = InputDirPage.ID then
    WizardForm.DirEdit.Text := InputDirPage.Values[0];

  if CurPageID = wpReady then begin
    if MsgBox('Downloading and installing all mod files may take a while. Continue?', mbConfirmation, MB_OKCANCEL) = IDCANCEL then
      Result := false;

    DownloadPage.Clear;
    DownloadPage.Add(ExpandConstant('{#DownloadLink}'), '{#TmpFolder}.zip', '');
    DownloadPage.Show;

    // double-try to ignore error when trying to extract non-downloaded files
    try
      try
        DownloadPage.Download; // This downloads the files to {tmp}
        Result := True;
      except
        // NOTE: This does not work in Inno Setup 6.1.2
        //if DownloadPage.AbortedByUser then
        //  Log('Aborted by user.')
        //else
        SuppressibleMsgBox(AddPeriod(GetExceptionMessage), mbCriticalError, MB_OK, IDOK);
        Result := False;
      end;
    finally
      ExtractSomething('{tmp}\{#TmpFolder}.zip', '{tmp}\{#TmpFolder}')
      DownloadPage.Hide;
    end;
  end else
    // you need this otherwise it'll try to install files it hasn't downloaded
    Result := True;

end;