Aegisub/packages/win_installer/fragment_migrate_code.iss
2021-01-10 03:14:12 -05:00

355 lines
12 KiB
Text

[Code]
var
HasLegacyVersion: Boolean;
LegacyStartMenuFolder: string;
LegacyInstallFolder: string;
LegacyVersionNumber: string;
function OldStartMenuFolder(Param: string): string;
begin
if HasLegacyVersion then
Result := LegacyStartMenuFolder
else
Result := ExpandConstant('{group}');
end;
function OldInstallFolder(Param: string): string;
begin
if HasLegacyVersion then
Result := LegacyInstallFolder
else
Result := ExpandConstant('{app}');
end;
function BoolToStr(x: Boolean): string;
begin
if x then Result := 'Yes' else Result := 'No';
end;
function InitializeSetupMigration: Boolean;
begin
LegacyStartMenuFolder := 'Aegisub';
LegacyInstallFolder := ExpandConstant('{commonpf32}\Aegisub');
LegacyVersionNumber := '1.x';
try
HasLegacyVersion := RegValueExists(HKLM, 'SOFTWARE\Aegisub\info', 'InstVer');
Log(Format('Legacy version found: %s', [BoolToStr(HasLegacyVersion)]));
if RegQueryStringValue(HKLM, 'SOFTWARE\Aegisub\info', 'StartMenuDir', LegacyStartMenuFolder) then
LegacyStartMenuFolder := ExpandConstant('{userprograms}\') + LegacyStartMenuFolder;
Log(Format('Legacy version Start menu folder: %s', [LegacyStartMenuFolder]));
RegQueryStringValue(HKLM, 'SOFTWARE\Aegisub\info', 'InstallDir', LegacyInstallFolder);
Log(Format('Legacy version install folder: %s', [LegacyInstallFolder]));
RegQueryStringValue(HKLM, 'SOFTWARE\Aegisub\info', 'InstVer', LegacyVersionNumber);
except
Log('An exception occurred while trying to detect a legacy installation of Aegisub. Assuming there isn''t one.');
HasLegacyVersion := False;
end;
Result := True;
if HasLegacyVersion then
Result := SuppressibleMsgBox(Format('A previous installation of Aegisub %s has been detected and will be removed along with its configuration.'#13#10#13#10'Continue installing and remove old version?', [LegacyVersionNumber]), mbConfirmation, MB_YESNO, IDYES) = IDYES;
end;
procedure MigrateStyleCatalogs;
var
OldCatalogDir: string;
NewCatalogDir: string;
search: TFindRec;
begin
try
// Upgrade an 1.x style-catalog by moving it to {appdata}
OldCatalogDir := OldInstallFolder('') + '\Catalog\';
Log('-- Migrate style catalogs --');
if DirExists(OldCatalogDir) then
begin
NewCatalogDir := ExpandConstant('{userappdata}\Aegisub\catalog\');
ForceDirectories(NewCatalogDir);
Log('Old style catalog dir: ' + OldCatalogDir);
Log('New catalog dir: ' + NewCatalogDir);
if FindFirst(OldCatalogDir + '*', search) then
try
repeat
Log('Found style catalog: ' + OldCatalogDir + search.Name);
if FileCopy(OldCatalogDir+search.Name, NewCatalogDir+search.Name, True) then
begin
Log('Copied catalog to: ' + NewCatalogDir+search.Name);
DeleteFile(OldCatalogDir+search.Name);
end;
until not FindNext(search);
finally
FindClose(search);
Log('Done migrating styles');
end;
RemoveDir(OldCatalogDir);
end
else
Log('No existing style catalog collection found');
except
Log('An exception occurred while trying to migrate style catalogues.');
end;
end;
procedure UninstallLegacyVersion;
var
page: TOutputProgressWizardPage;
file_list: TStringList;
dir_list: TStringList;
shortcut_list: TStringList;
locale_list: TStringList;
itemsdone, totalitems, i: Integer;
curname: string;
begin
// Uninstall Aegisub 1.x
Log('-- Uninstall legacy version --');
page := CreateOutputProgressPage('Uninstalling old version', 'Your old installation of Aegisub is being removed');
try
page.SetText('Preparing list of files', '');
page.Show;
Log('Load file lists');
ExtractTemporaryFile('legacy_shortcutlist.txt');
ExtractTemporaryFile('legacy_filelist.txt');
ExtractTemporaryFile('legacy_locales.txt');
ExtractTemporaryFile('legacy_dirlist.txt');
shortcut_list := TStringList.Create;
shortcut_list.LoadFromFile(ExpandConstant('{tmp}\legacy_shortcutlist.txt'));
file_list := TStringList.Create;
file_list.LoadFromFile(ExpandConstant('{tmp}\legacy_filelist.txt'));
locale_list := TStringList.Create;
locale_list.LoadFromFile(ExpandConstant('{tmp}\legacy_locales.txt'));
dir_list := TStringList.Create;
dir_list.LoadFromFile(ExpandConstant('{tmp}\legacy_dirlist.txt'));
itemsdone := 0;
totalitems := file_list.Count + dir_list.Count + shortcut_list.Count + locale_list.Count + 3;
// Two extra for the registry keys and one for Start menu folder
for i := 0 to shortcut_list.Count-1 do
begin
try
curname := LegacyStartMenuFolder + '\' + shortcut_list.Strings[i];
// Check that the link points to somewhere in the dir we're installing to so we don't
// delete a shortcut to something else
page.SetText('Removing shortcuts', curname);
if Pos(LegacyInstallFolder, RemoveQuotes(ReadShellLink(curname))) = 1 then
begin
page.SetProgress(itemsdone, totalitems);
Log('Remove shortcut: ' + curname);
if not DeleteFile(curname) then Log('* Deletion failed');
itemsdone := itemsdone + 1;
end
else
Log('Not deleting shortcut, not to old installation: ' + curname);
except
Log('Exception removing shortcut: ' + curname);
end;
end;
page.SetText('Removing Start menu folder', LegacyStartMenuFolder);
page.SetProgress(itemsdone, totalitems);
Log('Remove directory: ' + LegacyStartMenuFolder);
if not RemoveDir(LegacyStartMenuFolder) then Log('* Directory deletion failed');
itemsdone := itemsdone + 1;
for i := 0 to file_list.Count-1 do
begin
curname := LegacyInstallFolder + '\' + file_list.Strings[i];
page.SetText('Removing files', curname);
page.SetProgress(itemsdone, totalitems);
Log('Remove file: ' + curname);
if not DeleteFile(curname) then Log('* Deletion failed');
itemsdone := itemsdone + 1;
end;
for i := 0 to locale_list.Count-1 do
begin
curname := LegacyInstallFolder + '\' + locale_list.Strings[i];
page.SetText('Removing folders', curname);
page.SetProgress(itemsdone, totalitems);
Log('Remove directory recursively: ' + curname);
if not DelTree(curname, True, True, True) then Log('* Tree deletion failed');
itemsdone := itemsdone + 1;
end;
for i := 0 to dir_list.Count-1 do
begin
curname := LegacyInstallFolder + '\' + dir_list.Strings[i];
page.SetText('Removing folders', curname);
page.SetProgress(itemsdone, totalitems);
Log('Remove directory: ' + curname);
if not RemoveDir(curname) then Log('* Directory deletion failed');
itemsdone := itemsdone + 1;
end;
page.SetText('Removing registry entries', 'Installation data');
page.SetProgress(itemsdone, totalitems);
curname := 'SOFTWARE\Aegisub';
Log('Remove reg key: HKLM\' + curname);
if not RegDeleteKeyIncludingSubkeys(HKLM, curname) then Log('* Failed recursively deleting key');
page.SetText('Removing registry entries', 'Uninstaller entry');
page.SetProgress(itemsdone+1, totalitems);
curname := 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Aegisub ' + LegacyVersionNumber;
Log('Remove reg key: HKLM\' + curname);
if not RegDeleteKeyIncludingSubkeys(HKLM, curname) then Log('* Failed recursively deleting key');
page.SetText('Uninstallation complete', '');
page.SetProgress(totalitems, totalitems);
except
Log('An exception occurred while trying to uninstall a legacy version');
finally
shortcut_list.Free;
file_list.Free;
locale_list.Free;
dir_list.Free;
page.Hide;
end;
end;
function SetFileAttributes(lpFileName: WideString; dwFileAttributes: Longint): Boolean;
external 'SetFileAttributesW@kernel32.dll stdcall';
procedure CleanUpOldVersion;
var
StartMenuFolder, InstallFolder: string;
page: TOutputProgressWizardPage;
file_list: TStringList;
dir_list: TStringList;
shortcut_list: TStringList;
locale_list: TStringList;
itemsdone, totalitems, i: Integer;
curname, linktarget: string;
begin
// Clean up from previous Aegisub 2.x installs
Log('-- Clean up old versions --');
page := CreateOutputProgressPage('Cleaning old versions', 'Cleaning up from older versions of Aegisub 2');
try
page.SetText('Preparing list of files', '');
page.Show;
Log('Load file lists');
ExtractTemporaryFile('old_shortcutlist.txt');
ExtractTemporaryFile('old_filelist.txt');
ExtractTemporaryFile('old_locales.txt');
ExtractTemporaryFile('old_dirlist.txt');
shortcut_list := TStringList.Create;
shortcut_list.LoadFromFile(ExpandConstant('{tmp}\old_shortcutlist.txt'));
file_list := TStringList.Create;
file_list.LoadFromFile(ExpandConstant('{tmp}\old_filelist.txt'));
locale_list := TStringList.Create;
locale_list.LoadFromFile(ExpandConstant('{tmp}\old_locales.txt'));
dir_list := TStringList.Create;
dir_list.LoadFromFile(ExpandConstant('{tmp}\old_dirlist.txt'));
itemsdone := 0;
totalitems := file_list.Count + dir_list.Count + shortcut_list.Count + locale_list.Count + 2;
// Two extra:
// - Start menu folder
// - Renaming Aegisub.exe to aegiub32.exe
StartMenuFolder := ExpandConstant('{commonprograms}\Aegisub\');
InstallFolder := ExpandConstant('{app}\');
for i := 0 to shortcut_list.Count-1 do
begin
try
curname := StartMenuFolder + '\' + shortcut_list.Strings[i];
// Check that the link points to somewhere in the dir we're installing to so we don't
// delete a shortcut to something else
page.SetText('Removing shortcuts', curname);
linktarget := ReadShellLink(curname);
if Pos(InstallFolder, RemoveQuotes(linktarget)) = 1 then
begin
page.SetProgress(itemsdone, totalitems);
Log('Remove shortcut: ' + curname);
if not DeleteFile(curname) then Log('* Deletion failed');
itemsdone := itemsdone + 1;
end
else
begin
Log('Not deleting shortcut, not to old installation: ' + curname);
Log('Link target: "' + linktarget + '"; Install folder: "' + InstallFolder + '"');
end;
except
Log('Exception removing shortcut: ' + curname);
end;
end;
page.SetText('Removing Start menu folder', StartMenuFolder);
page.SetProgress(itemsdone, totalitems);
Log('Remove directory: ' + StartMenuFolder);
if not RemoveDir(StartMenuFolder) then Log('* Directory deletion failed');
itemsdone := itemsdone + 1;
for i := 0 to file_list.Count-1 do
begin
curname := InstallFolder + file_list.Strings[i];
page.SetText('Removing files', curname);
page.SetProgress(itemsdone, totalitems);
Log('Remove file: ' + curname);
SetFileAttributes(curname, 128); // 128 = FILE_ATTRIBUTE_NORMAL
if not DeleteFile(curname) then Log('* Deletion failed');
itemsdone := itemsdone + 1;
end;
// This moving is done to help Windows' link tracking code be able to fix shortcuts
page.SetText('Moving EXE file to new name', 'Aegisub.exe');
page.SetProgress(itemsdone, totalitems);
Log('Rename Aegisub.exe to aegisub32.exe');
RenameFile(InstallFolder+'Aegisub.exe', InstallFolder+'aegisub32.exe');
itemsdone := itemsdone + 1;
for i := 0 to locale_list.Count-1 do
begin
curname := InstallFolder + locale_list.Strings[i];
page.SetText('Removing folders', curname);
page.SetProgress(itemsdone, totalitems);
Log('Remove directory recursively: ' + curname);
if not DelTree(curname, True, True, True) then Log('* Tree deletion failed');
itemsdone := itemsdone + 1;
end;
for i := 0 to dir_list.Count-1 do
begin
curname := InstallFolder + dir_list.Strings[i];
page.SetText('Removing folders', curname);
page.SetProgress(itemsdone, totalitems);
Log('Remove directory: ' + curname);
if not RemoveDir(curname) then Log('* Directory deletion failed');
itemsdone := itemsdone + 1;
end;
page.SetText('Uninstallation complete', '');
page.SetProgress(totalitems, totalitems);
except
Log('An exception occurred while trying to clean up an older version');
finally
shortcut_list.Free;
file_list.Free;
locale_list.Free;
dir_list.Free;
page.Hide;
end;
end;
procedure CurStepChangedMigration(CurStep: TSetupStep);
begin
if CurStep = ssInstall then
begin
if HasLegacyVersion then
begin
MigrateStyleCatalogs;
UninstallLegacyVersion;
end;
CleanUpOldVersion;
end;
end;