完善在线工具、插件运行时与安装卸载流程
This commit is contained in:
+273
-78
@@ -82,6 +82,7 @@ CloseApplicationsFilter={#MyAppExeName}
|
||||
#endif
|
||||
RestartApplications=no
|
||||
UninstallDisplayIcon={app}\{#MyAppExeName}
|
||||
UninstallFilesDir={app}\Runtime\uninstall-engine
|
||||
|
||||
[Languages]
|
||||
Name: "chinesesimp"; MessagesFile: "{#ChineseMessagesFile}"
|
||||
@@ -162,6 +163,7 @@ Name: "desktopicon"; Description: "{cm:DesktopIcon}"; GroupDescription: "{cm:Sho
|
||||
Name: "startmenuicon"; Description: "{cm:StartMenuIcon}"; GroupDescription: "{cm:ShortcutGroup}"; Flags: unchecked
|
||||
Name: "autostart"; Description: "{cm:AutoStart}"; GroupDescription: "{cm:StartupGroup}"; Flags: unchecked
|
||||
Name: "launchapp"; Description: "{cm:LaunchApp}"; GroupDescription: "{cm:StartupGroup}"; Flags: checkedonce
|
||||
Name: "cleancache"; Description: "{cm:CleanCache}"; GroupDescription: "{cm:MaintenanceGroup}"; Flags: unchecked
|
||||
|
||||
[Files]
|
||||
Source: "{#PayloadDir}\*"; DestDir: "{app}"; Excludes: "*.pri"; Flags: ignoreversion recursesubdirs createallsubdirs; BeforeInstall: LogCurrentExtractFile
|
||||
@@ -178,50 +180,6 @@ Name: "{app}\data"
|
||||
Name: "{app}\FeedbackPackages"; Permissions: users-modify
|
||||
Name: "{app}\data\legacy-imports"
|
||||
|
||||
[InstallDelete]
|
||||
Type: filesandordirs; Name: "{app}\resources\lang"
|
||||
Type: filesandordirs; Name: "{app}\lang"
|
||||
#if Int(QAIsolated) == 0
|
||||
Type: filesandordirs; Name: "{localappdata}\YMhut Box\WinUI\Runtime"
|
||||
Type: filesandordirs; Name: "{localappdata}\YMhut Box\WinUI\runtime"
|
||||
Type: filesandordirs; Name: "{localappdata}\YMhut Box\WinUI\Runtimes"
|
||||
Type: filesandordirs; Name: "{localappdata}\YMhut Box\WinUI\runtimes"
|
||||
Type: filesandordirs; Name: "{localappdata}\YMhut Box\WinUI\Tools"
|
||||
Type: filesandordirs; Name: "{localappdata}\YMhut Box\WinUI\Metadata"
|
||||
Type: filesandordirs; Name: "{localappdata}\YMhut Box\Runtime"
|
||||
Type: filesandordirs; Name: "{localappdata}\YMhut Box\runtime"
|
||||
Type: filesandordirs; Name: "{localappdata}\YMhut Box\Tools"
|
||||
Type: filesandordirs; Name: "{localappdata}\YMhut Box\Metadata"
|
||||
Type: filesandordirs; Name: "{localappdata}\ymhut_box\Runtime"
|
||||
Type: filesandordirs; Name: "{localappdata}\ymhut_box\runtime"
|
||||
Type: filesandordirs; Name: "{localappdata}\ymhut_box\Tools"
|
||||
Type: filesandordirs; Name: "{localappdata}\ymhut_box\Metadata"
|
||||
Type: filesandordirs; Name: "{localappdata}\YMhut Box\cache"; Check: ShouldCleanCache
|
||||
Type: filesandordirs; Name: "{userappdata}\YMhut Box\cache"; Check: ShouldCleanCache
|
||||
Type: filesandordirs; Name: "{localappdata}\ymhut_box\cache"; Check: ShouldCleanCache
|
||||
Type: filesandordirs; Name: "{userappdata}\ymhut_box\cache"; Check: ShouldCleanCache
|
||||
#endif
|
||||
Type: files; Name: "{app}\*.winmd"
|
||||
Type: files; Name: "{app}\*.pdb"
|
||||
Type: files; Name: "{app}\workloads*.json"
|
||||
Type: files; Name: "{app}\installer-layout.txt"
|
||||
Type: files; Name: "{app}\config\installer-layout.dat"
|
||||
Type: files; Name: "{app}\config\installer-required-files.dat"
|
||||
Type: files; Name: "{app}\Assets\data\reference-data.dat"
|
||||
Type: files; Name: "{app}\YMhut.Box.Worker.exe"
|
||||
Type: files; Name: "{app}\YMhut.Box.Worker.dll"
|
||||
Type: files; Name: "{app}\YMhut.Box.Worker.deps.json"
|
||||
Type: files; Name: "{app}\YMhut.Box.Worker.runtimeconfig.json"
|
||||
Type: files; Name: "{app}\YMhut.Box.PluginHost.exe"
|
||||
Type: files; Name: "{app}\YMhut.Box.PluginHost.dll"
|
||||
Type: files; Name: "{app}\YMhut.Box.PluginHost.deps.json"
|
||||
Type: files; Name: "{app}\YMhut.Box.PluginHost.runtimeconfig.json"
|
||||
Type: filesandordirs; Name: "{app}\updater"
|
||||
Type: files; Name: "{app}\YMhut.Box.Updater.exe"
|
||||
Type: files; Name: "{app}\YMhut.Box.Updater.dll"
|
||||
Type: files; Name: "{app}\YMhut.Box.Updater.deps.json"
|
||||
Type: files; Name: "{app}\YMhut.Box.Updater.runtimeconfig.json"
|
||||
|
||||
[Icons]
|
||||
Name: "{userprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: startmenuicon
|
||||
Name: "{userdesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
||||
@@ -265,6 +223,9 @@ var
|
||||
InstallOutputPendingLineCount: Integer;
|
||||
InstallOutputBuffer: string;
|
||||
LastExtractFileName: string;
|
||||
OldPayloadFiles: TStringList;
|
||||
NewPayloadFiles: TStringList;
|
||||
LegacyBackupDir: string;
|
||||
|
||||
function SendMessage(hWnd: Longint; Msg: Longint; wParam: Longint; lParam: Longint): Longint;
|
||||
external 'SendMessageW@user32.dll stdcall';
|
||||
@@ -326,7 +287,7 @@ end;
|
||||
|
||||
function ShouldCleanCache(): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
Result := WizardIsTaskSelected('cleancache');
|
||||
end;
|
||||
|
||||
function DetectExistingInstallDir(): string;
|
||||
@@ -373,9 +334,13 @@ end;
|
||||
|
||||
procedure LayoutInstallOutputMemo(); forward;
|
||||
procedure ScrollInstallOutputToBottom(); forward;
|
||||
procedure CaptureOldPayloadManifest(); forward;
|
||||
procedure FinalizeLegacyInstallLayout(); forward;
|
||||
|
||||
procedure InitializeWizard;
|
||||
begin
|
||||
OldPayloadFiles := TStringList.Create;
|
||||
NewPayloadFiles := TStringList.Create;
|
||||
DownloadPage := CreateDownloadPage(SetupMessage(msgWizardPreparing), SetupMessage(msgPreparingDesc), nil);
|
||||
DownloadPage.ShowBaseNameInsteadOfUrl := True;
|
||||
ExistingInstallDir := DetectExistingInstallDir();
|
||||
@@ -902,37 +867,109 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function ShouldPreserveAppEntry(const Name: string): Boolean;
|
||||
var
|
||||
LowerName: string;
|
||||
function NormalizeManifestEntry(const Value: string): string;
|
||||
begin
|
||||
LowerName := Lowercase(Name);
|
||||
Result :=
|
||||
(LowerName = 'data') or
|
||||
(LowerName = 'feedbackpackages') or
|
||||
(Pos('unins', LowerName) = 1);
|
||||
Result := Trim(Value);
|
||||
StringChangeEx(Result, '/', '\', True);
|
||||
while (Length(Result) > 0) and (Result[1] = '\') do
|
||||
Delete(Result, 1, 1);
|
||||
Result := Lowercase(Result);
|
||||
if (Result = '') or (Result = '..') or
|
||||
(Pos('..\', Result) > 0) or (Pos('\..', Result) > 0) or
|
||||
(Pos(':', Result) > 0) then
|
||||
Result := '';
|
||||
end;
|
||||
|
||||
procedure CleanOldApplicationPayload(const DirName: string);
|
||||
procedure LoadInstallManifestFiles(const FileName: string; Files: TStringList);
|
||||
var
|
||||
FindRec: TFindRec;
|
||||
EntryPath: string;
|
||||
Lines: TStringList;
|
||||
I: Integer;
|
||||
Entry: string;
|
||||
InFiles: Boolean;
|
||||
begin
|
||||
if not DirExists(DirName) then
|
||||
Files.Clear;
|
||||
if not FileExists(FileName) then
|
||||
Exit;
|
||||
|
||||
if FindFirst(AddBackslash(DirName) + '*', FindRec) then
|
||||
Lines := TStringList.Create;
|
||||
try
|
||||
Lines.LoadFromFile(FileName);
|
||||
InFiles := False;
|
||||
for I := 0 to Lines.Count - 1 do
|
||||
begin
|
||||
Entry := Trim(Lines[I]);
|
||||
if (Length(Entry) > 1) and (Entry[1] = '[') then
|
||||
begin
|
||||
InFiles := CompareText(Entry, '[Files]') = 0;
|
||||
Continue;
|
||||
end;
|
||||
|
||||
if InFiles then
|
||||
begin
|
||||
Entry := NormalizeManifestEntry(Entry);
|
||||
if (Entry <> '') and (Files.IndexOf(Entry) < 0) then
|
||||
Files.Add(Entry);
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
Lines.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ManifestContains(Files: TStringList; const RelativePath: string): Boolean;
|
||||
var
|
||||
Entry: string;
|
||||
begin
|
||||
Entry := NormalizeManifestEntry(RelativePath);
|
||||
Result := (Entry <> '') and (Files.IndexOf(Entry) >= 0);
|
||||
end;
|
||||
|
||||
function IsPreservedInstallPath(const RelativePath: string): Boolean;
|
||||
var
|
||||
Entry: string;
|
||||
begin
|
||||
Entry := NormalizeManifestEntry(RelativePath);
|
||||
Result :=
|
||||
(Entry = 'data') or (Pos('data\', Entry) = 1) or
|
||||
(Entry = 'feedbackpackages') or (Pos('feedbackpackages\', Entry) = 1) or
|
||||
(Entry = 'config\install-manifest.ini') or
|
||||
(Entry = 'unins000.exe') or
|
||||
(Entry = 'runtime\uninstall-engine') or
|
||||
(Pos('runtime\uninstall-engine\', Entry) = 1);
|
||||
end;
|
||||
|
||||
function RelativeInstallPath(const AppDir, FullPath: string): string;
|
||||
begin
|
||||
Result := '';
|
||||
if Pos(Lowercase(AddBackslash(AppDir)), Lowercase(FullPath)) <> 1 then
|
||||
Exit;
|
||||
Result := NormalizeManifestEntry(Copy(FullPath, Length(AddBackslash(AppDir)) + 1, Length(FullPath)));
|
||||
end;
|
||||
|
||||
procedure CaptureOldPayloadManifest();
|
||||
var
|
||||
ManifestPath: string;
|
||||
begin
|
||||
if OldPayloadFiles = nil then
|
||||
Exit;
|
||||
ManifestPath := AddBackslash(WizardDirValue) + 'config\install-manifest.ini';
|
||||
LoadInstallManifestFiles(ManifestPath, OldPayloadFiles);
|
||||
Log(Format('Captured %d files from the previous install manifest.', [OldPayloadFiles.Count]));
|
||||
end;
|
||||
|
||||
function HasToolUiPayload(const AppDir: string): Boolean;
|
||||
var
|
||||
FindRec: TFindRec;
|
||||
begin
|
||||
Result := False;
|
||||
if FindFirst(AddBackslash(AppDir) + 'Assets\data\tool-ui\*.dat', FindRec) then
|
||||
begin
|
||||
try
|
||||
repeat
|
||||
if (FindRec.Name <> '.') and (FindRec.Name <> '..') and
|
||||
(not ShouldPreserveAppEntry(FindRec.Name)) then
|
||||
if (FindRec.Attributes and DirectoryAttribute) = 0 then
|
||||
begin
|
||||
EntryPath := AddBackslash(DirName) + FindRec.Name;
|
||||
if ((FindRec.Attributes and DirectoryAttribute) <> 0) then
|
||||
DelTree(EntryPath, True, True, True)
|
||||
else
|
||||
DeleteFile(EntryPath);
|
||||
Result := True;
|
||||
Exit;
|
||||
end;
|
||||
until not FindNext(FindRec);
|
||||
finally
|
||||
@@ -941,21 +978,169 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CleanLegacyInstallLayout();
|
||||
procedure VerifyNewApplicationPayload(const AppDir: string);
|
||||
var
|
||||
ManifestPath: string;
|
||||
begin
|
||||
ManifestPath := AddBackslash(AppDir) + 'config\install-manifest.ini';
|
||||
LoadInstallManifestFiles(ManifestPath, NewPayloadFiles);
|
||||
if NewPayloadFiles.Count = 0 then
|
||||
RaiseException('The new install manifest is missing or empty. Legacy files were not changed.');
|
||||
|
||||
if not FileExists(AddBackslash(AppDir) + '{#MyAppExeName}') or
|
||||
not FileExists(AddBackslash(AppDir) + 'YMhutBox.dll') or
|
||||
not FileExists(AddBackslash(AppDir) + 'Assets\runtime-assets.dat') or
|
||||
not FileExists(AddBackslash(AppDir) + 'Assets\data\ymhut-data.ybin') or
|
||||
not FileExists(AddBackslash(AppDir) + 'music-api\node.exe') or
|
||||
not FileExists(AddBackslash(AppDir) + 'music-api\api\ymhut-sidecar.js') or
|
||||
not FileExists(AddBackslash(AppDir) + 'music-api\api\pnpm-lock.yaml') or
|
||||
not FileExists(AddBackslash(AppDir) + 'music-api\api\LICENSE') or
|
||||
not FileExists(AddBackslash(AppDir) + 'unins000.exe') or
|
||||
not FileExists(AddBackslash(AppDir) + 'Runtime\uninstall-engine\unins000.exe') or
|
||||
not FileExists(AddBackslash(AppDir) + 'Runtime\uninstall-engine\unins000.dat') or
|
||||
not HasToolUiPayload(AppDir) then
|
||||
RaiseException('The new application payload is incomplete. Legacy files were not changed.');
|
||||
end;
|
||||
|
||||
procedure RegisterCustomUninstallEntry(const AppDir: string);
|
||||
var
|
||||
UninstallKey: string;
|
||||
UninstallCommand: string;
|
||||
QuietUninstallCommand: string;
|
||||
begin
|
||||
UninstallKey := 'Software\Microsoft\Windows\CurrentVersion\Uninstall\' + '{#MyAppId}' + '_is1';
|
||||
UninstallCommand := '"' + AddBackslash(AppDir) + 'unins000.exe" /UNINSTALL /INSTALLDIR="' + AppDir + '"';
|
||||
QuietUninstallCommand := UninstallCommand + ' /VERYSILENT /NORESTART';
|
||||
|
||||
if IsAdminInstallMode then
|
||||
begin
|
||||
RegWriteStringValue(HKLM64, UninstallKey, 'UninstallString', UninstallCommand);
|
||||
RegWriteStringValue(HKLM64, UninstallKey, 'QuietUninstallString', QuietUninstallCommand);
|
||||
end
|
||||
else
|
||||
begin
|
||||
RegWriteStringValue(HKCU, UninstallKey, 'UninstallString', UninstallCommand);
|
||||
RegWriteStringValue(HKCU, UninstallKey, 'QuietUninstallString', QuietUninstallCommand);
|
||||
end;
|
||||
Log('Registered the YMhut Box uninstall bootstrap.');
|
||||
end;
|
||||
|
||||
procedure DeleteKnownObsoletePayload(const AppDir: string);
|
||||
var
|
||||
I: Integer;
|
||||
RelativePath: string;
|
||||
FullPath: string;
|
||||
begin
|
||||
for I := 0 to OldPayloadFiles.Count - 1 do
|
||||
begin
|
||||
RelativePath := OldPayloadFiles[I];
|
||||
if (not ManifestContains(NewPayloadFiles, RelativePath)) and
|
||||
(not IsPreservedInstallPath(RelativePath)) then
|
||||
begin
|
||||
FullPath := AddBackslash(AppDir) + RelativePath;
|
||||
if FileExists(FullPath) then
|
||||
begin
|
||||
if DeleteFile(FullPath) then
|
||||
Log('Removed obsolete payload file: ' + RelativePath)
|
||||
else
|
||||
Log('Unable to remove obsolete payload file: ' + RelativePath);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure QuarantineLegacyFile(const AppDir, FullPath, RelativePath: string);
|
||||
var
|
||||
TargetPath: string;
|
||||
begin
|
||||
if LegacyBackupDir = '' then
|
||||
begin
|
||||
LegacyBackupDir := AddBackslash(AppDir) + 'data\legacy-imports\program-backup-' +
|
||||
GetDateTimeString('yyyymmdd-hhnnss', '', '');
|
||||
end;
|
||||
|
||||
TargetPath := AddBackslash(LegacyBackupDir) + RelativePath;
|
||||
ForceDirectories(ExtractFileDir(TargetPath));
|
||||
if FileExists(TargetPath) then
|
||||
TargetPath := TargetPath + '.old';
|
||||
|
||||
if RenameFile(FullPath, TargetPath) or
|
||||
(CopyFile(FullPath, TargetPath, False) and DeleteFile(FullPath)) then
|
||||
Log('Preserved unknown legacy file: ' + RelativePath)
|
||||
else
|
||||
Log('Unable to preserve unknown legacy file: ' + RelativePath);
|
||||
end;
|
||||
|
||||
procedure QuarantineUnknownLegacyFiles(const AppDir, CurrentDir: string);
|
||||
var
|
||||
FindRec: TFindRec;
|
||||
FullPath: string;
|
||||
RelativePath: string;
|
||||
begin
|
||||
if not DirExists(CurrentDir) then
|
||||
Exit;
|
||||
|
||||
if FindFirst(AddBackslash(CurrentDir) + '*', FindRec) then
|
||||
begin
|
||||
try
|
||||
repeat
|
||||
if (FindRec.Name <> '.') and (FindRec.Name <> '..') then
|
||||
begin
|
||||
FullPath := AddBackslash(CurrentDir) + FindRec.Name;
|
||||
RelativePath := RelativeInstallPath(AppDir, FullPath);
|
||||
if (RelativePath <> '') and (not IsPreservedInstallPath(RelativePath)) then
|
||||
begin
|
||||
if (FindRec.Attributes and DirectoryAttribute) <> 0 then
|
||||
begin
|
||||
QuarantineUnknownLegacyFiles(AppDir, FullPath);
|
||||
RemoveDir(FullPath);
|
||||
end
|
||||
else if (not ManifestContains(NewPayloadFiles, RelativePath)) and
|
||||
(not ManifestContains(OldPayloadFiles, RelativePath)) then
|
||||
QuarantineLegacyFile(AppDir, FullPath, RelativePath);
|
||||
end;
|
||||
end;
|
||||
until not FindNext(FindRec);
|
||||
finally
|
||||
FindClose(FindRec);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CleanLegacyRuntimeAndCache();
|
||||
begin
|
||||
#if Int(QAIsolated) == 0
|
||||
DelTree(ExpandConstant('{localappdata}\YMhut Box\WinUI\Runtime'), True, True, True);
|
||||
DelTree(ExpandConstant('{localappdata}\YMhut Box\WinUI\Runtimes'), True, True, True);
|
||||
DelTree(ExpandConstant('{localappdata}\YMhut Box\WinUI\Tools'), True, True, True);
|
||||
DelTree(ExpandConstant('{localappdata}\YMhut Box\WinUI\Metadata'), True, True, True);
|
||||
DelTree(ExpandConstant('{localappdata}\YMhut Box\Runtime'), True, True, True);
|
||||
DelTree(ExpandConstant('{localappdata}\YMhut Box\Tools'), True, True, True);
|
||||
DelTree(ExpandConstant('{localappdata}\YMhut Box\Metadata'), True, True, True);
|
||||
DelTree(ExpandConstant('{localappdata}\ymhut_box\Runtime'), True, True, True);
|
||||
DelTree(ExpandConstant('{localappdata}\ymhut_box\Tools'), True, True, True);
|
||||
DelTree(ExpandConstant('{localappdata}\ymhut_box\Metadata'), True, True, True);
|
||||
if ShouldCleanCache() then
|
||||
begin
|
||||
DelTree(ExpandConstant('{localappdata}\YMhut Box\cache'), True, True, True);
|
||||
DelTree(ExpandConstant('{userappdata}\YMhut Box\cache'), True, True, True);
|
||||
DelTree(ExpandConstant('{localappdata}\ymhut_box\cache'), True, True, True);
|
||||
DelTree(ExpandConstant('{userappdata}\ymhut_box\cache'), True, True, True);
|
||||
end;
|
||||
#endif
|
||||
end;
|
||||
|
||||
procedure FinalizeLegacyInstallLayout();
|
||||
var
|
||||
AppDir: string;
|
||||
begin
|
||||
AppDir := ExpandConstant('{app}');
|
||||
CleanOldApplicationPayload(AppDir);
|
||||
DeleteFilesByPattern(AppDir, '*.winmd', True);
|
||||
DeleteFilesByPattern(AppDir, '*.pdb', True);
|
||||
DeleteFilesByPattern(AppDir, 'workloads*.json', True);
|
||||
DeleteFilesByPattern(AddBackslash(AppDir) + 'Assets\data', '*.json', True);
|
||||
DeleteFile(AddBackslash(AppDir) + 'installer-layout.txt');
|
||||
DeleteFile(AddBackslash(AppDir) + 'config\installer-layout.dat');
|
||||
DeleteFile(AddBackslash(AppDir) + 'config\installer-required-files.dat');
|
||||
DeleteFile(AddBackslash(AppDir) + 'Assets\data\reference-data.dat');
|
||||
CleanCultureFolders(AppDir);
|
||||
VerifyNewApplicationPayload(AppDir);
|
||||
if OldPayloadFiles.Count > 0 then
|
||||
DeleteKnownObsoletePayload(AppDir)
|
||||
else
|
||||
QuarantineUnknownLegacyFiles(AppDir, AppDir);
|
||||
CleanLegacyRuntimeAndCache();
|
||||
end;
|
||||
|
||||
function PrepareToInstall(var NeedsRestart: Boolean): string;
|
||||
@@ -978,6 +1163,8 @@ begin
|
||||
Exit;
|
||||
end;
|
||||
|
||||
CaptureOldPayloadManifest();
|
||||
|
||||
try
|
||||
if IsWebView2Installed() then
|
||||
LogBootstrapEvent('DEPENDENCY', 'ready|' + GetCustomMessageValue('WebView2RuntimeName'))
|
||||
@@ -1028,8 +1215,6 @@ begin
|
||||
LastInstallProgressPercent := -1;
|
||||
LastExtractFileName := '';
|
||||
LogBootstrapEvent('STAGE', 'files');
|
||||
AppendInstallOutput(CustomMessage('InstallOutputClean'));
|
||||
CleanLegacyInstallLayout();
|
||||
AppendInstallOutput(CustomMessage('InstallOutputExtract'));
|
||||
end
|
||||
else if CurStep = ssPostInstall then
|
||||
@@ -1037,6 +1222,8 @@ begin
|
||||
FlushInstallOutput();
|
||||
LogBootstrapEvent('STAGE', 'finalize');
|
||||
AppendInstallOutput(CustomMessage('InstallOutputPostInstall'));
|
||||
FinalizeLegacyInstallLayout();
|
||||
RegisterCustomUninstallEntry(ExpandConstant('{app}'));
|
||||
#if Int(QAIsolated) == 0
|
||||
MigrateLegacyData();
|
||||
#endif
|
||||
@@ -1044,6 +1231,14 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure DeinitializeSetup();
|
||||
begin
|
||||
if OldPayloadFiles <> nil then
|
||||
OldPayloadFiles.Free;
|
||||
if NewPayloadFiles <> nil then
|
||||
NewPayloadFiles.Free;
|
||||
end;
|
||||
|
||||
procedure CurInstallProgressChanged(CurProgress, MaxProgress: Integer);
|
||||
var
|
||||
ProgressPercent: Integer;
|
||||
|
||||
Reference in New Issue
Block a user