Rethink portable releases:

* Remove complicated and unreadable NSIS stuff. No need to have a installer for a developer application. ZIP file is fine.
* On startup, if a portable_settings.txt exists in the application folder, heidisql.exe will read its contents into a unique registry key.
* In MainForm.OnDestroy, settings are written to that file again, and the reg key gets deleted.
* Avoid using Microsoft's .reg file syntax, as you need admin privileges to store and restore such files, even when using the appropriate Windows API functions.
This commit is contained in:
Ansgar Becker
2010-03-22 21:10:38 +00:00
parent 4724d660eb
commit ed5ec1e122
12 changed files with 119 additions and 2053 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

View File

@ -1,84 +0,0 @@
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
; Original HeidiSQL Portable setup script for Innosetup based on
; HeidiSQL setup script
[Setup]
AppId=HeidiSQL
AppName=HeidiSQL Portable
AppVerName=HeidiSQL Portable 4.0
AppVersion=1.0.0.0
VersionInfoVersion=1.0.0.0
AppPublisher=Ansgar Becker
AppPublisherURL=http://www.heidisql.com/
AppSupportURL=http://forum.heidisql.com/
AppUpdatesURL=http://download.heidisql.com/
AppContact=heidisql@anse.de
DefaultDirName=\HeidiSQLPortable
LicenseFile=.\..\..\out\license.txt
WizardImageFile=.\..\..\res\installer-logo.bmp
WizardImageBackColor=$ffffff
WizardSmallImageFile=.\..\..\res\installer-small-logo.bmp
OutputDir=.
OutputBaseFilename=HeidiSQLPortable_4.0_Setup
SetupIconFile=.\..\..\res\mainicon.ico
; uncomment the following line if you want your installation to run on NT 3.51 too.
; MinVersion=4,3.51
UsePreviousAppDir=no
DirExistsWarning=auto
PrivilegesRequired=none
; no uninstallation support is included, requiring the end-user
; to manually remove the files pertaining to your application.
Uninstallable=no
[InstallDelete]
Type: files; Name: "{app}\App\HeidiSQL\libmysql40.dll"
Type: files; Name: "{app}\App\HeidiSQL\libmysql41.dll"
Type: files; Name: "{app}\App\HeidiSQL\heidisql.exe.manifest"
[Files]
Source: ".\HeidiSQLPortable.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: ".\..\..\out\heidisql.exe"; DestDir: "{app}\App\HeidiSQL"; Flags: ignoreversion
Source: ".\..\..\out\readme.txt"; DestDir: "{app}\App\HeidiSQL"; Flags: ignoreversion
Source: ".\..\..\out\license.txt"; DestDir: "{app}\App\HeidiSQL"; Flags: ignoreversion
Source: ".\..\..\out\gpl.txt"; DestDir: "{app}\App\HeidiSQL"; Flags: ignoreversion
Source: ".\..\..\out\libmysql.dll"; DestDir: "{app}\App\HeidiSQL"; Flags: ignoreversion
[INI]
Filename: "{app}\App\HeidiSQL\heidisql.url"; Section: "InternetShortcut"; Key: "URL"; String: "http://www.heidisql.com/"
Filename: "{app}\App\HeidiSQL\heidisql_forum.url"; Section: "InternetShortcut"; Key: "URL"; String: "http://www.heidisql.com/forum/"
Filename: "{app}\App\HeidiSQL\donate.url"; Section: "InternetShortcut"; Key: "URL"; String: "http://www.heidisql.com/donate.php"
[Run]
Filename: "{app}\HeidiSQLPortable.exe"; Description: "Launch HeidiSQL Portable"; Flags: nowait postinstall skipifsilent
[Code]
procedure DonateClick(Sender: TObject);
var
ErrorCode: Integer;
begin
ShellExec('open', 'http://www.heidisql.com/donate.php', '', '', SW_SHOWNORMAL, ewNoWait, ErrorCode);
end;
procedure InitializeWizard();
var
txt: TNewStaticText;
btn: TButton;
begin
txt := TNewStaticText.Create(WizardForm);
txt.Parent := WizardForm.FinishedPage;
txt.Caption := 'HeidiSQL is free software. You may make a donation:';
txt.Left := WizardForm.FinishedLabel.Left;
txt.Top := WizardForm.FinishedLabel.Top + 130;
txt.AutoSize := True;
btn := TButton.Create(WizardForm);
btn.Parent := WizardForm.FinishedPage;
btn.Left := txt.Left;
btn.Top := txt.Top + txt.Height + 10;
btn.Width := 120;
btn.Height := WizardForm.CancelButton.Height;
btn.Caption := 'Donate';
btn.OnClick := @DonateClick;
end;

View File

@ -1,454 +0,0 @@
; **************************************************************************
; Name: HeidiSQL Portable
;
; Website: http://www.heidisql.com/
;
; Written for:
; NSIS 2.45 or higher
; Required plugins: Registry, FindProcDLL
;
; License:
; Copyright<68> 2009 by HeidiSQL Team
;
; Attention: When doing backups of existing directories or files, this could be a lengthy
; operation depending on the speed of your USB device. Keep this in mind!
; The status window showing the copy is enabled
;
; Portable application template created 2006 by Karl Loncarek, version 1.4.1 - 2006/11/30,
; modified by Bruno Soares Pasin and Francisco Ernesto Teixeira for heidisql.com
; License of this template see the respective readme.txt.
; **************************************************************************
; **************************************************************************
; * Define constants
; **************************************************************************
!define AUTHOR "HeidiSQL Team"
!define APP "HeidiSQL"
!define VER "1.0.0.0"
!define APPVER "4.0"
!define EXE "heidisql.exe"
!define PNAME "${App}Portable"
!define ICON "..\..\res\mainicon.ico"
!define SPLASHIMAGE "${PNAME}.bmp"
!define REGKEYS "HKEY_CURRENT_USER\Software\HeidiSQL"
!define INI "${PNAME}.ini"
; **************************************************************************
; * Includes
; **************************************************************************
!include "Registry.nsh"
!include "WordFunc.nsh"
!insertmacro "WordFind"
!include "FileFunc.nsh"
!insertmacro "GetParameters"
; **************************************************************************
; * Runtime Switches
; **************************************************************************
CRCCheck On
WindowIcon Off
SilentInstall Silent
AutoCloseWindow True
; **************************************************************************
; * Define variables
; **************************************************************************
Var ACTION
Var ACTIONDIRECTORY
Var ACTIONPARAMETERS
Var SPLASHSCREEN
Var PROGRAMEXE
Var PROGRAMDIR
Var PROGRAMPARMS
Var DATADIR
Var INIFILE
Var SECONDLAUNCH
; **************************************************************************
; * Set basic information
; **************************************************************************
Name "${APP} Portable"
!ifdef ICON
Icon "${ICON}"
!endif
Caption "${APP} Portable - ${VER}"
OutFile "${PNAME}.exe"
; **************************************************************************
; * Set version information
; **************************************************************************
LoadLanguageFile "${NSISDIR}\Contrib\Language files\English.nlf"
VIProductVersion "${Ver}"
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "${APP} ${APPVER} Portable"
VIAddVersionKey /LANG=${LANG_ENGLISH} "Comments" "Allow ${APP} to be run from a removeable drive."
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "<EFBFBD> ${AUTHOR}"
VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "by ${AUTHOR}"
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "${APP} ${APPVER} Portable"
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "${VER}"
VIAddVersionKey /LANG=${LANG_ENGLISH} "OriginalFilename" "${PNAME}.exe"
; **************************************************************************
; * Function: Other initialisations before launch of program
; **************************************************************************
Function Init
FunctionEnd
; **************************************************************************
; * Function: Other things that have to be cleaned up after end of the program
; **************************************************************************
Function CleanUp
FunctionEnd
; **************************************************************************
; * Function: Initialize working variables
; **************************************************************************
Function InitVariables
; --------------------------------------------------------------------------
; Check whether an INI file exists, set variable pointing to it
; --------------------------------------------------------------------------
IfFileExists "$EXEDIR\${INI}" "" CheckPortableINI
StrCpy "$INIFILE" "$EXEDIR\${INI}"
Goto ReadINIFile
CheckPortableINI:
IfFileExists "$EXEDIR\${PNAME}\${INI}" "" CheckPortableAppsINI
StrCpy "$INIFILE" "$EXEDIR\${PNAME}\${INI}"
Goto ReadINIFile
CheckPortableAppsINI:
IfFileExists "$EXEDIR\PortableApps\${PNAME}\${INI}" "" CheckAppsINI
StrCpy "$INIFILE" "$EXEDIR\PortableApps\${PNAME}\${INI}"
Goto ReadINIFile
CheckAppsINI:
IfFileExists "$EXEDIR\Apps\${PNAME}\${INI}" "" CheckDataINI
StrCpy "$INIFILE" "$EXEDIR\Apps\${PNAME}\${INI}"
Goto ReadINIFile
CheckDataINI:
IfFileExists "$EXEDIR\Data\${PNAME}\${INI}" "" NoINIFile
StrCpy "$INIFILE" "$EXEDIR\Data\${PNAME}\${INI}"
Goto ReadINIFile
Goto NoINIFile
; --------------------------------------------------------------------------
; Read content of the INI file
; --------------------------------------------------------------------------
ReadINIFile:
ReadINIStr $0 "$INIFILE" "${PNAME}" "ProgramDirectory"
StrCmp $0 "" NoINIFile ; if emtpy retrieve correct setting
StrCpy "$PROGRAMDIR" "$EXEDIR\$0" ; save program directory
ReadINIStr $0 "$INIFILE" "${PNAME}" "DataDirectory"
StrCmp $0 "" NoINIFile ; if empty retrieve correct setting
StrCpy "$DATADIR" "$EXEDIR\$0" ; save data directory
ReadINIStr $0 "$INIFILE" "${PNAME}" "ProgramExecutable"
StrCpy "$PROGRAMEXE" "$0" ; save .exe name
StrCmp $0 "" "" Splash ; if emtpy use default
StrCpy "$PROGRAMEXE" "${EXE}" ; set default value
Splash:
ReadINIStr $0 "$INIFILE" "${PNAME}" "SplashScreen"
StrCpy "$SPLASHSCREEN" "$0" ; save state of splashscreen display
StrCmp "$SPLASHSCREEN" "" "" ProgramParameters ; check whether variable splashscreen was empty
StrCpy "$SPLASHSCREEN" "enabled" ; set to default
ProgramParameters:
ReadINIStr $0 "$INIFILE" "${PNAME}" "ProgramParameters"
StrCpy "$PROGRAMPARMS" "$0" ; save additional program parameters
Goto InitVarEnd ; finished reading the INI file
NoINIFile: ; default settings for all the variables
; --------------------------------------------------------------------------
; Set default values for variables
; --------------------------------------------------------------------------
StrCpy "$PROGRAMEXE" "${EXE}" ; use default setting
StrCpy "$PROGRAMPARMS" ""
StrCpy "$SPLASHSCREEN" "enabled" ; enable splashscreen
; --------------------------------------------------------------------------
; Check which directory configuration is used and set variables accordingly
; --------------------------------------------------------------------------
IfFileExists "$EXEDIR\App\${APP}\$PROGRAMEXE" "" CheckPortableDIR
StrCpy "$PROGRAMDIR" "$EXEDIR\App\${APP}"
StrCpy "$DATADIR" "$EXEDIR\Data"
Goto InitVarEnd
CheckPortableDIR:
IfFileExists "$EXEDIR\${PNAME}\App\${APP}\$PROGRAMEXE" "" CheckPortableAppsDIR
StrCpy "$PROGRAMDIR" "$EXEDIR\${PNAME}\App\${APP}"
StrCpy "$DATADIR" "$EXEDIR\${PNAME}\Data"
Goto InitVarEnd
CheckPortableAppsDIR:
IfFileExists "$EXEDIR\PortableApps\${PNAME}\App\${APP}\$PROGRAMEXE" "" CheckAppsDIR
StrCpy "$PROGRAMDIR" "$EXEDIR\PortableApps\${PNAME}\App\${APP}"
StrCpy "$DATADIR" "$EXEDIR\PortableApps\${PNAME}\Data"
Goto InitVarEnd
CheckAppsDIR:
IfFileExists "$EXEDIR\Apps\${PNAME}\${APP}\$PROGRAMEXE" "" NoDIR
StrCpy "$PROGRAMDIR" "$EXEDIR\Apps\${PNAME}\${APP}"
StrCpy "$DATADIR" "$EXEDIR\Data\${PNAME}"
Goto InitVarEnd
NoDIR:
; --------------------------------------------------------------------------
; No allowed pathconfiguration was found
; --------------------------------------------------------------------------
MessageBox MB_OK|MB_ICONEXCLAMATION `$PROGRAMEXE was not found. Please check your configuration`
Abort ; terminate launcher
InitVarEnd: ;simly the end of the function
FunctionEnd
; **************************************************************************
; * Function: Work with registry keys or trees (backup, restore, delete)
; **************************************************************************
Function DoAction
StrCmp "$ACTIONPARAMETERS" "" AfterLoop ; if no parameters provided leave immediately
StrCpy "$R8" "0" ; reset counter
StrCpy "$R2" "$ACTION" 6 # ; get only first 6 characters of the required action
StrCmp "$R2" "Backup" "" GoOn ; backup requires existing directory
IfFileExists "$ACTIONDIRECTORY\*.*" GoOn ; create backup directory if not existant
CreateDirectory $ACTIONDIRECTORY
GoOn:
StrCpy "$R0" "$ACTIONPARAMETERS" ; copy constant to working register
Loop:
; --------------------------------------------------------------------------
; Get single parameter out of list
; --------------------------------------------------------------------------
StrCmp "$R0" "" AfterLoop ; do not do registry parsing, when no keys given anymore
IntOp $R8 $R8 + 1 ; increase counter
${WordFind} "$R0" "||" "+01" $R9 ; save first parameter to register
${WordFind} "$R0" "||" "+02*}" $R0 ; remove first part from saved value
StrCmp "$R0" "$R9" LastLoop ; if register values are identical -> no more delimiters
Goto DoWork ; do not delete value list
LastLoop:
StrCpy "$R0" "" ; if no delimiter available anymore empty working variable
; --------------------------------------------------------------------------
;Decide what to do with parameter
; --------------------------------------------------------------------------
DoWork:
StrCpy "$R2" "$ACTION" "" -4 # ; get last 7 characters of action variable
!ifdef REGKEYS
StrCmp "$R2" "Keys" DoWorkRegistry ; actions should be performed on the registry
!endif
!ifdef SETTINGSFILES
StrCmp "$R2" "File" DoWorkFiles ; actions should be performed on files
!endif
!ifdef SETTINGSDIRS
StrCmp "$R2" "Dirs" DoWorkDirectory ; actions should be performed on directories
!endif
Goto Continue ; something else undefined
; --------------------------------------------------------------------------
; Do action on registry keys
; --------------------------------------------------------------------------
!ifdef REGKEYS
DoWorkRegistry:
StrCmp "$ACTION" "BackupKeys" BackupRegistryKey ; do backup of registry key
StrCmp "$ACTION" "RestoreKeys" RestoreRegistryKey ; restore registry key, i.e. write them to the registry
StrCmp "$ACTION" "DeleteKeys" DeleteRegistryKey ; delete registry key from registry
Goto Continue ; something else undefined
BackupRegistryKey:
${registry::KeyExists} "$R9" $R7 ; check whether registry key exists
StrCmp "$R7" "0" 0 Continue ; registry key does not exist, do not save anything
${registry::SaveKey} "$R9" "$ACTIONDIRECTORY\RegKey$R8.reg" "/G=1" $R7 ; Backup registry key
Sleep 50
Goto Continue
RestoreRegistryKey:
IfFileExists "$ACTIONDIRECTORY\RegKey$R8.reg" 0 Continue ; only restore if a registry file exists
${registry::RestoreKey} "$ACTIONDIRECTORY\RegKey$R8.reg" $R7 ; Restore saved registry key
Sleep 50
Goto Continue
DeleteRegistryKey:
${registry::DeleteKey} "$R9" $R7 ; Delete registry key
Sleep 50
Goto Continue
!endif
; --------------------------------------------------------------------------
; Do action on files
; --------------------------------------------------------------------------
!ifdef SETTINGSFILES
DoWorkFiles:
StrCmp "$ACTION" "BackupFile" BackupFile ; do backup of file
StrCmp "$ACTION" "RestoreFile" RestoreFile ; restores saved file, i.e. write it to host computer
StrCmp "$ACTION" "DeleteFile" DeleteFile ; delete file from hostcomputer
BackupFile:
IfFileExists "$R9" 0 Continue ; check whether file exists
CopyFiles "$R9" "$ACTIONDIRECTORY\File$R8.dat" ; backup file
Goto Continue
RestoreFile:
IfFileExists "$ACTIONDIRECTORY\File$R8.dat" 0 Continue ; only restore when available
CopyFiles "$ACTIONDIRECTORY\File$R8.dat" "$R9" ; restore file
Goto Continue
DeleteFile:
Delete "$R9" ; delete file
Goto Continue
!endif
; --------------------------------------------------------------------------
; Do action on directories
; --------------------------------------------------------------------------
!ifdef SETTINGSDIRS
DoWorkDirectory:
StrCmp "$ACTION" "BackupDirs" BackupDirectory ; do backup of directory
StrCmp "$ACTION" "RestoreDirs" RestoreDirectory ; restores saved directory, i.e. write it to host computer
StrCmp "$ACTION" "DeleteDirs" DeleteDirectory ; delete directory from hostcomputer
BackupDirectory:
IfFileExists "$R9\*.*" 0 Continue ; check whether source directory exists
IfFileExists "$ACTIONDIRECTORY\Dir$R8.dat" +2 0 ; does target directory exist?
CreateDirectory "$ACTIONDIRECTORY\Dir$R8.dat" ; create target directory
CopyFiles "$R9\*.*" "$ACTIONDIRECTORY\Dir$R8.dat" ; backup directory
Goto Continue
RestoreDirectory:
IfFileExists "$ACTIONDIRECTORY\Dir$R8.dat\*.*" 0 Continue ; check whether backup exists
IfFileExists "$R9\*.*" +2 0 ; does target directory exist
CreateDirectory "$R9" ; create target directory
CopyFiles "$ACTIONDIRECTORY\Dir$R8.dat\*.*" "$R9" ; restore directories
Goto Continue
DeleteDirectory:
RMDir "/r" "$R9" ; delete directory
Goto Continue
!endif
; --------------------------------------------------------------------------
; End of Loop
; --------------------------------------------------------------------------
Continue:
Goto Loop
AfterLoop:
FunctionEnd
; **************************************************************************
; * Function: Check whether EXE exists is launched a second time etc.
; **************************************************************************
Function CheckEXE
IfFileExists "$PROGRAMDIR\$PROGRAMEXE" FoundEXE
; Program executable not where expected
MessageBox MB_OK|MB_ICONEXCLAMATION `$PROGRAMEXE was not found. Please check your configuration!`
Abort
FoundEXE: ; Check if already running and set variable
FindProcDLL::FindProc "$PROGRAMEXE"
StrCmp $R0 "1" "" EndEXE
StrCpy $SECONDLAUNCH "true"
EndEXE:
FunctionEnd
; **************************************************************************
; * Main section
; **************************************************************************
Section "Main"
; --------------------------------------------------------------------------
; Initialize variables, read INI etc.
; --------------------------------------------------------------------------
Call InitVariables
; --------------------------------------------------------------------------
; Do some EXE checking
; --------------------------------------------------------------------------
Call CheckEXE
; --------------------------------------------------------------------------
; Display Splashscreen when available
; --------------------------------------------------------------------------
!ifdef SPLASHIMAGE
StrCmp "$SPLASHSCREEN" "enabled" 0 NoSplash
InitPluginsDir
File /oname=$PLUGINSDIR\splash.bmp "${SPLASHIMAGE}"
advsplash::show 1000 600 400 -1 $PLUGINSDIR\splash
NoSplash:
!endif
StrCmp $SECONDLAUNCH "true" SimplyStartProgram
; --------------------------------------------------------------------------
; Backup existing, replace with saved registry keys
; --------------------------------------------------------------------------
!ifdef REGKEYS
StrCpy "$ACTIONPARAMETERS" "${REGKEYS}" ; hand over parameters list
StrCpy "$ACTIONDIRECTORY" "$DATADIR\RegistryBackup" ; define where to backup keys
StrCpy "$ACTION" "BackupKeys" ; backup existing registry keys
Call DoAction ; just do it
; StrCpy "$ACTION" "DeleteKeys" ; delete existing registry keys
; Call DoAction
StrCpy "$ACTIONDIRECTORY" "$DATADIR\Registry" ; define where local keys are
StrCpy "$ACTION" "RestoreKeys" ;restore saved keys
Call DoAction ; just do it
!endif
; --------------------------------------------------------------------------
; Backup existing, replace with saved settings files
; --------------------------------------------------------------------------
!ifdef SETTINGSFILES
StrCpy "$ACTIONPARAMETERS" "${SETTINGSFILES}" ; hand over parameters list
StrCpy "$ACTIONDIRECTORY" "$DATADIR\SettingsBackup" ; define where to save files
StrCpy "$ACTION" "BackupFile" ; define action
Call DoAction ; just do it
StrCpy "$ACTIONDIRECTORY" "$DATADIR\Settings" ; define where local files are
StrCpy "$ACTION" "RestoreFile" ; define action
Call DoAction ; just do it
!endif
; --------------------------------------------------------------------------
; Backup existing settings directories
; --------------------------------------------------------------------------
!ifdef SETTINGSDIRS
StrCpy "$ACTIONPARAMETERS" "${SETTINGSDIRS}" ; hand over parameters list
StrCpy "$ACTIONDIRECTORY" "$DATADIR\SettingsBackup" ; define where to save directories
StrCpy "$ACTION" "BackupDirs" ; define action
Call DoAction ; just do it
StrCpy "$ACTIONDIRECTORY" "$DATADIR\Settings" ; define where local directories are
StrCpy "$ACTION" "RestoreDirs" ; define action
Call DoAction ; just do it
!endif
; --------------------------------------------------------------------------
; Other changes before start
; --------------------------------------------------------------------------
Call Init
; --------------------------------------------------------------------------
; Start program
; --------------------------------------------------------------------------
${GetParameters} $R0 ; obtain eventually provided commandline parameters
ExecWait "$PROGRAMDIR\$PROGRAMEXE $PROGRAMPARMS $R0" ; run program
; --------------------------------------------------------------------------
; Other clean up action after program has run
; --------------------------------------------------------------------------
Call CleanUp
; --------------------------------------------------------------------------
; backup and restore or clean up settings directories
; --------------------------------------------------------------------------
!ifdef SETTINGSDIRS
StrCpy "$ACTIONPARAMETERS" "${SETTINGSDIRS}" ; hand over parameters list
StrCpy "$ACTIONDIRECTORY" "$DATADIR\Settings" ; define where local directories are
StrCpy "$ACTION" "BackupDirs" ; define action
Call DoAction ; just do it
StrCpy "$ACTION" "DeleteDirs" ; delete directories on host computer
Call DoAction ; just do it
StrCpy "$ACTIONDIRECTORY" "$DATADIR\SettingsBackup" ; define where to save directories
StrCpy "$ACTION" "RestoreDirs" ; define action
Call DoAction ; just do it
!endif
; --------------------------------------------------------------------------
; backup and restore or clean up settings files
; --------------------------------------------------------------------------
!ifdef SETTINGSFILES
StrCpy "$ACTIONPARAMETERS" "${SETTINGSFILES}" ; hand over parameters list
StrCpy "$ACTIONDIRECTORY" "$DATADIR\Settings" ; define where local files are
StrCpy "$ACTION" "BackupFile" ; define action
Call DoAction ; just do it
StrCpy "$ACTION" "DeleteFile" ; delete files on host computer
Call DoAction ; just do it
StrCpy "$ACTIONDIRECTORY" "$DATADIR\SettingsBackup" ; define where to save directories
StrCpy "$ACTION" "RestoreFile" ; define action
Call DoAction ; just do it
!endif
; --------------------------------------------------------------------------
; backup and restore or clean up registry keys
; --------------------------------------------------------------------------
!ifdef REGKEYS
StrCpy "$ACTIONPARAMETERS" "${REGKEYS}" ; hand over parameters list
StrCpy "$ACTIONDIRECTORY" "$DATADIR\Registry" ; define where local keys are
StrCpy "$ACTION" "BackupKeys" ; backup existing registry keys
Call DoAction ; just do it
StrCpy "$ACTION" "DeleteKeys" ; delete registry keys on host computer
Call DoAction ; just do it
sleep 500 ; let deletion of registry keys finish
StrCpy "$ACTIONDIRECTORY" "$DATADIR\RegistryBackup" ; define where to backup keys
StrCpy "$ACTION" "RestoreKeys" ;restore saved keys
Call DoAction ; just do it
sleep 1000 ; let registry writing finish (necessary before deleting backup file)
!endif
${registry::Unload}
; --------------------------------------------------------------------------
; remove saved backups
; --------------------------------------------------------------------------
RMDir "/r" "$DATADIR\SettingsBackup"
RMDir "/r" "$DATADIR\RegistryBackup"
Goto EndOfCode
; --------------------------------------------------------------------------
; run application directly without doing anything else, as it is already running
; --------------------------------------------------------------------------
SimplyStartProgram:
${GetParameters} $R0 ; obtain eventually provided commandline parameters
Exec "$PROGRAMDIR\$PROGRAMEXE $PROGRAMPARMS $R0" ; run program
${registry::Unload}
EndOfCode:
SectionEnd

View File

@ -1,43 +0,0 @@
HeidiSQL Portable Launcher 1.0.0.0
==================================
Website: http://www.heidisql.com/
This software is OSI Certified Open Source Software.
OSI Certified is a certification mark of the Open Source Initiative.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
ABOUT HEIDISQL PORTABLE
=======================
The HeidiSQL Portable Launcher allows you to run HeidiSQL from a removable drive whose letter changes as you move it to another computer. The program can be entirely self-contained on the drive and then used on any Windows computer.
The HeidiSQL Portable Launcher is based on template created by Karl Loncarek and modified by Bruno Soares Pasin.
LICENSE
=======
This code is released under the GPL. The full code is included with this package as HeidiSQLPortable.nsi.
INSTALLATION / DIRECTORY STRUCTURE
==================================
By default, the program expects one of these directory structures:
-\ <--- Directory with HeidiSQlPortable.exe
+\App\
+\HeidiSQL\
+\Data\
+\Registry\

View File

@ -1,75 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docname="usb.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs4">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective10" />
<inkscape:perspective
id="perspective2390"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 526.18109 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="0.50362889"
inkscape:cx="372.04724"
inkscape:cy="526.18109"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1014"
inkscape:window-height="725"
inkscape:window-x="0"
inkscape:window-y="0" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 372.04724,291.39307 L 322.49075,373.71819 L 353.80658,374.04104 L 353.80658,578.56248 L 317.32525,542.72683 L 318.61662,515.93081 C 327.71033,509.28034 333.62885,498.51146 333.62885,486.39062 C 333.62885,466.21563 317.32251,449.74782 297.14752,449.74787 C 276.97253,449.74787 260.50477,466.21563 260.50477,486.39062 C 260.50477,502.29643 270.84718,515.75405 285.04089,520.77347 L 284.07236,551.44361 L 353.80658,625.69764 L 353.80658,648.61954 C 330.71293,656.13544 313.93539,677.75109 313.93539,703.34154 C 313.93539,735.15594 339.74857,760.96907 371.56298,760.96912 C 403.37738,760.96912 429.19057,735.15594 429.19057,703.34154 C 429.19057,678.11882 413.02808,656.75029 390.44933,648.94239 L 390.44933,582.27518 L 461.47493,506.89119 L 462.12061,464.7601 L 483.58972,464.7601 L 483.58972,392.60455 L 411.43417,392.60455 L 411.43417,464.7601 L 429.51341,464.7601 L 429.99767,496.39877 L 390.44933,535.14001 L 390.44933,374.5253 L 421.76516,374.84815 L 372.04724,291.39307 z"
id="rect2400" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

File diff suppressed because it is too large Load Diff

View File

@ -292,7 +292,7 @@ begin
i := 0;
NewName := 'Unnamed';
while MainReg.KeyExists(REGPATH + REGKEY_SESSIONS + NewName) do begin
while MainReg.KeyExists(RegPath + REGKEY_SESSIONS + NewName) do begin
inc(i);
NewName := 'Unnamed-' + IntToStr(i);
end;
@ -314,7 +314,7 @@ var
begin
if MessageDlg('Delete session "' + SelectedSession + '" ?', mtConfirmation, [mbYes, mbCancel], 0) = mrYes then
begin
SessionKey := REGPATH + REGKEY_SESSIONS + SelectedSession;
SessionKey := RegPath + REGKEY_SESSIONS + SelectedSession;
if MainReg.KeyExists(SessionKey) then
MainReg.DeleteKey(SessionKey);
FSessionNames.Delete(FSessionNames.IndexOf(SelectedSession));
@ -345,7 +345,7 @@ end;
procedure Tconnform.RefreshSessionList;
begin
// Refresh list of session names
MainReg.OpenKey(REGPATH + REGKEY_SESSIONS, True);
MainReg.OpenKey(RegPath + REGKEY_SESSIONS, True);
FSessionNames.BeginUpdate;
MainReg.GetKeyNames(FSessionNames);
FSessionNames.EndUpdate;
@ -398,7 +398,7 @@ begin
OpenRegistry;
SessionFocused := Assigned(Node);
if SessionFocused then begin
SessionExists := MainReg.KeyExists(REGPATH + REGKEY_SESSIONS + SelectedSession);
SessionExists := MainReg.KeyExists(RegPath + REGKEY_SESSIONS + SelectedSession);
if SessionExists then begin
OpenRegistry(SelectedSession);
FOrgNetType := GetRegValue(REGNAME_NETTYPE, DEFAULT_NETTYPE, SelectedSession);
@ -470,7 +470,7 @@ begin
lblCounterRight.Enabled := False;
if (not Assigned(ListSessions.FocusedNode))
or (not MainReg.KeyExists(REGPATH + REGKEY_SESSIONS + SelectedSession)) then
or (not MainReg.KeyExists(RegPath + REGKEY_SESSIONS + SelectedSession)) then
Exit;
DummyDate := StrToDateTime('2000-01-01');
@ -517,9 +517,9 @@ begin
MessageDLG('Session "'+NewText+'" already exists!', mtError, [mbCancel], 0);
NewText := SelectedSession;
end else begin
SessionKey := REGPATH + REGKEY_SESSIONS + SelectedSession;
SessionKey := RegPath + REGKEY_SESSIONS + SelectedSession;
if MainReg.KeyExists(SessionKey) then
MainReg.MoveKey(SessionKey, REGPATH + REGKEY_SESSIONS + NewText, true);
MainReg.MoveKey(SessionKey, RegPath + REGKEY_SESSIONS + NewText, true);
// Also fix internal session name in main form, which gets used to store e.g. "lastuseddb" later
if Mainform.SessionName = SelectedSession then begin
Mainform.SessionName := NewText;

View File

@ -21,7 +21,6 @@ const
// General things
APPNAME = 'HeidiSQL';
APPDOMAIN = 'http://www.heidisql.com/';
REGPATH = '\Software\' + APPNAME + '\';
REGKEY_SESSIONS = 'Servers\';
// Some unique char, used to separate e.g. selected columns in registry
DELIM = '|';

View File

@ -250,9 +250,11 @@ type
function KeyPressed(Code: Integer): Boolean;
function GeneratePassword(Len: Integer): String;
procedure InvalidateVT(VT: TVirtualStringTree; RefreshTag: Integer; ImmediateRepaint: Boolean);
procedure HandlePortableSettings(StartupMode: Boolean);
var
MainReg: TRegistry;
RegPath: String = '\Software\' + APPNAME + '\';
MutexHandle: THandle = 0;
dbgCounter: Integer = 0;
DecimalSeparatorSystemdefault: Char;
@ -2593,9 +2595,11 @@ procedure OpenRegistry(Session: String = '');
var
folder : String;
begin
if MainReg = nil then
if MainReg = nil then begin
MainReg := TRegistry.Create;
folder := REGPATH;
HandlePortableSettings(True);
end;
folder := RegPath;
if Session <> '' then
folder := folder + REGKEY_SESSIONS + Session;
if MainReg.CurrentPath <> folder then
@ -2619,7 +2623,7 @@ end;
Read a boolean preference value from registry
@param string Name of the value
@param boolean Default-value to return if valueName was not found
@param string Subkey of REGPATH where to search for the value
@param string Subkey of RegPath where to search for the value
}
function GetRegValue( valueName: String; defaultValue: Boolean; Session: String = '' ) : Boolean;
begin
@ -3456,6 +3460,108 @@ begin
end;
procedure HandlePortableSettings(StartupMode: Boolean);
var
Content, FileName, Name, Value, KeyPath: String;
Lines, Segments: TStringList;
i: Integer;
DataType: TRegDataType;
const
Chr10Replacement = '<}}}>';
Chr13Replacement = '<{{{>';
Delimiter = '<|||>';
procedure ReadKeyToContent(Path: String);
var
Names: TStringList;
i: Integer;
SubPath: String;
begin
MainReg.OpenKeyReadOnly(Path);
SubPath := Copy(Path, Length(RegPath)+1, MaxInt);
Names := TStringList.Create;
MainReg.GetValueNames(Names);
for i:=0 to Names.Count-1 do begin
DataType := MainReg.GetDataType(Names[i]);
Content := Content +
SubPath + Names[i] + Delimiter +
IntToStr(Integer(DataType)) + Delimiter;
case DataType of
rdString: begin
Value := MainReg.ReadString(Names[i]);
Value := StringReplace(Value, #13, Chr13Replacement, [rfReplaceAll]);
Value := StringReplace(Value, #10, Chr10Replacement, [rfReplaceAll]);
end;
rdInteger:
Value := IntToStr(MainReg.ReadInteger(Names[i]));
rdBinary, rdUnknown, rdExpandString:
MessageDlg(Names[i]+' has an unsupported data type.', mtError, [mbOK], 0);
end;
Content := Content + Value + CRLF;
end;
Names.Clear;
MainReg.GetKeyNames(Names);
for i:=0 to Names.Count-1 do
ReadKeyToContent(Path + Names[i] + '\');
Names.Free;
end;
begin
// Export registry keys and values into textfile, for portable reasons
FileName := ExtractFilePath(ParamStr(0)) + 'portable_settings.txt';
if not FileExists(FileName) then
Exit;
// Open the right key
if StartupMode then
RegPath := '\Software\' + APPNAME + ' Portable '+IntToStr(GetCurrentThreadId)+'\';
Screen.Cursor := crHourGlass;
try
if StartupMode then begin
Content := ReadTextfile(FileName);
Lines := Explode(CRLF, Content);
for i:=0 to Lines.Count-1 do begin
// Each line has 3 segments: reg path | data type | value
Segments := Explode(Delimiter, Lines[i]);
KeyPath := RegPath + ExtractFilePath(Segments[0]);
Name := ExtractFileName(Segments[0]);
DataType := TRegDataType(StrToInt(Segments[1]));
MainReg.OpenKey(KeyPath, True);
if MainReg.ValueExists(Name) then
Continue; // Don't touch value if already there
Value := '';
if Segments.Count >= 3 then
Value := Segments[2];
case DataType of
rdString: begin
Value := StringReplace(Value, Chr13Replacement, #13, [rfReplaceAll]);
Value := StringReplace(Value, Chr10Replacement, #10, [rfReplaceAll]);
MainReg.WriteString(Name, Value);
end;
rdInteger:
MainReg.WriteInteger(Name, MakeInt(Value));
rdBinary, rdUnknown, rdExpandString:
MessageDlg(Name+' has an unsupported data type.', mtError, [mbOK], 0);
end;
Segments.Free;
end;
Lines.Free;
end else begin
// Application closes: Recursively read values in keys and their subkeys into textfile
ReadKeyToContent(RegPath);
SaveUnicodeFile(FileName, Content);
MainReg.CloseKey;
MainReg.DeleteKey(RegPath);
end;
except
On E:Exception do
MessageDlg(E.Message, mtError, [mbOK], 0);
end;
Screen.Cursor := crDefault;
end;
end.

View File

@ -1176,6 +1176,8 @@ begin
deletefile(filename+'bmp');
if MainReg <> nil then begin
MainReg.CloseKey;
// Export settings into textfile in portable mode.
HandlePortableSettings(False);
MainReg.Free;
end;
end;

View File

@ -186,7 +186,7 @@ begin
comboExportOutputTarget.Text := '';
// Add session names from registry
SessionNames := TStringList.Create;
MainReg.OpenKey(REGPATH + REGKEY_SESSIONS, True);
MainReg.OpenKey(RegPath + REGKEY_SESSIONS, True);
MainReg.GetKeyNames(SessionNames);
for i:=0 to SessionNames.Count-1 do begin
if SessionNames[i] <> Mainform.SessionName then