Remove setup mgmt command from installer

Called the setup mgmt command, but apparently the KALITE_ROOT_DATA_PATH
  environment variable was not set properly -- the installer would have
  to exit first for the change to be broadcast.

Instead, let the app handle the setup the first time it's started.

#define MyAppName "KA Lite"
#define MyAppPublisher "Foundation for Learning Equality"
#define MyAppURL "http://learningequality.org/"
#define MyAppExeName "KA Lite.exe"

#define getKALiteVersion() \
    Local[1] = Exec(SourcePath+"\getversion.bat") == 0 ? StringChange(FileRead(FileOpen(SourcePath+"\version.temp")), " ", "") : "null"

#define TargetVersion = getKALiteVersion();

#expr DeleteFile(SourcePath+"\version.temp")

[Setup]
AppId={#MyAppName}-{#MyAppPublisher}
AppName={#MyAppName}
AppVersion={#TargetVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName={#MyAppName}
LicenseFile=..\ka-lite\LICENSE
OutputDir=..\
OutputBaseFilename=KALiteSetup-{#TargetVersion}
SetupIconFile=logo48.ico
Compression=lzma
SolidCompression=yes
PrivilegesRequired=admin
UsePreviousAppDir=yes
ChangesEnvironment=yes
AlwaysRestart=yes

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

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

[Files]
Source: "..\ka-lite\*"; DestDir: "{app}\ka-lite"; Excludes: ".KALITE_SOURCE_DIR,content\assessment,content\assessment\*,content\assessmentitems.sqlite"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\ka-lite\content\*"; DestDir: "{app}\ka-lite\content"; Excludes: "assessment,assessment\*,assessmentitems.sqlite"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\ka-lite\content\assessment\*"; DestDir: "{app}\ka-lite\assessment"; Excludes: "assessmentitems.sqlite"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\ka-lite\content\assessmentitems.sqlite"; DestDir: "{app}\ka-lite\assessment\khan"; Flags: ignoreversion
Source: "..\gui-packed\KA Lite.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\gui-packed\guitools.vbs"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\gui-packed\images\logo48.ico"; DestDir: "{app}\images"; Flags: ignoreversion
Source: "..\python-setup\*"; DestDir: "{app}\python-setup"; Flags: ignoreversion

[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\images\logo48.ico"
Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon ; IconFilename: "{app}\images\logo48.ico"

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

[Dirs]
Name: "{app}\"; Permissions: everyone-modify

[InstallDelete]
Type: Files; Name: "{app}\ka-lite\kalite\updates\utils.*"

[UninstallDelete]
Type: filesandordirs; Name: "{app}\ka-lite*"
Type: files; Name: "{userstartup}\KA Lite.lnk"
Type: files; Name: "{app}\CONFIG.dat"

[Code]
var
  installFlag : boolean;
  startupFlag : string;
  ServerInformationPage : TInputQueryWizardPage;
  StartupPage : TInputOptionWizardPage;
  isUpgrade : boolean;
  stopServerCode: integer;
  removeOldGuiTool: integer;
  uninstallError: integer;
  saveDatabaseTemp : integer;
  cleanOldKaliteFolder : integer;
  restoreDatabaseTemp : integer;
  forceCancel : boolean;
  prevVerStr : string;
  prevAppBackupDir : string;
  runGitmigrate : boolean;

procedure InitializeWizard;
begin
    isUpgrade := False;
    forceCancel := False;
    runGitmigrate := False;

    if WizardForm.PrevAppDir <> nil then
    begin
        ShellExec('open', 'taskkill.exe', '/F /T /im "KA Lite.exe"', '', SW_HIDE, ewWaitUntilTerminated, stopServerCode);
        ShellExec('open', 'tskill.exe', '"KA Lite"', '', SW_HIDE, ewWaitUntilTerminated, stopServerCode);
        Exec(ExpandConstant('{cmd}'),'/C ka-lite\bin\windows\kalite.bat stop', WizardForm.PrevAppDir, SW_HIDE, ewWaitUntilTerminated, stopServerCode);
        Exec(ExpandConstant('{cmd}'),'/C del winshortcut.vbs', WizardForm.PrevAppDir, SW_HIDE, ewWaitUntilTerminated, removeOldGuiTool);
    end;

    // Server data
    ServerInformationPage := CreateInputQueryPage(wpSelectDir,
    'Server Information', 'General data',
    'Please specify the server name and a description, then click Next. (you can leave blank both fields if you want to use the default server name or if you do not want to insert a description)');
    ServerInformationPage.Add('Server name:', False);
    ServerInformationPage.Add('Server description:', False);

    // Run at windows startup.
    StartupPage := CreateInputOptionPage(ServerInformationPage.ID,
    'Server Configuration', 'Startup configuration',
    'The server can run automatically. You may choose one of the following options:', True, False);
    StartupPage.Add('Run the server at windows startup');
    StartupPage.Add('Run the server when this user logs in');
    StartupPage.Add('Do not run the server at startup.');
    StartupPage.SelectedValueIndex := 2;
end;

procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin
  if forceCancel = True then
  begin
    Confirm := False;
  end;
end;

function ShouldSkipPage(PageID: Integer): Boolean;
begin
    result := False;
    if isUpgrade = True then
    begin
        if PageID = ServerInformationPage.ID then
        begin
            result := True;
        end;
        if PageID = wpSelectDir then
        begin
            result := True;
        end;
    end;
end;

procedure RemoveOldInstallation(targetPath : String);
begin
    WizardForm.Hide;
    if Not Exec(ExpandConstant('{cmd}'),'/C ( dir /b "unins***.exe" | findstr /r "unins[0-9][0-9][0-9].exe" ) > tempu & ( for /f "delims=" %A in ( tempu ) do call %A /SILENT /SUPPRESSMSGBOXES ) & del tempu', targetPath, SW_HIDE, ewWaitUntilTerminated, uninstallError) then
    begin
        Exec(ExpandConstant('{cmd}'),'/C mkdir '+ExpandConstant('{tmp}')+'\ka-lite\kalite\database & xcopy /y /s ka-lite\kalite\database\data.sqlite '+ExpandConstant('{tmp}')+'\ka-lite\kalite\database', targetPath, SW_HIDE, ewWaitUntilTerminated, saveDatabaseTemp);
        Exec(ExpandConstant('{cmd}'),'/C cd .. & del /q "'+targetPath+'\*" & for /d %x in ( "'+targetPath+'\*" ) do @rd /s /q "%x"', targetPath, SW_HIDE, ewWaitUntilTerminated, cleanOldKaliteFolder);
        Exec(ExpandConstant('{cmd}'),'/C mkdir ka-lite\kalite\database & xcopy /y /s '+ExpandConstant('{tmp}')+'\ka-lite\kalite\database\data.sqlite ka-lite\kalite\database', targetPath, SW_HIDE, ewWaitUntilTerminated, restoreDatabaseTemp);
    end;
    WizardForm.Show;
end;

{ Get the previous version number by checking the uninstall key registry values. }
{ IS writes quite a bit of information to the registry by default: https://github.com/jrsoftware/issrc/blob/5203240a7de9b83c5432bee0b5b09d467869a02b/Projects/Install.pas#L434 }
procedure GetPreviousVersion;
var
    subkey : String;
begin
    subkey := 'Software\Microsoft\Windows\CurrentVersion\Uninstall\KA Lite-Foundation for Learning Equality_is1';
    prevVerStr := ''
    { 32-bit programs have a virtualized registry on 64-bit windows. So check all possible root keys. }
    if Not RegQueryStringValue(HKLM, subkey, 'DisplayVersion', prevVerStr) then
    begin
        if Not RegQueryStringValue(HKCU, subkey, 'DisplayVersion', prevVerStr) then
        begin
            if IsWin64 then
            begin
                if Not RegQueryStringValue(HKLM64, subkey, 'DisplayVersion', prevVerStr) then
                begin
                    if Not RegQueryStringValue(HKCU64, subkey, 'DisplayVersion', prevVerStr) then
                    begin
                        { Couldn't determine the previous version, so prevVerStr is '' }
                    end;
                end;
            end;
        end;
    end;
end;

procedure ConfirmUpgradeDialog;
begin
    if MsgBox('We have detected an existing KA Lite installation; would you like to upgrade?', mbInformation,  MB_YESNO or MB_DEFBUTTON1) = IDYES then
    begin
        isUpgrade := True;
    end
    else if MsgBox('Installing fresh will delete all of your existing data; is this what you really want to do?', mbInformation,  MB_YESNO or MB_DEFBUTTON2) = IDYES then
    begin
        isUpgrade := False;
    end
    else
    begin
        isUpgrade := True;
    end;
end;

procedure Backup013Files;
var
    prevDBDir, prevContentDir: String;
    resCode: integer;
begin
    { Copy the old database and content folders, preserving the dir structure, then after installing then new files... }
    { ...run gitmigrate management command and delete the old stuff. }
    prevAppBackupDir := ExpandConstant('{tmp}') + '\prev-ka-lite';  // Expand this when we use it, instead of earlier.
    prevDBDir := WizardForm.PrevAppDir + '\ka-lite\kalite\database';
    prevContentDir := WizardForm.PrevAppDir + '\ka-lite\content';

    if Not ForceDirectories(prevAppBackupDir + '\kalite\') then
    begin
        MsgBox('Fatal error' #13#13 'Failed to create backup directories at: ' + prevAppBackupDir, mbError, MB_OK);
        forceCancel := True;
        WizardForm.Close;
    end;

    MsgBox('Setup will now copy your prior user data for migration. If you have a lot of data, this may take some time!', mbInformation, MB_OK);

    Exec(ExpandConstant('{cmd}'), '/S /C "xcopy "' + prevDBDir + '" "' + prevAppBackupDir + '\kalite\database\" /E "', '', SW_HIDE, ewWaitUntilTerminated, resCode);
    if resCode <> 0 then
    begin
        MsgBox('Fatal error' #13#13 'Failed to backup database directory.', mbError, MB_OK);
        forceCancel := True;
        WizardForm.Close;
    end;
    Exec(ExpandConstant('{cmd}'), '/S /C "xcopy "' + prevContentDir + '" "' + prevAppBackupDir + '\content\" /E"', '', SW_HIDE, ewWaitUntilTerminated, resCode);
    if resCode <> 0 then
    begin
        MsgBox('Fatal error' #13#13 'Failed to backup content directory.', mbError, MB_OK);
        forceCancel := True;
        WizardForm.Close;
    end;

    runGitmigrate := True;
end;

procedure HandleUpgrade(targetPath : String);
begin
    GetPreviousVersion;
    if FileExists(targetPath + '\ka-lite\kalite\database\data.sqlite') then
    begin
        ConfirmUpgradeDialog;
        if Not isUpgrade then
        begin
            if Not DeleteFile(targetPath + '\ka-lite\kalite\database\data.sqlite') then
            begin
                MsgBox('Error' #13#13 'Failed to delete the old database as requested; aborting the install.', mbError, MB_OK);
                forceCancel := True;
                WizardForm.Close;
            end;
        end
        else
        begin
            { This is where version-specific migration stuff should happen. }
            if CompareStr(prevVerStr, '0.13.99') < 0 then
            begin
                if CompareStr('{#TargetVersion}', '0.14.0') >= 0 then
                begin
                    Backup013Files;
                end;
            end;
        end;
    { forceCancel will be true if something went awry in Backup013Files... abort instead of trampling the user's data. }
    if Not forceCancel then
        RemoveOldInstallation(targetPath);
    end;
end;

function NextButtonClick(CurPageID: Integer): Boolean;
begin
    result := True;

    if CurPageID = wpLicense then
    begin
        if WizardForm.PrevAppDir <> nil then
            HandleUpgrade(WizardForm.PrevAppDir);
    end;

    if CurPageID = wpSelectDir then
    begin
        { Unclear what the logic here is. This is only executed if HandleUpgrade was not previously run. }
        if Not isUpgrade then
            HandleUpgrade(ExpandConstant('{app}'));
    end;
end;

procedure HandlePythonSetup;
var
    installPythonErrorCode : Integer;
begin
    if(MsgBox('Python 2.7.9+ is required to install KA Lite on Windows; do you wish to first install Python 2.7.10, before continuing with the installation of KA Lite?', mbConfirmation, MB_YESNO) = idYes) then
    begin
        ExtractTemporaryFile('python-2.7.10.msi');
        ShellExec('open', ExpandConstant('{tmp}')+'\python-2.7.10.msi', '', '', SW_SHOWNORMAL, ewWaitUntilTerminated, installPythonErrorCode);
    end
    else begin
        MsgBox('Error' #13#13 'You must have Python 2.7.9+ installed to proceed! Installation will now exit.', mbError, MB_OK);
        forceCancel := True;
        WizardForm.Close;
    end;
end;

{ Used in GetPipPath below }
const
    DEFAULT_PATH = '\Python27\Scripts\pip.exe';

{ Returns the path of pip.exe on the system. }
{ Tries several different locations before prompting user. }
function GetPipPath: string;
var
    path : string;
    i : integer;
begin
    for i := Ord('C') to Ord('H') do
    begin
        path := Chr(i) + ':' + DEFAULT_PATH;
        if FileExists(path) then
        begin
            Result := path;
            exit;
        end;
    end;
    MsgBox('Could not find pip.exe. Please select the location of pip.exe to continue installation.', mbInformation, MB_OK);
    if GetOpenFileName('Please select pip.exe', path, '', 'All files (*.*)|*.*', 'exe') then
    begin
        Result := path;
    end
    else begin
        MsgBox('Fatal error'#13#13'Please install pip and try again.', mbError, MB_OK);
        forceCancel := True;
        Result := '';
    end;
end;

procedure HandlePipSetup;
var
    PipCommand: string;
    PipPath: string;
    ErrorCode: integer;

begin
    PipPath := GetPipPath;
    if PipPath = '' then
        exit;
    PipCommand := 'install "' + ExpandConstant('{app}\ka-lite\dist\ka-lite-static-')  + '{#TargetVersion}' + '.zip"';

    MsgBox('Setup will now unpack dependencies for your installation.', mbInformation, MB_OK);
    if not ShellExec('open', PipPath, PipCommand, '', SW_HIDE, ewWaitUntilTerminated, ErrorCode) then
    begin
      MsgBox('Critical error.' #13#13 'Dependencies have failed to install. Error Number: ' + IntToStr(ErrorCode), mbInformation, MB_OK);
      forceCancel := True;
      WizardForm.Close;
    end;
end;

function InitializeSetup(): Boolean;
var
  PythonVersionCodeCheck: integer;
  killErrorCode: integer;
begin
    installFlag:=true;
    Result := true;
    startupFlag:='';

    ShellExec('open', 'taskkill.exe', '/F /T /im "KA Lite.exe"', '', SW_HIDE, ewWaitUntilTerminated, killErrorCode)
    ShellExec('open', 'tskill.exe', ' "KA Lite"', '', SW_HIDE, ewWaitUntilTerminated, killErrorCode);

    RegDeleteValue(HKCU, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run', ExpandConstant('{#MyAppName}'));

    if ShellExec('open', 'python.exe','-c "import sys; (sys.version_info >= (2, 7, 9,) and sys.version_info < (3,) and sys.exit(0)) or sys.exit(1)"', '', SW_HIDE, ewWaitUntilTerminated, PythonVersionCodeCheck) then
    begin
        if PythonVersionCodeCheck = 1 then
        begin
            HandlePythonSetup();
        end;
    end
    else
    begin
        HandlePythonSetup();
    end;
end;

function InitializeUninstall(): Boolean;
var
ErrorCode: Integer;
begin
  ShellExec('open', 'taskkill.exe', '/F /T /im "KA Lite.exe"', '', SW_HIDE, ewWaitUntilTerminated, ErrorCode);
  ShellExec('open', 'tskill.exe', '"KA Lite"', '', SW_HIDE, ewWaitUntilTerminated, ErrorCode);
  ShellExec('open', ExpandConstant('{app}') + '\ka-lite\bin\windows\kalite.bat stop', '', '', SW_HIDE, ewWaitUntilTerminated, ErrorCode);
  result := True;
end;

{ Runs the gitmigrate management command introduced in 0.14 on the backup of a 0.13 installation }
procedure DoGitMigrate;
var
    retCodeContent, retCodeDB, retCode : integer;
begin
    MsgBox('Migrating old data to current user''s %USERPROFILE%\.kalite\ directory.', mbInformation, MB_OK);
    Exec(ExpandConstant('{cmd}'), '/S /C "mkdir "%USERPROFILE%\.kalite""', '', SW_SHOW, ewWaitUntilTerminated, retCode);
    Exec(ExpandConstant('{cmd}'), '/S /C "xcopy "' + prevAppBackupDir + '\content" "%USERPROFILE%\.kalite\content\" /E /Y"', '', SW_SHOW, ewWaitUntilTerminated, retCodeContent);
    Exec(ExpandConstant('{cmd}'), '/S /C "xcopy "' + prevAppBackupDir + '\kalite\database" "%USERPROFILE%\.kalite\database\" /E /Y"', '', SW_SHOW, ewWaitUntilTerminated, retCodeDB);
    if (retCodeContent <> 0) or (retCodeDB <> 0) then
    begin
        Exec(ExpandConstant('{cmd}'), '/S /C "xcopy "' + prevAppBackupDir + '" "' + ExpandConstant('{app}') + '\kalite-backup\" /E /Y"', '', SW_SHOW, ewWaitUntilTerminated, retCode);
        MsgBox('Unable to migrate your data. Your data is still backed up at the directory: ' + ExpandConstant('{app}') + '\kalite-backup', mbError, MB_OK);
    end;
end;

{ Completes the setup with bundled empty database file. }
procedure DoSetup;
var
    setupCommand: string;
    retCode: integer;
begin
    { Copy the bundled empty db to the proper location. }
    { Used to have more responsibility, but we delegated those to the app itself! }
    Exec(ExpandConstant('{cmd}'), '/S /C "xcopy "' + ExpandConstant('{app}') + '\ka-lite\kalite\database" "%USERPROFILE%\.kalite\database\" /E /Y"', '', SW_HIDE, ewWaitUntilTerminated, retCode);
end;

procedure CurStepChanged(CurStep: TSetupStep);
var
  StartupCode: integer;
  moveKaliteFolderTemp: integer;
  moveContentFolderTemp: integer;
  cleanKaliteFolder: integer;
  restoreKaliteFolder: integer;
  restoreContentFolder: integer;
  informationBoxFlagged: boolean;

begin
    if CurStep = ssInstall then
    begin
        informationBoxFlagged :=False;

        ShellExec('open', 'taskkill.exe', '/F /T /im "KA Lite.exe"', '', SW_HIDE, ewWaitUntilTerminated, stopServerCode);
        ShellExec('open', 'tskill.exe', '"KA Lite"', '', SW_HIDE, ewWaitUntilTerminated, stopServerCode);
        Exec(ExpandConstant('{cmd}'),'/C ka-lite\bin\windows\kalite.bat stop', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, stopServerCode);
        Exec(ExpandConstant('{cmd}'),'/C del winshortcut.vbs', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, removeOldGuiTool);

        if DirExists(ExpandConstant('{app}') + '\kalite') then
        begin
            MsgBox('KA Lite old data structure' #13#13 'Setup detected that you have the old file structure. Setup will now move data to update the structure. Please be patient; this may take some time.', mbInformation, MB_OK);
            informationBoxFlagged :=True;
            Exec(ExpandConstant('{cmd}'),'/C mkdir '+ExpandConstant('{tmp}')+'\ka-lite\kalite & xcopy /y /s kalite\* '+ExpandConstant('{tmp}')+'\ka-lite\kalite', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, moveKaliteFolderTemp);
        end;

        if DirExists(ExpandConstant('{app}') + '\content') then
        begin
            if Not informationBoxFlagged then
            begin
                MsgBox('KA Lite old data structure' #13#13 'Setup detected that you have the old file structure. Setup will now move data to update the structure. Please be patient; this may take some time.', mbInformation, MB_OK);
                informationBoxFlagged :=True;
            end;
            Exec(ExpandConstant('{cmd}'),'/C mkdir '+ExpandConstant('{tmp}')+'\ka-lite\content & xcopy /y /s content\* '+ExpandConstant('{tmp}')+'\ka-lite\content', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, moveContentFolderTemp);
        end;

        if informationBoxFlagged then
        begin
            Exec(ExpandConstant('{cmd}'),'/C cd .. & del /q "'+ExpandConstant('{app}')+'\*" & for /d %x in ( "'+ExpandConstant('{app}')+'\*" ) do @rd /s /q "%x"', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, cleanKaliteFolder);

            if DirExists(ExpandConstant('{tmp}')+'\ka-lite\kalite') then
            begin
                Exec(ExpandConstant('{cmd}'),'/C mkdir ka-lite\kalite & xcopy /y /s '+ExpandConstant('{tmp}')+'\ka-lite\kalite\* ka-lite\kalite', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, restoreKaliteFolder);
            end;

            if DirExists(ExpandConstant('{tmp}')+'\ka-lite\content') then
            begin
                Exec(ExpandConstant('{cmd}'),'/C mkdir ka-lite\content & xcopy /y /s '+ExpandConstant('{tmp}')+'\ka-lite\content\* ka-lite\content', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, restoreContentFolder);
            end;
        end;

    end;

    if CurStep = ssPostInstall then
    begin
        if installFlag then
        begin
            HandlePipSetup();

            { Add KALITE_ROOT_DATA_PATH to environment variables. A workaround for setting kalite.ROOT_DATA_PATH }
            { In the future, the windows installer should use setuptools to avoid OS-dependent workarounds like this. }
            RegWriteStringValue(
                HKLM,
                'System\CurrentControlSet\Control\Session Manager\Environment',
                'KALITE_ROOT_DATA_PATH',
                ExpandConstant('{app}\ka-lite\')
            );

            { Migrate old database if applicable, otherwise create a new one }
            if runGitmigrate and Not forceCancel then
            begin
                DoGitMigrate;
            end
            else if Not forceCancel then
            begin
                DoSetup;
            end;

            if StartupPage.SelectedValueIndex = 0 then
            begin
                if ShellExec('open','guitools.vbs','4', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, StartupCode) then
                begin
                    if Not SaveStringToFile(ExpandConstant('{app}')+'\CONFIG.dat', 'RUN_AT_STARTUP:TRUE;' + #13#10, False) then
                    begin
                        MsgBox('Configuration file error.' #13#13 'Setup has failed to add the entry in the configuration file to run KA Lite at Windows startup. The installation may proceed and you can set this option later while using KA Lite.', mbError, MB_OK);
                    end;
                end
                else begin
                    MsgBox('GUI tools error.' #13#13 'Setup has failed to register a task to run KA Lite at Windows startup. The installation may proceed and you can set this option later while using KA Lite.', mbError, MB_OK);
                end;
            end
            else if StartupPage.SelectedValueIndex = 1 then
            begin
                if ShellExec('open', 'guitools.vbs', '0', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, StartupCode) then
                begin
                    if Not SaveStringToFile(ExpandConstant('{app}')+'\CONFIG.dat', 'RUN_AT_USER_LOGIN:TRUE;' + #13#10, False) then
                    begin
                        MsgBox('Configuration file error.' #13#13 'Setup has failed to add the entry in the configuration file to run KA Lite on user login. The installation may proceed and you can set this option later while using KA Lite.', mbError, MB_OK);
                    end;
                end
                else begin
                    MsgBox('GUI tools error.' #13#13 'Setup has failed to add the shortcut at the startup folder to run KA Lite on user login. The installation may proceed and you can set this option later while using KA Lite.', mbError, MB_OK);
                end;
            end;
        end;
    end;
end;

{ Called just prior to uninstall finishing. }
{ Clean up things we did during uninstall: }
{ * Remove environment variable KALITE_ROOT_DATA_PATH }
procedure DeinitializeUninstall();
begin
    if not RegDeleteValue(
        HKLM,
        'System\CurrentControlSet\Control\Session Manager\Environment',
        'KALITE_ROOT_DATA_PATH'
    ) then
    begin
        MsgBox('Unable to unset environment variable KALITE_ROOT_DATA_PATH.', mbError, MB_OK);
    end;
end;

#define MyAppName "KA Lite"
#define MyAppPublisher "Foundation for Learning Equality"
#define MyAppURL "http://learningequality.org/"
#define MyAppExeName "KA Lite.exe"

#define getKALiteVersion() \
    Local[1] = Exec(SourcePath+"\getversion.bat") == 0 ? StringChange(FileRead(FileOpen(SourcePath+"\version.temp")), " ", "") : "null"

#define TargetVersion = getKALiteVersion();

#expr DeleteFile(SourcePath+"\version.temp")

[Setup]
AppId={#MyAppName}-{#MyAppPublisher}
AppName={#MyAppName}
AppVersion={#TargetVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName={#MyAppName}
LicenseFile=..\ka-lite\LICENSE
OutputDir=..\
OutputBaseFilename=KALiteSetup-{#TargetVersion}
SetupIconFile=logo48.ico
Compression=lzma
SolidCompression=yes
PrivilegesRequired=admin
UsePreviousAppDir=yes
ChangesEnvironment=yes
AlwaysRestart=yes

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

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

[Files]
Source: "..\ka-lite\*"; DestDir: "{app}\ka-lite"; Excludes: ".KALITE_SOURCE_DIR,content\assessment,content\assessment\*,content\assessmentitems.sqlite"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\ka-lite\content\*"; DestDir: "{app}\ka-lite\content"; Excludes: "assessment,assessment\*,assessmentitems.sqlite"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\ka-lite\content\assessment\*"; DestDir: "{app}\ka-lite\assessment"; Excludes: "assessmentitems.sqlite"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\ka-lite\content\assessmentitems.sqlite"; DestDir: "{app}\ka-lite\assessment\khan"; Flags: ignoreversion
Source: "..\gui-packed\KA Lite.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\gui-packed\guitools.vbs"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\gui-packed\images\logo48.ico"; DestDir: "{app}\images"; Flags: ignoreversion
Source: "..\python-setup\*"; DestDir: "{app}\python-setup"; Flags: ignoreversion

[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\images\logo48.ico"
Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon ; IconFilename: "{app}\images\logo48.ico"

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

[Dirs]
Name: "{app}\"; Permissions: everyone-modify

[InstallDelete]
Type: Files; Name: "{app}\ka-lite\kalite\updates\utils.*"

[UninstallDelete]
Type: filesandordirs; Name: "{app}\ka-lite*"
Type: files; Name: "{userstartup}\KA Lite.lnk"
Type: files; Name: "{app}\CONFIG.dat"

[Code]
var
  installFlag : boolean;
  startupFlag : string;
  ServerInformationPage : TInputQueryWizardPage;
  StartupPage : TInputOptionWizardPage;
  isUpgrade : boolean;
  stopServerCode: integer;
  removeOldGuiTool: integer;
  uninstallError: integer;
  saveDatabaseTemp : integer;
  cleanOldKaliteFolder : integer;
  restoreDatabaseTemp : integer;
  forceCancel : boolean;
  prevVerStr : string;
  prevAppBackupDir : string;
  runGitmigrate : boolean;

procedure InitializeWizard;
begin
    isUpgrade := False;
    forceCancel := False;
    runGitmigrate := False;

    if WizardForm.PrevAppDir <> nil then
    begin
        ShellExec('open', 'taskkill.exe', '/F /T /im "KA Lite.exe"', '', SW_HIDE, ewWaitUntilTerminated, stopServerCode);
        ShellExec('open', 'tskill.exe', '"KA Lite"', '', SW_HIDE, ewWaitUntilTerminated, stopServerCode);
        Exec(ExpandConstant('{cmd}'),'/C ka-lite\bin\windows\kalite.bat stop', WizardForm.PrevAppDir, SW_HIDE, ewWaitUntilTerminated, stopServerCode);
        Exec(ExpandConstant('{cmd}'),'/C del winshortcut.vbs', WizardForm.PrevAppDir, SW_HIDE, ewWaitUntilTerminated, removeOldGuiTool);
    end;

    // Server data
    ServerInformationPage := CreateInputQueryPage(wpSelectDir,
    'Server Information', 'General data',
    'Please specify the server name and a description, then click Next. (you can leave blank both fields if you want to use the default server name or if you do not want to insert a description)');
    ServerInformationPage.Add('Server name:', False);
    ServerInformationPage.Add('Server description:', False);

    // Run at windows startup.
    StartupPage := CreateInputOptionPage(ServerInformationPage.ID,
    'Server Configuration', 'Startup configuration',
    'The server can run automatically. You may choose one of the following options:', True, False);
    StartupPage.Add('Run the server at windows startup');
    StartupPage.Add('Run the server when this user logs in');
    StartupPage.Add('Do not run the server at startup.');
    StartupPage.SelectedValueIndex := 2;
end;

procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin
  if forceCancel = True then
  begin
    Confirm := False;
  end;
end;

function ShouldSkipPage(PageID: Integer): Boolean;
begin
    result := False;
    if isUpgrade = True then
    begin
        if PageID = ServerInformationPage.ID then
        begin
            result := True;
        end;
        if PageID = wpSelectDir then
        begin
            result := True;
        end;
    end;
end;

procedure RemoveOldInstallation(targetPath : String);
begin
    WizardForm.Hide;
    if Not Exec(ExpandConstant('{cmd}'),'/C ( dir /b "unins***.exe" | findstr /r "unins[0-9][0-9][0-9].exe" ) > tempu & ( for /f "delims=" %A in ( tempu ) do call %A /SILENT /SUPPRESSMSGBOXES ) & del tempu', targetPath, SW_HIDE, ewWaitUntilTerminated, uninstallError) then
    begin
        Exec(ExpandConstant('{cmd}'),'/C mkdir '+ExpandConstant('{tmp}')+'\ka-lite\kalite\database & xcopy /y /s ka-lite\kalite\database\data.sqlite '+ExpandConstant('{tmp}')+'\ka-lite\kalite\database', targetPath, SW_HIDE, ewWaitUntilTerminated, saveDatabaseTemp);
        Exec(ExpandConstant('{cmd}'),'/C cd .. & del /q "'+targetPath+'\*" & for /d %x in ( "'+targetPath+'\*" ) do @rd /s /q "%x"', targetPath, SW_HIDE, ewWaitUntilTerminated, cleanOldKaliteFolder);
        Exec(ExpandConstant('{cmd}'),'/C mkdir ka-lite\kalite\database & xcopy /y /s '+ExpandConstant('{tmp}')+'\ka-lite\kalite\database\data.sqlite ka-lite\kalite\database', targetPath, SW_HIDE, ewWaitUntilTerminated, restoreDatabaseTemp);
    end;
    WizardForm.Show;
end;

{ Get the previous version number by checking the uninstall key registry values. }
{ IS writes quite a bit of information to the registry by default: https://github.com/jrsoftware/issrc/blob/5203240a7de9b83c5432bee0b5b09d467869a02b/Projects/Install.pas#L434 }
procedure GetPreviousVersion;
var
    subkey : String;
begin
    subkey := 'Software\Microsoft\Windows\CurrentVersion\Uninstall\KA Lite-Foundation for Learning Equality_is1';
    prevVerStr := ''
    { 32-bit programs have a virtualized registry on 64-bit windows. So check all possible root keys. }
    if Not RegQueryStringValue(HKLM, subkey, 'DisplayVersion', prevVerStr) then
    begin
        if Not RegQueryStringValue(HKCU, subkey, 'DisplayVersion', prevVerStr) then
        begin
            if IsWin64 then
            begin
                if Not RegQueryStringValue(HKLM64, subkey, 'DisplayVersion', prevVerStr) then
                begin
                    if Not RegQueryStringValue(HKCU64, subkey, 'DisplayVersion', prevVerStr) then
                    begin
                        { Couldn't determine the previous version, so prevVerStr is '' }
                    end;
                end;
            end;
        end;
    end;
end;

procedure ConfirmUpgradeDialog;
begin
    if MsgBox('We have detected an existing KA Lite installation; would you like to upgrade?', mbInformation,  MB_YESNO or MB_DEFBUTTON1) = IDYES then
    begin
        isUpgrade := True;
    end
    else if MsgBox('Installing fresh will delete all of your existing data; is this what you really want to do?', mbInformation,  MB_YESNO or MB_DEFBUTTON2) = IDYES then
    begin
        isUpgrade := False;
    end
    else
    begin
        isUpgrade := True;
    end;
end;

procedure Backup013Files;
var
    prevDBDir, prevContentDir: String;
    resCode: integer;
begin
    { Copy the old database and content folders, preserving the dir structure, then after installing then new files... }
    { ...run gitmigrate management command and delete the old stuff. }
    prevAppBackupDir := ExpandConstant('{tmp}') + '\prev-ka-lite';  // Expand this when we use it, instead of earlier.
    prevDBDir := WizardForm.PrevAppDir + '\ka-lite\kalite\database';
    prevContentDir := WizardForm.PrevAppDir + '\ka-lite\content';

    if Not ForceDirectories(prevAppBackupDir + '\kalite\') then
    begin
        MsgBox('Fatal error' #13#13 'Failed to create backup directories at: ' + prevAppBackupDir, mbError, MB_OK);
        forceCancel := True;
        WizardForm.Close;
    end;

    MsgBox('Setup will now copy your prior user data for migration. If you have a lot of data, this may take some time!', mbInformation, MB_OK);

    Exec(ExpandConstant('{cmd}'), '/S /C "xcopy "' + prevDBDir + '" "' + prevAppBackupDir + '\kalite\database\" /E "', '', SW_HIDE, ewWaitUntilTerminated, resCode);
    if resCode <> 0 then
    begin
        MsgBox('Fatal error' #13#13 'Failed to backup database directory.', mbError, MB_OK);
        forceCancel := True;
        WizardForm.Close;
    end;
    Exec(ExpandConstant('{cmd}'), '/S /C "xcopy "' + prevContentDir + '" "' + prevAppBackupDir + '\content\" /E"', '', SW_HIDE, ewWaitUntilTerminated, resCode);
    if resCode <> 0 then
    begin
        MsgBox('Fatal error' #13#13 'Failed to backup content directory.', mbError, MB_OK);
        forceCancel := True;
        WizardForm.Close;
    end;

    runGitmigrate := True;
end;

procedure HandleUpgrade(targetPath : String);
begin
    GetPreviousVersion;
    if FileExists(targetPath + '\ka-lite\kalite\database\data.sqlite') then
    begin
        ConfirmUpgradeDialog;
        if Not isUpgrade then
        begin
            if Not DeleteFile(targetPath + '\ka-lite\kalite\database\data.sqlite') then
            begin
                MsgBox('Error' #13#13 'Failed to delete the old database as requested; aborting the install.', mbError, MB_OK);
                forceCancel := True;
                WizardForm.Close;
            end;
        end
        else
        begin
            { This is where version-specific migration stuff should happen. }
            if CompareStr(prevVerStr, '0.13.99') < 0 then
            begin
                if CompareStr('{#TargetVersion}', '0.14.0') >= 0 then
                begin
                    Backup013Files;
                end;
            end;
        end;
    { forceCancel will be true if something went awry in Backup013Files... abort instead of trampling the user's data. }
    if Not forceCancel then
        RemoveOldInstallation(targetPath);
    end;
end;

function NextButtonClick(CurPageID: Integer): Boolean;
begin
    result := True;

    if CurPageID = wpLicense then
    begin
        if WizardForm.PrevAppDir <> nil then
            HandleUpgrade(WizardForm.PrevAppDir);
    end;

    if CurPageID = wpSelectDir then
    begin
        { Unclear what the logic here is. This is only executed if HandleUpgrade was not previously run. }
        if Not isUpgrade then
            HandleUpgrade(ExpandConstant('{app}'));
    end;
end;

procedure HandlePythonSetup;
var
    installPythonErrorCode : Integer;
begin
    if(MsgBox('Python 2.7.9+ is required to install KA Lite on Windows; do you wish to first install Python 2.7.10, before continuing with the installation of KA Lite?', mbConfirmation, MB_YESNO) = idYes) then
    begin
        ExtractTemporaryFile('python-2.7.10.msi');
        ShellExec('open', ExpandConstant('{tmp}')+'\python-2.7.10.msi', '', '', SW_SHOWNORMAL, ewWaitUntilTerminated, installPythonErrorCode);
    end
    else begin
        MsgBox('Error' #13#13 'You must have Python 2.7.9+ installed to proceed! Installation will now exit.', mbError, MB_OK);
        forceCancel := True;
        WizardForm.Close;
    end;
end;

{ Used in GetPipPath below }
const
    DEFAULT_PATH = '\Python27\Scripts\pip.exe';

{ Returns the path of pip.exe on the system. }
{ Tries several different locations before prompting user. }
function GetPipPath: string;
var
    path : string;
    i : integer;
begin
    for i := Ord('C') to Ord('H') do
    begin
        path := Chr(i) + ':' + DEFAULT_PATH;
        if FileExists(path) then
        begin
            Result := path;
            exit;
        end;
    end;
    MsgBox('Could not find pip.exe. Please select the location of pip.exe to continue installation.', mbInformation, MB_OK);
    if GetOpenFileName('Please select pip.exe', path, '', 'All files (*.*)|*.*', 'exe') then
    begin
        Result := path;
    end
    else begin
        MsgBox('Fatal error'#13#13'Please install pip and try again.', mbError, MB_OK);
        forceCancel := True;
        Result := '';
    end;
end;

procedure HandlePipSetup;
var
    PipCommand: string;
    PipPath: string;
    ErrorCode: integer;

begin
    PipPath := GetPipPath;
    if PipPath = '' then
        exit;
    PipCommand := 'install "' + ExpandConstant('{app}\ka-lite\dist\ka-lite-static-')  + '{#TargetVersion}' + '.zip"';

    MsgBox('Setup will now unpack dependencies for your installation.', mbInformation, MB_OK);
    if not ShellExec('open', PipPath, PipCommand, '', SW_HIDE, ewWaitUntilTerminated, ErrorCode) then
    begin
      MsgBox('Critical error.' #13#13 'Dependencies have failed to install. Error Number: ' + IntToStr(ErrorCode), mbInformation, MB_OK);
      forceCancel := True;
      WizardForm.Close;
    end;
end;

function InitializeSetup(): Boolean;
var
  PythonVersionCodeCheck: integer;
  killErrorCode: integer;
begin
    installFlag:=true;
    Result := true;
    startupFlag:='';

    ShellExec('open', 'taskkill.exe', '/F /T /im "KA Lite.exe"', '', SW_HIDE, ewWaitUntilTerminated, killErrorCode)
    ShellExec('open', 'tskill.exe', ' "KA Lite"', '', SW_HIDE, ewWaitUntilTerminated, killErrorCode);

    RegDeleteValue(HKCU, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run', ExpandConstant('{#MyAppName}'));

    if ShellExec('open', 'python.exe','-c "import sys; (sys.version_info >= (2, 7, 9,) and sys.version_info < (3,) and sys.exit(0)) or sys.exit(1)"', '', SW_HIDE, ewWaitUntilTerminated, PythonVersionCodeCheck) then
    begin
        if PythonVersionCodeCheck = 1 then
        begin
            HandlePythonSetup();
        end;
    end
    else
    begin
        HandlePythonSetup();
    end;
end;

function InitializeUninstall(): Boolean;
var
ErrorCode: Integer;
begin
  ShellExec('open', 'taskkill.exe', '/F /T /im "KA Lite.exe"', '', SW_HIDE, ewWaitUntilTerminated, ErrorCode);
  ShellExec('open', 'tskill.exe', '"KA Lite"', '', SW_HIDE, ewWaitUntilTerminated, ErrorCode);
  ShellExec('open', ExpandConstant('{app}') + '\ka-lite\bin\windows\kalite.bat stop', '', '', SW_HIDE, ewWaitUntilTerminated, ErrorCode);
  result := True;
end;

{ Runs the gitmigrate management command introduced in 0.14 on the backup of a 0.13 installation }
procedure DoGitMigrate;
var
    retCodeContent, retCodeDB, retCode : integer;
begin
    MsgBox('Migrating old data to current user''s %USERPROFILE%\.kalite\ directory.', mbInformation, MB_OK);
    Exec(ExpandConstant('{cmd}'), '/S /C "mkdir "%USERPROFILE%\.kalite""', '', SW_SHOW, ewWaitUntilTerminated, retCode);
    Exec(ExpandConstant('{cmd}'), '/S /C "xcopy "' + prevAppBackupDir + '\content" "%USERPROFILE%\.kalite\content\" /E /Y"', '', SW_SHOW, ewWaitUntilTerminated, retCodeContent);
    Exec(ExpandConstant('{cmd}'), '/S /C "xcopy "' + prevAppBackupDir + '\kalite\database" "%USERPROFILE%\.kalite\database\" /E /Y"', '', SW_SHOW, ewWaitUntilTerminated, retCodeDB);
    if (retCodeContent <> 0) or (retCodeDB <> 0) then
    begin
        Exec(ExpandConstant('{cmd}'), '/S /C "xcopy "' + prevAppBackupDir + '" "' + ExpandConstant('{app}') + '\kalite-backup\" /E /Y"', '', SW_SHOW, ewWaitUntilTerminated, retCode);
        MsgBox('Unable to migrate your data. Your data is still backed up at the directory: ' + ExpandConstant('{app}') + '\kalite-backup', mbError, MB_OK);
    end;
end;

{ Completes the setup with bundled empty database file. }
procedure DoSetup;
var
    setupCommand: string;
    retCode: integer;
begin
    { Copy the bundled empty db to the proper location. }
    Exec(ExpandConstant('{cmd}'), '/S /C "xcopy "' + ExpandConstant('{app}') + '\ka-lite\kalite\database" "%USERPROFILE%\.kalite\database\" /E /Y"', '', SW_HIDE, ewWaitUntilTerminated, retCode);
    MsgBox('Setup will now configure the database. This operation may take a few minutes. Please be patient.', mbInformation, MB_OK);
    setupCommand := 'kalite manage setup --noinput --hostname="'+ServerInformationPage.Values[0]+'" --description="'+ServerInformationPage.Values[1]+'"';
    if Not ShellExec('open', 'python.exe', setupCommand, ExpandConstant('{app}')+'\ka-lite\bin', SW_HIDE, ewWaitUntilTerminated, retCode) then
    begin
        MsgBox('Critical error.' #13#13 'Setup has failed to initialize the database; aborting the install.', mbInformation, MB_OK);
        forceCancel := True;
        WizardForm.Close;
    end;
end;

procedure CurStepChanged(CurStep: TSetupStep);
var
  StartupCode: integer;
  moveKaliteFolderTemp: integer;
  moveContentFolderTemp: integer;
  cleanKaliteFolder: integer;
  restoreKaliteFolder: integer;
  restoreContentFolder: integer;
  informationBoxFlagged: boolean;

begin
    if CurStep = ssInstall then
    begin
        informationBoxFlagged :=False;

        ShellExec('open', 'taskkill.exe', '/F /T /im "KA Lite.exe"', '', SW_HIDE, ewWaitUntilTerminated, stopServerCode);
        ShellExec('open', 'tskill.exe', '"KA Lite"', '', SW_HIDE, ewWaitUntilTerminated, stopServerCode);
        Exec(ExpandConstant('{cmd}'),'/C ka-lite\bin\windows\kalite.bat stop', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, stopServerCode);
        Exec(ExpandConstant('{cmd}'),'/C del winshortcut.vbs', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, removeOldGuiTool);

        if DirExists(ExpandConstant('{app}') + '\kalite') then
        begin
            MsgBox('KA Lite old data structure' #13#13 'Setup detected that you have the old file structure. Setup will now move data to update the structure. Please be patient; this may take some time.', mbInformation, MB_OK);
            informationBoxFlagged :=True;
            Exec(ExpandConstant('{cmd}'),'/C mkdir '+ExpandConstant('{tmp}')+'\ka-lite\kalite & xcopy /y /s kalite\* '+ExpandConstant('{tmp}')+'\ka-lite\kalite', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, moveKaliteFolderTemp);
        end;

        if DirExists(ExpandConstant('{app}') + '\content') then
        begin
            if Not informationBoxFlagged then
            begin
                MsgBox('KA Lite old data structure' #13#13 'Setup detected that you have the old file structure. Setup will now move data to update the structure. Please be patient; this may take some time.', mbInformation, MB_OK);
                informationBoxFlagged :=True;
            end;
            Exec(ExpandConstant('{cmd}'),'/C mkdir '+ExpandConstant('{tmp}')+'\ka-lite\content & xcopy /y /s content\* '+ExpandConstant('{tmp}')+'\ka-lite\content', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, moveContentFolderTemp);
        end;

        if informationBoxFlagged then
        begin
            Exec(ExpandConstant('{cmd}'),'/C cd .. & del /q "'+ExpandConstant('{app}')+'\*" & for /d %x in ( "'+ExpandConstant('{app}')+'\*" ) do @rd /s /q "%x"', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, cleanKaliteFolder);

            if DirExists(ExpandConstant('{tmp}')+'\ka-lite\kalite') then
            begin
                Exec(ExpandConstant('{cmd}'),'/C mkdir ka-lite\kalite & xcopy /y /s '+ExpandConstant('{tmp}')+'\ka-lite\kalite\* ka-lite\kalite', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, restoreKaliteFolder);
            end;

            if DirExists(ExpandConstant('{tmp}')+'\ka-lite\content') then
            begin
                Exec(ExpandConstant('{cmd}'),'/C mkdir ka-lite\content & xcopy /y /s '+ExpandConstant('{tmp}')+'\ka-lite\content\* ka-lite\content', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, restoreContentFolder);
            end;
        end;

    end;

    if CurStep = ssPostInstall then
    begin
        if installFlag then
        begin
            HandlePipSetup();

            { Add KALITE_ROOT_DATA_PATH to environment variables. A workaround for setting kalite.ROOT_DATA_PATH }
            { In the future, the windows installer should use setuptools to avoid OS-dependent workarounds like this. }
            RegWriteStringValue(
                HKLM,
                'System\CurrentControlSet\Control\Session Manager\Environment',
                'KALITE_ROOT_DATA_PATH',
                ExpandConstant('{app}\ka-lite\')
            );

            { Migrate old database if applicable, otherwise create a new one }
            if runGitmigrate and Not forceCancel then
            begin
                DoGitMigrate;
            end
            else if Not forceCancel then
            begin
                DoSetup;
            end;

            if StartupPage.SelectedValueIndex = 0 then
            begin
                if ShellExec('open','guitools.vbs','4', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, StartupCode) then
                begin
                    if Not SaveStringToFile(ExpandConstant('{app}')+'\CONFIG.dat', 'RUN_AT_STARTUP:TRUE;' + #13#10, False) then
                    begin
                        MsgBox('Configuration file error.' #13#13 'Setup has failed to add the entry in the configuration file to run KA Lite at Windows startup. The installation may proceed and you can set this option later while using KA Lite.', mbError, MB_OK);
                    end;
                end
                else begin
                    MsgBox('GUI tools error.' #13#13 'Setup has failed to register a task to run KA Lite at Windows startup. The installation may proceed and you can set this option later while using KA Lite.', mbError, MB_OK);
                end;
            end
            else if StartupPage.SelectedValueIndex = 1 then
            begin
                if ShellExec('open', 'guitools.vbs', '0', ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, StartupCode) then
                begin
                    if Not SaveStringToFile(ExpandConstant('{app}')+'\CONFIG.dat', 'RUN_AT_USER_LOGIN:TRUE;' + #13#10, False) then
                    begin
                        MsgBox('Configuration file error.' #13#13 'Setup has failed to add the entry in the configuration file to run KA Lite on user login. The installation may proceed and you can set this option later while using KA Lite.', mbError, MB_OK);
                    end;
                end
                else begin
                    MsgBox('GUI tools error.' #13#13 'Setup has failed to add the shortcut at the startup folder to run KA Lite on user login. The installation may proceed and you can set this option later while using KA Lite.', mbError, MB_OK);
                end;
            end;
        end;
    end;
end;

{ Called just prior to uninstall finishing. }
{ Clean up things we did during uninstall: }
{ * Remove environment variable KALITE_ROOT_DATA_PATH }
procedure DeinitializeUninstall();
begin
    if not RegDeleteValue(
        HKLM,
        'System\CurrentControlSet\Control\Session Manager\Environment',
        'KALITE_ROOT_DATA_PATH'
    ) then
    begin
        MsgBox('Unable to unset environment variable KALITE_ROOT_DATA_PATH.', mbError, MB_OK);
    end;
end;


TRAFODION-1893 Remove vcredist from win-odbc build

; @@@ START COPYRIGHT @@@
; Licensed to the Apache Software Foundation (ASF) under one
; or more contributor license agreements.  See the NOTICE file
; distributed with this work for additional information
; regarding copyright ownership.  The ASF licenses this file
; to you under the Apache License, Version 2.0 (the
; "License"); you may not use this file except in compliance
; with the License.  You may obtain a copy of the License at
;   http://www.apache.org/licenses/LICENSE-2.0
; Unless required by applicable law or agreed to in writing,
; software distributed under the License is distributed on an
; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
; KIND, either express or implied.  See the License for the
; specific language governing permissions and limitations
; under the License.
; @@@ END COPYRIGHT @@@
;
; Script generated by the Inno Script Studio Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "Trafodion ODBC64 1.3"
#define MyAppVersion "1.3.0"
#define MyAppPublisher "Apache Trafodion"
#define MyAppURL ""
#define MyDriverName "TRAF ODBC 1.0"
#define BUILDDIR  GetEnv('BUILDDIR')

[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={{5E6042F8-7C2F-490A-899F-9552D5DE8DE2}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultGroupName={#MyAppName}
DefaultDirName={pf}\Trafodion\TRAF ODBC 1.0
OutputBaseFilename=TFODBC64-{#MyAppVersion}
Compression=lzma
SolidCompression=yes
DisableProgramGroupPage=yes
ArchitecturesInstallIn64BitMode=x64
UninstallDisplayName={#MyAppName}
ArchitecturesAllowed=x64
SetupLogging=yes

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

[Files]
Source: "{#BUILDDIR}\win-odbc64\odbcclient\inc\trafsqlext.h"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#BUILDDIR}\lib\x64\Release\traf_odbcDrvMsg_intl0100.dll"; DestDir: "{sys}"
Source: "{#BUILDDIR}\lib\x64\Release\traf_ores0100.dll"; DestDir: "{sys}"
Source: "{#BUILDDIR}\lib\x64\Release\traf_tcpipv40100.dll"; DestDir: "{sys}"
Source: "{#BUILDDIR}\lib\x64\Release\traf_tcpipv60100.dll"; DestDir: "{sys}"
Source: "{#BUILDDIR}\lib\x64\Release\traf_translation01.dll"; DestDir: "{sys}"
Source: "{#BUILDDIR}\lib\x64\Release\trfoadm1.dll"; DestDir: "{sys}"
Source: "{#BUILDDIR}\lib\x64\Release\trfodbc1.dll"; DestDir: "{sys}"
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
Name: "{group}\MS ODBC Administrator"; Filename: "{sys}\odbcad32.exe";  WorkingDir: "{sys}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"

[Registry]
Root: HKLM; SubKey: Software\ODBC\ODBCINST.INI\ODBC Drivers; ValueType: string; ValueName: {#MyDriverName}; ValueData: Installed ;Flags: uninsdeletekey
Root: HKLM; SubKey: Software\ODBC\ODBCINST.INI\{#MyDriverName}; ValueType: dword; ValueName: UsageCount; ValueData: $00000001 ;Flags: uninsdeletekey
Root: HKLM; SubKey: Software\ODBC\ODBCINST.INI\{#MyDriverName}; ValueType: string; ValueName: Driver; ValueData: {sys}\trfodbc1.dll ;Flags: uninsdeletekey
Root: HKLM; SubKey: Software\ODBC\ODBCINST.INI\{#MyDriverName}; ValueType: string; ValueName: Setup; ValueData: {sys}\trfoadm1.dll ;Flags: uninsdeletekey
Root: HKLM; SubKey: Software\ODBC\ODBCINST.INI\{#MyDriverName}; ValueType: string; ValueName: CertificateDir; ValueData: SYSTEM_DEFAULT ;Flags: uninsdeletekey
Root: HKLM; SubKey: Software\ODBC\ODBCINST.INI\{#MyDriverName}; ValueType: string; ValueName: CPTimeout; ValueData: 60 ;Flags: uninsdeletekey

[UninstallDelete]
Type: filesandordirs; Name: "{app}"

[Code]
#IFDEF UNICODE
  #DEFINE AW "W"
#ELSE
  #DEFINE AW "A"
#ENDIF
type
  INSTALLSTATE = Longint;
const
  INSTALLSTATE_INVALIDARG = -2;  // An invalid parameter was passed to the function.
  INSTALLSTATE_UNKNOWN = -1;     // The product is neither advertised or installed.
  INSTALLSTATE_ADVERTISED = 1;   // The product is advertised but not installed.
  INSTALLSTATE_ABSENT = 2;       // The product is installed for a different user.
  INSTALLSTATE_DEFAULT = 5;      // The product is installed for the current user.

  VC_2013_REDIST_X64_MIN = '{A749D8E6-B613-3BE3-8F5F-045C84EBA29B}';
  VC_2013_REDIST_X64_ADD = '{929FBD26-9020-399B-9A7A-751D61F0B942}';

function MsiQueryProductState(szProduct: string): INSTALLSTATE;
  external 'MsiQueryProductState{#AW}@msi.dll stdcall';

function VCVersionInstalled(const ProductID: string): Boolean;
begin
  Result := MsiQueryProductState(ProductID) = INSTALLSTATE_DEFAULT;
end;

function VCRedistNeedsInstall: Boolean;
begin
  // here the Result must be True when you need to install your VCRedist
  // or False when you don't need to, so now it's upon you how you build
  // this statement, the following won't install your VC redist only when
  // the Visual C++ 2010 Redist (x64) and Visual C++ 2010 SP1 Redist(x64)
  // are installed for the current user
  Result := not (VCVersionInstalled(VC_2013_REDIST_X64_MIN) or
    VCVersionInstalled(VC_2013_REDIST_X64_ADD));
end;

function GetUninstallString(): string;
var
  sUnInstPath: string;
  sUnInstPath_is1: string;
  sUnInstallString: String;
  sAppId: String;
  sAppId_is1: String;
begin
  Result := '';
  sAppId := ExpandConstant('{#emit SetupSetting("AppId")}');
  sAppId_is1 := ExpandConstant('{#emit SetupSetting("AppId")}_is1');
  sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\') + sAppId;
  sUnInstPath_is1 := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\') + sAppId_is1;

  sUnInstallString := '';
  if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
    if not RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString) then
      if not RegQueryStringValue(HKLM, sUnInstPath_is1, 'UninstallString', sUnInstallString) then
        RegQueryStringValue(HKCU, sUnInstPath_is1, 'UninstallString', sUnInstallString);
  Result := sUnInstallString;
end;

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

procedure CurStepChanged(CurStep: TSetupStep);
var
  bRedistNeedsInstall: Boolean;
  sDefaultBrowserName: String;
  sDefaultBrowserReg: String;
  sDefaultBrowserValue: String;
  iQuotePos: Integer;
  lLength: Longint;
  iRetCode: Integer;
begin
  if CurStep=ssPostInstall then
  begin
    bRedistNeedsInstall := VCRedistNeedsInstall();
    if bRedistNeedsInstall=True then
    begin
      MsgBox('Install of Visual C++ Redistributable Packages for Visual Studio 2013 is not dectected.'+ #13#10#13#10 + 'Please download vcredist_x64.exe from Microsoft Download Centre and install it.', mbInformation, MB_OK);
      if RegQueryStringValue(HKCU,'Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice','Progid',sDefaultBrowserName) then
      begin
        sDefaultBrowserReg := sDefaultBrowserName + '\shell\open\command';
        if RegQueryStringValue(HKCR,sDefaultBrowserReg,'',sDefaultBrowserValue) then
        begin
          iQuotePos := Pos('"',sDefaultBrowserValue);
          Delete(sDefaultBrowserValue,iQuotePos,1);
          lLength := Length(sDefaultBrowserValue);
          iQuotePos := Pos('"',sDefaultBrowserValue);
          Delete(sDefaultBrowserValue,iQuotePos,lLength);
          Exec(sDefaultBrowserValue, 'http://www.microsoft.com/en-us/download/details.aspx?id=40784', '', SW_SHOW, ewNoWait, iRetCode)
        end
      end
    end
  end
end;

function InitializeSetup: Boolean;
var
  V: Integer;
  iResultCode: Integer;
  sUnInstallString: string;
  sAppId: String;
  sAppId_is1: String;
  sAppName: String;
begin
  Result := True; // in case when no previous version is found
  sAppId := ExpandConstant('{#emit SetupSetting("AppId")}');
  sAppId_is1 := ExpandConstant('{#emit SetupSetting("AppId")}_is1');
  sAppName := ExpandConstant('{#emit SetupSetting("AppName")}');
  sUnInstallString := GetUninstallString();
  if (sUnInstallString <> '') then  //Your App GUID/ID
  begin
    V := MsgBox(ExpandConstant('An existing install of '+ sAppName + ' was detected.' + #13#10#13#10 +'The installer will now uninstall the old version and install the new version.' + #13#10#13#10 +'Do you want to continue?'), mbInformation, MB_YESNO); //Custom Message if App installed
    if V = IDYES then
    begin
      sUnInstallString :=  RemoveQuotes(sUnInstallString);
      if (Pos('msiexec',Lowercase(sUnInstallString)) <> 0) then
      begin
        if not Exec('msiexec.exe', '/X'+sAppId+' /qn', '', SW_SHOW, ewWaitUntilTerminated, iResultCode) then
        begin
        MsgBox('Failed to uninstall existing files.' + #13#10 + ' ' + SysErrorMessage(iResultCode), mbError, MB_OK);
        Result := False;
        end
      end
      else
      begin
        if not Exec(sUnInstallString, '/SILENT', '', SW_SHOW, ewWaitUntilTerminated, iResultCode) then
        begin
        MsgBox('Failed to uninstall existing files.' + #13#10 + ' ' + SysErrorMessage(iResultCode), mbError, MB_OK);
        Result := False;
        end
        else

        Result := True; //if you want to proceed after uninstall
                  //Exit; //if you want to quit after uninstall
     end
     end
    else
      Result := False; //when older version present and not uninstalled
  end;

end;

; @@@ START COPYRIGHT @@@
; Licensed to the Apache Software Foundation (ASF) under one
; or more contributor license agreements.  See the NOTICE file
; distributed with this work for additional information
; regarding copyright ownership.  The ASF licenses this file
; to you under the Apache License, Version 2.0 (the
; "License"); you may not use this file except in compliance
; with the License.  You may obtain a copy of the License at
;   http://www.apache.org/licenses/LICENSE-2.0
; Unless required by applicable law or agreed to in writing,
; software distributed under the License is distributed on an
; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
; KIND, either express or implied.  See the License for the
; specific language governing permissions and limitations
; under the License.
; @@@ END COPYRIGHT @@@
;
; Script generated by the Inno Script Studio Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "Trafodion ODBC64 1.3"
#define MyAppVersion "1.3.0"
#define MyAppPublisher "Apache Trafodion"
#define MyAppURL ""
#define MyDriverName "TRAF ODBC 1.0"
#define BUILDDIR  GetEnv('BUILDDIR')
#define VCREDISTDIR GetEnv('VC_REDIST_DIR')

[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={{5E6042F8-7C2F-490A-899F-9552D5DE8DE2}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultGroupName={#MyAppName}
DefaultDirName={pf}\Trafodion\TRAF ODBC 1.0
OutputBaseFilename=TFODBC64-{#MyAppVersion}
Compression=lzma
SolidCompression=yes
DisableProgramGroupPage=yes
ArchitecturesInstallIn64BitMode=x64
UninstallDisplayName={#MyAppName}
ArchitecturesAllowed=x64
SetupLogging=yes

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

[Files]
Source: "{#BUILDDIR}\win-odbc64\odbcclient\inc\trafsqlext.h"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#BUILDDIR}\lib\x64\Release\traf_odbcDrvMsg_intl0100.dll"; DestDir: "{sys}"
Source: "{#BUILDDIR}\lib\x64\Release\traf_ores0100.dll"; DestDir: "{sys}"
Source: "{#BUILDDIR}\lib\x64\Release\traf_tcpipv40100.dll"; DestDir: "{sys}"
Source: "{#BUILDDIR}\lib\x64\Release\traf_tcpipv60100.dll"; DestDir: "{sys}"
Source: "{#BUILDDIR}\lib\x64\Release\traf_translation01.dll"; DestDir: "{sys}"
Source: "{#BUILDDIR}\lib\x64\Release\trfoadm1.dll"; DestDir: "{sys}"
Source: "{#BUILDDIR}\lib\x64\Release\trfodbc1.dll"; DestDir: "{sys}"
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
Name: "{group}\MS ODBC Administrator"; Filename: "{sys}\odbcad32.exe";  WorkingDir: "{sys}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"

[Registry]
Root: HKLM; SubKey: Software\ODBC\ODBCINST.INI\ODBC Drivers; ValueType: string; ValueName: {#MyDriverName}; ValueData: Installed ;Flags: uninsdeletekey
Root: HKLM; SubKey: Software\ODBC\ODBCINST.INI\{#MyDriverName}; ValueType: dword; ValueName: UsageCount; ValueData: $00000001 ;Flags: uninsdeletekey
Root: HKLM; SubKey: Software\ODBC\ODBCINST.INI\{#MyDriverName}; ValueType: string; ValueName: Driver; ValueData: {sys}\trfodbc1.dll ;Flags: uninsdeletekey
Root: HKLM; SubKey: Software\ODBC\ODBCINST.INI\{#MyDriverName}; ValueType: string; ValueName: Setup; ValueData: {sys}\trfoadm1.dll ;Flags: uninsdeletekey
Root: HKLM; SubKey: Software\ODBC\ODBCINST.INI\{#MyDriverName}; ValueType: string; ValueName: CertificateDir; ValueData: SYSTEM_DEFAULT ;Flags: uninsdeletekey
Root: HKLM; SubKey: Software\ODBC\ODBCINST.INI\{#MyDriverName}; ValueType: string; ValueName: CPTimeout; ValueData: 60 ;Flags: uninsdeletekey

[Code]
[Files]
Source: "{#VCREDISTDIR}\vcredist_x64.exe"; DestDir: {tmp}; Flags: deleteafterinstall

[Run]
; add the Parameters, WorkingDir and StatusMsg as you wish, just keep here
; the conditional installation Check
Filename: "{tmp}\vcredist_x64.exe"; Check: VCRedistNeedsInstall

[UninstallDelete]
Type: filesandordirs; Name: "{app}"

[Code]
#IFDEF UNICODE
  #DEFINE AW "W"
#ELSE
  #DEFINE AW "A"
#ENDIF
type
  INSTALLSTATE = Longint;
const
  INSTALLSTATE_INVALIDARG = -2;  // An invalid parameter was passed to the function.
  INSTALLSTATE_UNKNOWN = -1;     // The product is neither advertised or installed.
  INSTALLSTATE_ADVERTISED = 1;   // The product is advertised but not installed.
  INSTALLSTATE_ABSENT = 2;       // The product is installed for a different user.
  INSTALLSTATE_DEFAULT = 5;      // The product is installed for the current user.

  VC_2013_REDIST_X64_MIN = '{A749D8E6-B613-3BE3-8F5F-045C84EBA29B}';
  VC_2013_REDIST_X64_ADD = '{929FBD26-9020-399B-9A7A-751D61F0B942}';

function MsiQueryProductState(szProduct: string): INSTALLSTATE;
  external 'MsiQueryProductState{#AW}@msi.dll stdcall';

function VCVersionInstalled(const ProductID: string): Boolean;
begin
  Result := MsiQueryProductState(ProductID) = INSTALLSTATE_DEFAULT;
end;

function VCRedistNeedsInstall: Boolean;
begin
  // here the Result must be True when you need to install your VCRedist
  // or False when you don't need to, so now it's upon you how you build
  // this statement, the following won't install your VC redist only when
  // the Visual C++ 2010 Redist (x64) and Visual C++ 2010 SP1 Redist(x64)
  // are installed for the current user
  Result := not (VCVersionInstalled(VC_2013_REDIST_X64_MIN) or
    VCVersionInstalled(VC_2013_REDIST_X64_ADD));
end;

function GetUninstallString(): string;
var
  sUnInstPath: string;
  sUnInstPath_is1: string;
  sUnInstallString: String;
  sAppId: String;
  sAppId_is1: String;
begin
  Result := '';
  sAppId := ExpandConstant('{#emit SetupSetting("AppId")}');
  sAppId_is1 := ExpandConstant('{#emit SetupSetting("AppId")}_is1');
  sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\') + sAppId;
  sUnInstPath_is1 := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\') + sAppId_is1;

  sUnInstallString := '';
  if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
    if not RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString) then
      if not RegQueryStringValue(HKLM, sUnInstPath_is1, 'UninstallString', sUnInstallString) then
        RegQueryStringValue(HKCU, sUnInstPath_is1, 'UninstallString', sUnInstallString);
  Result := sUnInstallString;
end;

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

function InitializeSetup: Boolean;
var
  V: Integer;
  iResultCode: Integer;
  sUnInstallString: string;
  sAppId: String;
  sAppId_is1: String;
  sAppName: String;
begin
  Result := True; // in case when no previous version is found
  sAppId := ExpandConstant('{#emit SetupSetting("AppId")}');
  sAppId_is1 := ExpandConstant('{#emit SetupSetting("AppId")}_is1');
  sAppName := ExpandConstant('{#emit SetupSetting("AppName")}');
  sUnInstallString := GetUninstallString();
  if (sUnInstallString <> '') then  //Your App GUID/ID
  begin
    V := MsgBox(ExpandConstant('An existing install of '+ sAppName + ' was detected.' + #13#10#13#10 +'The installer will now uninstall the old version and install the new version.' + #13#10#13#10 +'Do you want to continue?'), mbInformation, MB_YESNO); //Custom Message if App installed
    if V = IDYES then
    begin
      sUnInstallString :=  RemoveQuotes(sUnInstallString);
      if (Pos('msiexec',Lowercase(sUnInstallString)) <> 0) then
      begin
        if not Exec('msiexec.exe', '/X'+sAppId+' /qn', '', SW_SHOW, ewWaitUntilTerminated, iResultCode) then
        begin
        MsgBox('Failed to uninstall existing files.' + #13#10 + ' ' + SysErrorMessage(iResultCode), mbError, MB_OK);
        Result := False;
        end
      end
      else
      begin
        if not Exec(sUnInstallString, '/SILENT', '', SW_SHOW, ewWaitUntilTerminated, iResultCode) then
        begin
        MsgBox('Failed to uninstall existing files.' + #13#10 + ' ' + SysErrorMessage(iResultCode), mbError, MB_OK);
        Result := False;
        end
        else

        Result := True; //if you want to proceed after uninstall
                  //Exit; //if you want to quit after uninstall
     end
     end
    else
      Result := False; //when older version present and not uninstalled
  end;

end;


Windows uninstall previous version before installing new one

; Installer Variables
#define AppName "Atraci"
#define AppVersion "0.6.5"
#define AppPublisher "Atraci Team"
#define AppURL "http://getatraci.net"
#define AppExeName "run.bat"
#define WebKitVersion "0.10.1"

[Setup]
; DON'T FUCK WITH THE APPID. This uniquely identifies this application, which is used to find the app if we need to update it.
AppId={{F4B2C5C1-F084-4858-B9C3-E641F5C12BBC}

AppName={#AppName}
AppVersion={#AppVersion}
AppVerName={#AppName} {#AppVersion}
AppPublisher={#AppPublisher}
AppPublisherURL={#AppURL}
AppSupportURL={#AppURL}
AppUpdatesURL={#AppURL}

; Make the Installer nicer and Minimalistic
WizardImageFile=.\installer-image.bmp
WindowResizable=no

; Don't ask for a install folder (it goes into \Users\Username\AppData\Roaming\Atraci\, which doesn't require admin privileges)
UsePreviousAppDir=no
DefaultDirName={userappdata}\Atraci

; No Start Menu Folder picker (It's always created)
DefaultGroupName={#AppName}
DisableProgramGroupPage=yes

; We just need a Welcome Page and a Finish page. Nothing else.
DisableReadyPage=yes
DisableFinishedPage=no
DisableWelcomePage=no

; No UAC bullshit
PrivilegesRequired=lowest
; Put the uninstaller in the same folder, or else it'll go into Program Files, which requires Admin Privileges
UninstallFilesDir={app}

; Use the same language as the user (or ask otherwise)
ShowLanguageDialog=no

; Compress the files nicely
Compression=lzma2
SolidCompression=yes

; Final Installer
OutputBaseFilename=Install {#AppName} {#AppVersion}
SetupIconFile=..\..\images\atraci.ico
OutputDir=.\

[Languages]
Name: "en"; MessagesFile: ".\languages\English.isl"

[Files]
Source: ".\run.bat"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\..\index.html"; DestDir: "{app}\app\"; Flags: ignoreversion
Source: "..\..\package.json"; DestDir: "{app}\app\"; Flags: ignoreversion
Source: "..\..\featured-music\*"; DestDir: "{app}\app\featured-music\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\l10n\*"; DestDir: "{app}\app\l10n\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\css\*"; DestDir: "{app}\app\css\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\fonts\*"; DestDir: "{app}\app\fonts\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\js\*"; DestDir: "{app}\app\js\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\images\*"; DestDir: "{app}\app\images\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\node_modules\node-uuid\*"; DestDir: "{app}\app\node_modules\node-uuid\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\node_modules\request\*"; DestDir: "{app}\app\node_modules\request\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\node_modules\universal-analytics\*"; DestDir: "{app}\app\node_modules\universal-analytics\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\node_modules\ytdl\*"; DestDir: "{app}\app\node_modules\ytdl\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\cache\{#WebKitVersion}\win\*"; DestDir: "{app}\node-webkit\"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
; Add an Icon in the app folder as a reference
Name: "{app}\{#AppName}"; WorkingDir: "{app}"; Filename: "{app}\node-webkit\nw.exe"; Parameters:"""{app}\app"""; IconFilename: "{app}\app\images\atraci.ico"; Flags: runminimized preventpinning
; Another in the group (this one can be featured)
Name: "{group}\{#AppName}"; WorkingDir: "{app}"; Filename: "{app}\node-webkit\nw.exe"; Parameters:"""{app}\app"""; IconFilename: "{app}\app\images\atraci.ico"; Flags: runminimized
; Another in the desktop
Name: "{commondesktop}\{#AppName}"; WorkingDir: "{app}"; Filename: "{app}\node-webkit\nw.exe"; Parameters:"""{app}\app"""; IconFilename: "{app}\app\images\atraci.ico"; Flags: runminimized preventpinning

[Run]
; Run the app after installing
Filename: "{app}\node-webkit\nw.exe"; Parameters: """{app}\app"""; Description: "{cm:LaunchProgram,{#StringChange(AppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent runminimized

[Code]
/////////////////////////////////////////////////////////////////////
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
    begin
      UnInstallOldVersion();
    end;
  end;
end;

; Installer Variables
#define AppName "Atraci"
#define AppVersion "0.6.0"
#define AppPublisher "Atraci Team"
#define AppURL "http://getatraci.net"
#define AppExeName "run.bat"
#define WebKitVersion "0.10.1"

[Setup]
; DON'T FUCK WITH THE APPID. This uniquely identifies this application, which is used to find the app if we need to update it.
AppId={{F4B2C5C1-F084-4858-B9C3-E641F5C12BBC}

AppName={#AppName}
AppVersion={#AppVersion}
AppVerName={#AppName} {#AppVersion}
AppPublisher={#AppPublisher}
AppPublisherURL={#AppURL}
AppSupportURL={#AppURL}
AppUpdatesURL={#AppURL}

; Make the Installer nicer and Minimalistic
WizardImageFile=.\installer-image.bmp
WindowResizable=no

; Don't ask for a install folder (it goes into \Users\Username\AppData\Roaming\Atraci\, which doesn't require admin privileges)
UsePreviousAppDir=no
DefaultDirName={userappdata}\Atraci

; No Start Menu Folder picker (It's always created)
DefaultGroupName={#AppName}
DisableProgramGroupPage=yes

; We just need a Welcome Page and a Finish page. Nothing else.
DisableReadyPage=yes
DisableFinishedPage=no
DisableWelcomePage=no

; No UAC bullshit
PrivilegesRequired=lowest
; Put the uninstaller in the same folder, or else it'll go into Program Files, which requires Admin Privileges
UninstallFilesDir={app}

; Use the same language as the user (or ask otherwise)
ShowLanguageDialog=no

; Compress the files nicely
Compression=lzma2
SolidCompression=yes

; Final Installer
OutputBaseFilename=Install {#AppName} {#AppVersion}
SetupIconFile=..\..\images\atraci.ico
OutputDir=.\

[Languages]
Name: "en"; MessagesFile: ".\languages\English.isl"

[Files]
Source: ".\run.bat"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\..\index.html"; DestDir: "{app}\app\"; Flags: ignoreversion
Source: "..\..\package.json"; DestDir: "{app}\app\"; Flags: ignoreversion
Source: "..\..\featured-music\*"; DestDir: "{app}\app\featured-music\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\l10n\*"; DestDir: "{app}\app\l10n\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\css\*"; DestDir: "{app}\app\css\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\fonts\*"; DestDir: "{app}\app\fonts\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\js\*"; DestDir: "{app}\app\js\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\images\*"; DestDir: "{app}\app\images\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\node_modules\node-uuid\*"; DestDir: "{app}\app\node_modules\node-uuid\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\node_modules\request\*"; DestDir: "{app}\app\node_modules\request\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\node_modules\universal-analytics\*"; DestDir: "{app}\app\node_modules\universal-analytics\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\node_modules\ytdl\*"; DestDir: "{app}\app\node_modules\ytdl\"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\..\cache\{#WebKitVersion}\win\*"; DestDir: "{app}\node-webkit\"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
; Add an Icon in the app folder as a reference
Name: "{app}\{#AppName}"; WorkingDir: "{app}"; Filename: "{app}\node-webkit\nw.exe"; Parameters:"""{app}\app"""; IconFilename: "{app}\app\images\atraci.ico"; Flags: runminimized preventpinning
; Another in the group (this one can be featured)
Name: "{group}\{#AppName}"; WorkingDir: "{app}"; Filename: "{app}\node-webkit\nw.exe"; Parameters:"""{app}\app"""; IconFilename: "{app}\app\images\atraci.ico"; Flags: runminimized
; Another in the desktop
Name: "{commondesktop}\{#AppName}"; WorkingDir: "{app}"; Filename: "{app}\node-webkit\nw.exe"; Parameters:"""{app}\app"""; IconFilename: "{app}\app\images\atraci.ico"; Flags: runminimized preventpinning

[Run]
; Run the app after installing
Filename: "{app}\node-webkit\nw.exe"; Parameters: """{app}\app"""; Description: "{cm:LaunchProgram,{#StringChange(AppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent runminimized


added installer images.

added installer images.

#define BuildMode "opt"
#define AppName "cycles"
#define AppVerName "cycles 1.0"
#define Publisher "CHDS"
#define AppURL "http://dmzdev.org"
#define AppExeName "cycles.exe"
#define DependDir "..\..\..\depend"
#define VsDir "c:\Program Files\Microsoft Visual Studio 8"

[Setup]
AppId={{FF5299C5-982A-49CD-8A81-405BB6529401}
AppName={#AppName}
AppVerName={#AppVerName}
AppPublisher={#Publisher}
AppPublisherURL={#AppURL}
AppSupportURL={#AppURL}
AppUpdatesURL={#AppURL}
ShowLanguageDialog=no
DefaultDirName={pf}\{#AppName}
DefaultGroupName={#AppName}
UninstallDisplayName={#AppName}
UninstallDisplayIcon={app}\bin\{#AppExeName}
UninstallFilesDir={app}\uninst
OutputDir=.
OutputBaseFilename=cyclessetup
;OutputManifestFile=manifest.txt
WizardImageFile=WizImage.bmp
WizardSmallImageFile=WizSmallImage.bmp
SetupIconFile=Setup.ico
Compression=lzma
SolidCompression=yes

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

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

[Icons]
Name: {group}\{#AppName}; Filename: {app}\bin\{#AppExeName}; WorkingDir: {app}; IconFilename: {app}\bin\{#AppExeName}; Tasks:
Name: {group}\{cm:UninstallProgram,{#AppName}}; Filename: {uninstallexe}
Name: {userdesktop}\{#AppName}; Filename: {app}\bin\{#AppExeName}; Tasks: desktopicon; WorkingDir: {app}; IconFilename: {app}\bin\{#AppExeName}; Languages:
Name: {userappdata}\Microsoft\Internet Explorer\Quick Launch\{#AppName}; Filename: {app}\bin\{#AppExeName}; Tasks: quicklaunchicon; WorkingDir: {app}; IconFilename: {app}\bin\{#AppExeName}; Languages:

[Run]
Filename: {app}\bin\{#AppExeName}; Description: {cm:LaunchProgram,{#AppName}}; Flags: nowait postinstall skipifsilent; Tasks: ; Languages:

[Registry]
Root: HKLM; Subkey: Software\DMZ\{#AppName}; ValueType: string; ValueName: workingDir; ValueData: {app}; Flags: uninsdeletekey
Root: HKCR; Subkey: cycles.file\shell\open\command; ValueType: string; ValueData: "{app}\bin\cycles.exe ""%1"""; Flags: uninsdeletekey

[Files]
Source: ..\..\..\bin\win32-{#BuildMode}\cycles.app\*; DestDir: {app}; Flags: recursesubdirs
Source: {#DependDir}\bin\QtCore4.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\QtGui4.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\QtOpenGL4.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\QtSvg4.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\QtXml4.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osg44-osg.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osg44-osgSim.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osg44-osgGA.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osg44-osgViewer.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osg44-osgUtil.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osg44-osgDB.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\ot11-OpenThreads.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\libpng13.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osgplugins-2.6.0\osgdb_png.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osgplugins-2.6.0\osgdb_obj.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\fmodex.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\fmodexL.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\fmodexp.dll; DestDir: {app}\bin
Source: {#VsDir}\VC\redist\x86\Microsoft.VC80.CRT\*; DestDir: {app}\bin\Microsoft.VC80.CRT

#define BuildMode "opt"
#define AppName "cycles"
#define AppVerName "cycles 1.0"
#define Publisher "CHDS"
#define AppURL "http://dmzdev.org"
#define AppExeName "cycles.exe"
#define DependDir "..\..\..\depend"
#define VsDir "c:\Program Files\Microsoft Visual Studio 8"

[Setup]
AppId={{FF5299C5-982A-49CD-8A81-405BB6529401}
AppName={#AppName}
AppVerName={#AppVerName}
AppPublisher={#Publisher}
AppPublisherURL={#AppURL}
AppSupportURL={#AppURL}
AppUpdatesURL={#AppURL}
ShowLanguageDialog=no
DefaultDirName={pf}\{#AppName}
DefaultGroupName={#AppName}
UninstallDisplayName={#AppName}
UninstallDisplayIcon={app}\bin\{#AppExeName}
UninstallFilesDir={app}\uninst
OutputDir=.
OutputBaseFilename=cyclessetup
;OutputManifestFile=manifest.txt
;WizardImageFile=WizImage.bmp
;WizardSmallImageFile=WizSmallImage.bmp
SetupIconFile=Setup.ico
Compression=lzma
SolidCompression=yes

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

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

[Icons]
Name: {group}\{#AppName}; Filename: {app}\bin\{#AppExeName}; WorkingDir: {app}; IconFilename: {app}\bin\{#AppExeName}; Tasks:
Name: {group}\{cm:UninstallProgram,{#AppName}}; Filename: {uninstallexe}
Name: {userdesktop}\{#AppName}; Filename: {app}\bin\{#AppExeName}; Tasks: desktopicon; WorkingDir: {app}; IconFilename: {app}\bin\{#AppExeName}; Languages:
Name: {userappdata}\Microsoft\Internet Explorer\Quick Launch\{#AppName}; Filename: {app}\bin\{#AppExeName}; Tasks: quicklaunchicon; WorkingDir: {app}; IconFilename: {app}\bin\{#AppExeName}; Languages:

[Run]
Filename: {app}\bin\{#AppExeName}; Description: {cm:LaunchProgram,{#AppName}}; Flags: nowait postinstall skipifsilent; Tasks: ; Languages:

[Registry]
Root: HKLM; Subkey: Software\DMZ\{#AppName}; ValueType: string; ValueName: workingDir; ValueData: {app}; Flags: uninsdeletekey
Root: HKCR; Subkey: cycles.file\shell\open\command; ValueType: string; ValueData: "{app}\bin\cycles.exe ""%1"""; Flags: uninsdeletekey

[Files]
Source: ..\..\..\bin\win32-{#BuildMode}\cycles.app\*; DestDir: {app}; Flags: recursesubdirs
Source: {#DependDir}\bin\QtCore4.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\QtGui4.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\QtOpenGL4.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\QtSvg4.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\QtXml4.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osg44-osg.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osg44-osgSim.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osg44-osgGA.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osg44-osgViewer.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osg44-osgUtil.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osg44-osgDB.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\ot11-OpenThreads.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\libpng13.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osgplugins-2.6.0\osgdb_png.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\osgplugins-2.6.0\osgdb_obj.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\fmodex.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\fmodexL.dll; DestDir: {app}\bin
Source: {#DependDir}\bin\fmodexp.dll; DestDir: {app}\bin
Source: {#VsDir}\VC\redist\x86\Microsoft.VC80.CRT\*; DestDir: {app}\bin\Microsoft.VC80.CRT


Handle autostart reg keys in installer

Handle autostart reg keys in installer

#define AppExeName "SyncTrayzor.exe"
#define AppRoot ".."
#define AppSrc AppRoot + "\src\SyncTrayzor"
#define AppBin AppRoot +"\bin\Release"
#define AppExe AppBin + "\SyncTrayzor.exe"
#define AppName GetStringFileInfo(AppExe, "ProductName")
#define AppVersion GetFileVersion(AppExe)
#define AppPublisher "SyncTrayzor"
#define AppURL "https://github.com/canton7/SyncTrayzor"
#define AppDataFolder "SyncTrayzor"
#define RunRegKey "Software\Microsoft\Windows\CurrentVersion\Run"

[Setup]
AppId={{c004dcef-b848-46a5-9c30-4dbf736396fa}
AppName={#AppName}
AppVersion={#AppVersion}
;AppVerName={#AppName} {#AppVersion}
AppPublisher={#AppPublisher}
AppPublisherURL={#AppURL}
AppSupportURL={#AppURL}
AppUpdatesURL={#AppURL}
DefaultDirName={pf}\{#AppName}
DefaultGroupName={#AppName}
AllowNoIcons=yes
LicenseFile={#AppRoot}\LICENSE.txt
OutputDir="."
OutputBaseFilename={#AppName}Setup_{#AppVersion}
SetupIconFile={#AppSrc}\Icons\default.ico
Compression=lzma
SolidCompression=yes
PrivilegesRequired=admin

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

[Tasks]
Name: "startonlogon"; Description: "Start SyncTrayzor automatically on logon"; GroupDescription: "Autostart"
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked

[Dirs]
Name: "{userappdata}\{#AppDataFolder}"

[Files]
Source: "{#AppBin}\{#AppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#AppBin}\*.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#AppBin}\*.pdb"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#AppSrc}\Icons\default.ico"; DestDir: "{app}"; Flags: ignoreversion
Source: "syncthing.exe"; DestDir: "{userappdata}\{#AppDataFolder}"
Source: "dotNet451Setup.exe"; DestDir: {tmp}; Flags: deleteafterinstall; Check: FrameworkIsNotInstalled

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

[Registry]
Root: HKCU; Subkey: "{#RunRegKey}"; ValueType: string; ValueName: "SyncTrayzor"; ValueData: """{app}\{#AppExeName}"" -minimized"; Tasks: startonlogon

[Run]
Filename: "{tmp}\dotNet451Setup.exe"; Parameters: "/passive /promptrestart"; Check: FrameworkIsNotInstalled; StatusMsg: "Microsoft .NET Framework 4.5.1 is being installed. Please wait..."
Filename: "{app}\{#AppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(AppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

[Code]
function FrameworkIsNotInstalled: Boolean;
var
  exists: boolean;
  release: cardinal;
begin
  exists := RegQueryDWordValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Release', release);
  result := not exists or (release < 378758);
end;

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
  if CurUninstallStep = usPostUninstall then
  begin
    if RegValueExists(HKEY_CURRENT_USER, '{#RunRegKey}', 'SyncTrayzor') then
      RegDeleteValue(HKEY_CURRENT_USER, '{#RunRegKey}', 'SyncTrayzor');
  end;
end;

[UninstallDelete]
Type: files; Name: "{userappdata}\{#AppDataFolder}\config.xml"
Type: dirifempty; Name: "{userappdata}\{#AppDataFolder}"

#define AppExeName "SyncTrayzor.exe"
#define AppRoot ".."
#define AppSrc AppRoot + "\src\SyncTrayzor"
#define AppBin AppRoot +"\bin\Release"
#define AppExe AppBin + "\SyncTrayzor.exe"
#define AppName GetStringFileInfo(AppExe, "ProductName")
#define AppVersion GetFileVersion(AppExe)
#define AppPublisher "SyncTrayzor"
#define AppURL "https://github.com/canton7/SyncTrayzor"
#define AppDataFolder "SyncTrayzor"

[Setup]
AppId={{c004dcef-b848-46a5-9c30-4dbf736396fa}
AppName={#AppName}
AppVersion={#AppVersion}
;AppVerName={#AppName} {#AppVersion}
AppPublisher={#AppPublisher}
AppPublisherURL={#AppURL}
AppSupportURL={#AppURL}
AppUpdatesURL={#AppURL}
DefaultDirName={pf}\{#AppName}
DefaultGroupName={#AppName}
AllowNoIcons=yes
LicenseFile={#AppRoot}\LICENSE.txt
OutputDir="."
OutputBaseFilename={#AppName}Setup_{#AppVersion}
SetupIconFile={#AppSrc}\Icons\default.ico
Compression=lzma
SolidCompression=yes

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

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

[Dirs]
Name: "{userappdata}\{#AppDataFolder}"

[Files]
Source: "{#AppBin}\{#AppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#AppBin}\*.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#AppBin}\*.pdb"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#AppSrc}\Icons\default.ico"; DestDir: "{app}"; Flags: ignoreversion
Source: "syncthing.exe"; DestDir: "{userappdata}\{#AppDataFolder}"
Source: "dotNet451Setup.exe"; DestDir: {tmp}; Flags: deleteafterinstall; Check: FrameworkIsNotInstalled

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

[Run]
Filename: "{tmp}\dotNet451Setup.exe"; Parameters: "/passive /promptrestart"; Check: FrameworkIsNotInstalled; StatusMsg: Microsoft .NET Framework 4.5.1 is being installed. Please wait...
Filename: "{app}\{#AppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(AppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

[code]
function FrameworkIsNotInstalled: Boolean;
var
  exists: boolean;
  release: cardinal;
begin
  exists := RegQueryDWordValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Release', release);
  result := not exists or (release < 378758);
end;

[UninstallDelete]
Type: files; Name: "{userappdata}\{#AppDataFolder}\config.xml"
Type: dirifempty; Name: "{userappdata}\{#AppDataFolder}"


changed version #

changed version #

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

[Setup]
AppName=SansView-0.9.1
AppVerName=SansView 0.9.1
AppPublisher=University of Tennessee
AppPublisherURL=http://danse.chem.utk.edu/
AppSupportURL=http://danse.chem.utk.edu/
AppUpdatesURL=http://danse.chem.utk.edu/
DefaultDirName={pf}\SansView-0.9.1
DefaultGroupName=DANSE\SansView-0.9.1
DisableProgramGroupPage=yes
LicenseFile=license.txt
OutputBaseFilename=setupSansView
SetupIconFile=images\ball.ico
Compression=lzma
SolidCompression=yes
PrivilegesRequired=none

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

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

[Files]
Source: "dist\SansView.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "dist\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "images\*"; DestDir: "{app}\images"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "test\*"; DestDir: "{app}\test"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
Name: "{group}\SansView"; Filename: "{app}\SansView.exe"; WorkingDir: "{app}"
Name: "{group}\{cm:UninstallProgram,SansView}"; Filename: "{uninstallexe}"
Name: "{commondesktop}\SansView 0.9.1"; Filename: "{app}\SansView.exe"; Tasks: desktopicon; WorkingDir: "{app}"

[Run]
Filename: "{app}\SansView.exe"; Description: "{cm:LaunchProgram,SansView}"; Flags: nowait postinstall skipifsilent

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

[Setup]
AppName=SansView-0.9
AppVerName=SansView 0.9
AppPublisher=University of Tennessee
AppPublisherURL=http://danse.chem.utk.edu/
AppSupportURL=http://danse.chem.utk.edu/
AppUpdatesURL=http://danse.chem.utk.edu/
DefaultDirName={pf}\SansView-0.9
DefaultGroupName=DANSE\SansView-0.9
DisableProgramGroupPage=yes
LicenseFile=license.txt
OutputBaseFilename=setupSansView
SetupIconFile=images\ball.ico
Compression=lzma
SolidCompression=yes
PrivilegesRequired=none

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

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

[Files]
Source: "dist\SansView.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "dist\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "images\*"; DestDir: "{app}\images"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "test\*"; DestDir: "{app}\test"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
Name: "{group}\SansView"; Filename: "{app}\SansView.exe"; WorkingDir: "{app}"
Name: "{group}\{cm:UninstallProgram,SansView}"; Filename: "{uninstallexe}"
Name: "{commondesktop}\SansView 0.9"; Filename: "{app}\SansView.exe"; Tasks: desktopicon; WorkingDir: "{app}"

[Run]
Filename: "{app}\SansView.exe"; Description: "{cm:LaunchProgram,SansView}"; Flags: nowait postinstall skipifsilent


Forgot to save installer.

Forgot to save installer.

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

#define MyAppName "BorderlessImageViewer"
#define MyAppVersion "20220414"
#define MyAppURL "https://github.com/Helios-vmg/Borderless"
#define MyAppExeName "Borderless.exe"
#define SourceBasePath ".."

[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={{F86CCAD1-7B42-4869-8A0B-3B32A0717A0B}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppName}
DisableProgramGroupPage=yes
LicenseFile={#SourceBasePath}\COPYING.txt
OutputDir={#SourceBasePath}\bin64\
OutputBaseFilename=Borderless_setup_noredist
SetupIconFile=custom\icons\icon.ico
Compression=lzma
SolidCompression=yes
ArchitecturesInstallIn64BitMode=x64

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

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

[Files]
Source: "{#SourceBasePath}\bin64\{#MyAppExeName}"; DestDir: "{app}\bin"; Flags: ignoreversion
Source: "{#SourceBasePath}\COPYING.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "custom\qt.conf"; DestDir: "{app}\bin"; Flags: ignoreversion
Source: "custom\bin\*"; DestDir: "{app}\bin"; Flags: ignoreversion recursesubdirs

[Registry]
; Set up Applications subkey
Root: HKCR; Subkey: "Applications\{#MyAppExeName}"; Flags: uninsdeletekey
Root: HKCR; Subkey: "Applications\{#MyAppExeName}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppName}"
Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; Flags: uninsdeletekey
Root: HKCR; Subkey: "Applications\{#MyAppExeName}\shell\open\command"; Flags: uninsdeletekey
Root: HKCR; Subkey: "Applications\{#MyAppExeName}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\{#MyAppExeName}"" ""%1"""

#include "registry.iss"

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

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

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

#define MyAppName "BorderlessImageViewer"
#define MyAppVersion "20220414"
#define MyAppURL "https://github.com/Helios-vmg/Borderless"
#define MyAppExeName "Borderless.exe"
#define SourceBasePath ".."

[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={{F86CCAD1-7B42-4869-8A0B-3B32A0717A0B}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppName}
DisableProgramGroupPage=yes
LicenseFile={#SourceBasePath}\COPYING.txt
OutputDir={#SourceBasePath}\bin64\
OutputBaseFilename=Borderless_setup
SetupIconFile=custom\icons\icon.ico
Compression=lzma
SolidCompression=yes
ArchitecturesInstallIn64BitMode=x64

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

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

[Files]
Source: "{#SourceBasePath}\bin64\{#MyAppExeName}"; DestDir: "{app}\bin"; Flags: ignoreversion
Source: "{#SourceBasePath}\COPYING.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "custom\qt.conf"; DestDir: "{app}\bin"; Flags: ignoreversion
Source: "custom\bin\*"; DestDir: "{app}\bin"; Flags: ignoreversion recursesubdirs

[Registry]
; Set up Applications subkey
Root: HKCR; Subkey: "Applications\{#MyAppExeName}"; Flags: uninsdeletekey
Root: HKCR; Subkey: "Applications\{#MyAppExeName}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppName}"
Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; Flags: uninsdeletekey
Root: HKCR; Subkey: "Applications\{#MyAppExeName}\shell\open\command"; Flags: uninsdeletekey
Root: HKCR; Subkey: "Applications\{#MyAppExeName}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\{#MyAppExeName}"" ""%1"""

#include "registry.iss"

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

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