mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-26 11:17:57 +08:00
Use home brown file format for exporting and importing registry settings, as used for portable_settings.txt. Registry dumps cannot be imported into a separate registry key for a portable instance, which is hereby fixed, see http://www.heidisql.com/forum.php?t=10503 .
This commit is contained in:
@ -17,6 +17,9 @@ const
|
||||
REGKEY_QUERYHISTORY = 'QueryHistory';
|
||||
// Some unique char, used to separate e.g. selected columns in registry
|
||||
DELIM = '|';
|
||||
CHR10REPLACEMENT = '<}}}>';
|
||||
CHR13REPLACEMENT = '<{{{>';
|
||||
DELIMITER = '<|||>';
|
||||
|
||||
// Used by maskSQL and fixSQL:
|
||||
SQL_VERSION_ANSI = -1;
|
||||
|
@ -192,6 +192,8 @@ type
|
||||
function GeneratePassword(Len: Integer): String;
|
||||
procedure InvalidateVT(VT: TVirtualStringTree; RefreshTag: Integer; ImmediateRepaint: Boolean);
|
||||
procedure HandlePortableSettings(StartupMode: Boolean);
|
||||
procedure ImportSettings(Filename: String);
|
||||
procedure ExportSettings(Filename: String);
|
||||
function CharAtPos(Str: String; Pos: Integer): Char;
|
||||
function CompareAnyNode(Text1, Text2: String): Integer;
|
||||
function StringListCompareAnythingAsc(List: TStringList; Index1, Index2: Integer): Integer;
|
||||
@ -2192,20 +2194,51 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
procedure HandlePortableSettings(StartupMode: Boolean);
|
||||
procedure ImportSettings(Filename: String);
|
||||
var
|
||||
Content, FileName, Name, Value, KeyPath: String;
|
||||
Lines, Segments, AllKeys: TStringList;
|
||||
Content, Name, Value, KeyPath: String;
|
||||
Lines, Segments: TStringList;
|
||||
i: Integer;
|
||||
DataType: TRegDataType;
|
||||
Proc: TProcessEntry32;
|
||||
ProcRuns: Boolean;
|
||||
SnapShot: THandle;
|
||||
rx: TRegExpr;
|
||||
const
|
||||
Chr10Replacement = '<}}}>';
|
||||
Chr13Replacement = '<{{{>';
|
||||
Delimiter = '<|||>';
|
||||
begin
|
||||
// Load registry settings from file
|
||||
Content := ReadTextfile(FileName, nil);
|
||||
Lines := Explode(CRLF, Content);
|
||||
for i:=0 to Lines.Count-1 do begin
|
||||
// Each line has 3 segments: reg path | data type | value. Continue if explode finds less or more than 3.
|
||||
Segments := Explode(DELIMITER, Lines[i]);
|
||||
if Segments.Count <> 3 then
|
||||
continue;
|
||||
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:
|
||||
ErrorDialog(Name+' has an unsupported data type.');
|
||||
end;
|
||||
Segments.Free;
|
||||
end;
|
||||
Lines.Free;
|
||||
end;
|
||||
|
||||
|
||||
procedure ExportSettings(Filename: String);
|
||||
var
|
||||
Content, Value: String;
|
||||
DataType: TRegDataType;
|
||||
|
||||
procedure ReadKeyToContent(Path: String);
|
||||
var
|
||||
@ -2213,20 +2246,21 @@ const
|
||||
i: Integer;
|
||||
SubPath: String;
|
||||
begin
|
||||
MainReg.OpenKeyReadOnly(Path);
|
||||
// Recursively read values in keys and their subkeys into "content" variable
|
||||
MainReg.OpenKey(Path, True);
|
||||
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;
|
||||
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]);
|
||||
Value := StringReplace(Value, #13, CHR13REPLACEMENT, [rfReplaceAll]);
|
||||
Value := StringReplace(Value, #10, CHR10REPLACEMENT, [rfReplaceAll]);
|
||||
end;
|
||||
rdInteger:
|
||||
Value := IntToStr(MainReg.ReadInteger(Names[i]));
|
||||
@ -2241,6 +2275,24 @@ const
|
||||
ReadKeyToContent(Path + Names[i] + '\');
|
||||
Names.Free;
|
||||
end;
|
||||
|
||||
begin
|
||||
// Save registry settings to file
|
||||
Content := '';
|
||||
ReadKeyToContent(RegPath);
|
||||
SaveUnicodeFile(FileName, Content);
|
||||
end;
|
||||
|
||||
|
||||
procedure HandlePortableSettings(StartupMode: Boolean);
|
||||
var
|
||||
FileName: String;
|
||||
AllKeys: TStringList;
|
||||
i: Integer;
|
||||
Proc: TProcessEntry32;
|
||||
ProcRuns: Boolean;
|
||||
SnapShot: THandle;
|
||||
rx: TRegExpr;
|
||||
begin
|
||||
// Export registry keys and values into textfile, for portable reasons
|
||||
|
||||
@ -2270,41 +2322,12 @@ begin
|
||||
|
||||
Screen.Cursor := crHourGlass;
|
||||
try
|
||||
// Both ImportSettings and ExportSettings rely on RegPath pointing to the right reg key
|
||||
if StartupMode then begin
|
||||
Content := ReadTextfile(FileName, nil);
|
||||
Lines := Explode(CRLF, Content);
|
||||
for i:=0 to Lines.Count-1 do begin
|
||||
// Each line has 3 segments: reg path | data type | value. Continue if explode finds less or more than 3.
|
||||
Segments := Explode(Delimiter, Lines[i]);
|
||||
if Segments.Count <> 3 then
|
||||
continue;
|
||||
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:
|
||||
ErrorDialog(Name+' has an unsupported data type.');
|
||||
end;
|
||||
Segments.Free;
|
||||
end;
|
||||
Lines.Free;
|
||||
ImportSettings(Filename);
|
||||
end else begin
|
||||
// Application closes: Recursively read values in keys and their subkeys into textfile
|
||||
ReadKeyToContent(RegPath);
|
||||
SaveUnicodeFile(FileName, Content);
|
||||
// Application closes
|
||||
ExportSettings(Filename);
|
||||
MainReg.CloseKey;
|
||||
MainReg.DeleteKey(RegPath);
|
||||
|
||||
|
@ -2577,21 +2577,6 @@ object MainForm: TMainForm
|
||||
OnExecute = actLaunchCommandlineExecute
|
||||
end
|
||||
end
|
||||
object SaveDialog2: TSaveDialog
|
||||
DefaultExt = 'reg'
|
||||
Filter = 'Registry-files (*.reg)|*.reg|All files (*.*)|*.*'
|
||||
Options = [ofOverwritePrompt, ofHideReadOnly, ofEnableSizing]
|
||||
Title = 'Export settings from registry...'
|
||||
Left = 8
|
||||
Top = 128
|
||||
end
|
||||
object OpenDialog2: TOpenDialog
|
||||
DefaultExt = 'reg'
|
||||
Filter = 'Registry-files (*.reg)|*.reg|All files (*.*)|*.*'
|
||||
Title = 'Import settings to registry...'
|
||||
Left = 72
|
||||
Top = 160
|
||||
end
|
||||
object menuConnections: TPopupMenu
|
||||
AutoHotkeys = maManual
|
||||
Images = ImageListMain
|
||||
|
@ -171,10 +171,8 @@ type
|
||||
ToolButton14: TToolButton;
|
||||
actExecuteQuery: TAction;
|
||||
actExecuteSelection: TAction;
|
||||
SaveDialog2: TSaveDialog;
|
||||
ExportSettings1: TMenuItem;
|
||||
Importsettings1: TMenuItem;
|
||||
OpenDialog2: TOpenDialog;
|
||||
menuSupportForum: TMenuItem;
|
||||
actExportData: TAction;
|
||||
actExecuteCurrentQuery: TAction;
|
||||
@ -2203,18 +2201,48 @@ end;
|
||||
|
||||
|
||||
procedure TMainForm.actExportSettingsExecute(Sender: TObject);
|
||||
var
|
||||
Dialog: TSaveDialog;
|
||||
begin
|
||||
// Export settings to .reg-file
|
||||
if SaveDialog2.Execute then
|
||||
ShellExec('regedit.exe', '', '/e "'+SaveDialog2.FileName+'" HKEY_CURRENT_USER'+REGPATH);
|
||||
// Export settings to .txt file
|
||||
Dialog := TSaveDialog.Create(Self);
|
||||
Dialog.Title := 'Export '+APPNAME+' settings to file ...';
|
||||
Dialog.DefaultExt := 'txt';
|
||||
Dialog.Filter := 'Textfiles (*.txt)|*.txt|All files (*.*)|*.*';
|
||||
Dialog.Options := Dialog.Options + [ofOverwritePrompt];
|
||||
if Dialog.Execute then try
|
||||
ExportSettings(Dialog.FileName);
|
||||
MessageDialog('Settings successfully exported to '+Dialog.FileName, mtInformation, [mbOK]);
|
||||
except
|
||||
on E:Exception do
|
||||
ErrorDialog(E.Message);
|
||||
end;
|
||||
Dialog.Free;
|
||||
end;
|
||||
|
||||
|
||||
procedure TMainForm.actImportSettingsExecute(Sender: TObject);
|
||||
var
|
||||
Dialog: TOpenDialog;
|
||||
begin
|
||||
// Import settings from .reg-file
|
||||
if OpenDialog2.Execute then
|
||||
ShellExec('regedit.exe', '', '"'+OpenDialog2.FileName+'"');
|
||||
// Import settings from .txt or .reg file
|
||||
Dialog := TOpenDialog.Create(Self);
|
||||
Dialog.Title := 'Import '+APPNAME+' settings from file ...';
|
||||
Dialog.Filter := 'Textfiles (*.txt)|*.txt|Registry dump, deprecated (*.reg)|*.reg|All files (*.*)|*.*';
|
||||
if Dialog.Execute then try
|
||||
if LowerCase(ExtractFileExt(Dialog.FileName)) = 'reg' then
|
||||
ShellExec('regedit.exe', '', '"'+Dialog.FileName+'"')
|
||||
else begin
|
||||
ImportSettings(Dialog.FileName);
|
||||
MessageDialog('Settings successfully restored from '+Dialog.FileName, mtInformation, [mbOK]);
|
||||
end;
|
||||
except
|
||||
on E:Exception do
|
||||
ErrorDialog(E.Message);
|
||||
end;
|
||||
Dialog.Free;
|
||||
end;
|
||||
|
||||
|
||||
procedure TMainForm.actExecuteQueryExecute(Sender: TObject);
|
||||
var
|
||||
|
Reference in New Issue
Block a user