mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-23 01:44:26 +08:00
0.5.12
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
#define MyAppName "LanMountainDesktop"
|
||||
#define MyAppName "LanMountainDesktop"
|
||||
#define MyAppPublisher "LanMountainDesktop Team"
|
||||
#define MyAppExeName "LanMountainDesktop.exe"
|
||||
#define MyAppId "{{5A058B0D-F95D-4A18-B9A0-93F843655DDB}"
|
||||
#define MyAppRegistryId "{5A058B0D-F95D-4A18-B9A0-93F843655DDB}"
|
||||
|
||||
#ifndef MyAppVersion
|
||||
#define MyAppVersion "0.0.0"
|
||||
@@ -19,13 +21,16 @@
|
||||
#endif
|
||||
|
||||
[Setup]
|
||||
AppId={{5A058B0D-F95D-4A18-B9A0-93F843655DDB}
|
||||
AppId={#MyAppId}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion}
|
||||
AppPublisher={#MyAppPublisher}
|
||||
DefaultDirName={autopf}\{#MyAppName}
|
||||
DisableDirPage=no
|
||||
UsePreviousAppDir=no
|
||||
ShowLanguageDialog=yes
|
||||
UsePreviousLanguage=no
|
||||
LanguageDetectionMethod=uilanguage
|
||||
DefaultGroupName={#MyAppName}
|
||||
UninstallDisplayIcon={app}\{#MyAppExeName}
|
||||
OutputDir={#MyOutputDir}
|
||||
@@ -34,6 +39,9 @@ Compression=lzma2/ultra64
|
||||
SolidCompression=yes
|
||||
WizardStyle=modern
|
||||
PrivilegesRequired=admin
|
||||
CloseApplications=yes
|
||||
CloseApplicationsFilter={#MyAppExeName}
|
||||
RestartApplications=no
|
||||
DisableProgramGroupPage=yes
|
||||
|
||||
#if MyAppArch == "x64"
|
||||
@@ -47,10 +55,55 @@ ArchitecturesAllowed=x86compatible
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
Name: "chinesesimplified"; MessagesFile: "{#SourcePath}\ChineseSimplified.isl"
|
||||
|
||||
[CustomMessages]
|
||||
english.StartupTaskDescription=Launch LanMountainDesktop when you sign in to Windows
|
||||
chinesesimplified.StartupTaskDescription=登录 Windows 时启动 LanMountainDesktop
|
||||
english.WebView2MissingMessage=Microsoft Edge WebView2 Runtime is required for the browser component.
|
||||
chinesesimplified.WebView2MissingMessage=浏览器组件需要 Microsoft Edge WebView2 Runtime。
|
||||
english.WebView2MissingAction=Click "Yes" to open the official download page. Install it first, then run this installer again.
|
||||
chinesesimplified.WebView2MissingAction=单击“是”打开官方下载页面。请先完成安装,然后重新运行此安装程序。
|
||||
english.WebView2OpenFailedMessage=Unable to open the download page automatically.
|
||||
chinesesimplified.WebView2OpenFailedMessage=无法自动打开下载页面。
|
||||
english.WebView2OpenFailedAction=Please open this URL manually:
|
||||
chinesesimplified.WebView2OpenFailedAction=请手动打开以下链接:
|
||||
english.UpgradePageCaption=Upgrade Existing Installation
|
||||
chinesesimplified.UpgradePageCaption=升级现有安装
|
||||
english.UpgradePageDescription=LanMountainDesktop is already installed on this computer. Choose how to upgrade it.
|
||||
chinesesimplified.UpgradePageDescription=此计算机上已安装 LanMountainDesktop。请选择升级方式。
|
||||
english.UpgradeDetectedVersionLabel=Detected version:
|
||||
chinesesimplified.UpgradeDetectedVersionLabel=检测到的版本:
|
||||
english.UpgradeCurrentLocationLabel=Current location:
|
||||
chinesesimplified.UpgradeCurrentLocationLabel=当前安装位置:
|
||||
english.UpgradePageSubCaption=Choose "Upgrade existing installation" to reuse the current location, or choose "Change installation location and migrate installation" to move the app without leaving a duplicate copy behind.
|
||||
chinesesimplified.UpgradePageSubCaption=选择“升级现有安装”可复用当前安装位置;选择“更改安装位置并迁移安装”可移动应用,同时避免留下重复安装。
|
||||
english.UpgradeOptionInPlace=Upgrade existing installation
|
||||
chinesesimplified.UpgradeOptionInPlace=升级现有安装
|
||||
english.UpgradeOptionRelocate=Change installation location and migrate installation
|
||||
chinesesimplified.UpgradeOptionRelocate=更改安装位置并迁移安装
|
||||
english.UpgradeUnknownVersion=Unknown
|
||||
chinesesimplified.UpgradeUnknownVersion=未知
|
||||
english.UpgradeCleanupMissingUninstaller=Setup found an existing installation, but its uninstaller is unavailable. Please uninstall the current version manually and run this installer again.
|
||||
chinesesimplified.UpgradeCleanupMissingUninstaller=安装程序发现了现有安装,但无法找到它的卸载程序。请先手动卸载当前版本,再重新运行此安装程序。
|
||||
english.UpgradeCleanupFailedPrefix=Setup could not remove the existing installation automatically. Error code:
|
||||
chinesesimplified.UpgradeCleanupFailedPrefix=安装程序无法自动移除现有安装。错误代码:
|
||||
english.UpgradeCleanupFailedSuffix=Please close LanMountainDesktop, uninstall the current version manually, and then run this installer again.
|
||||
chinesesimplified.UpgradeCleanupFailedSuffix=请关闭 LanMountainDesktop,手动卸载当前版本,然后重新运行此安装程序。
|
||||
|
||||
[Tasks]
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
|
||||
Name: "startup"; Description: "Launch LanMountainDesktop when you sign in to Windows"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||
Name: "startup"; Description: "{cm:StartupTaskDescription}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||
|
||||
[Dirs]
|
||||
Name: "{app}\log"; Permissions: users-modify
|
||||
|
||||
[InstallDelete]
|
||||
Type: files; Name: "{app}\LanMontainDesktop.exe"
|
||||
Type: files; Name: "{app}\LanMontainDesktop.dll"
|
||||
Type: files; Name: "{app}\LanMontainDesktop.deps.json"
|
||||
Type: files; Name: "{app}\LanMontainDesktop.runtimeconfig.json"
|
||||
Type: files; Name: "{app}\LanMontainDesktop.pdb"
|
||||
|
||||
[Files]
|
||||
Source: "{#PublishDir}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
@@ -67,12 +120,309 @@ Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChang
|
||||
|
||||
[Code]
|
||||
const
|
||||
UninstallRegSubkey = 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{#MyAppRegistryId}_is1';
|
||||
WebView2RuntimeKeyPath = 'SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}';
|
||||
WebView2RuntimeDownloadUrl = 'https://go.microsoft.com/fwlink/p/?LinkId=2124703';
|
||||
UpgradeChoiceInPlace = 0;
|
||||
UpgradeChoiceRelocate = 1;
|
||||
|
||||
var
|
||||
UpgradeModePage: TInputOptionWizardPage;
|
||||
ExistingInstallFound: Boolean;
|
||||
ExistingInstallPath: String;
|
||||
ExistingInstallVersion: String;
|
||||
ExistingUninstallCommand: String;
|
||||
ExistingInstallWas64Bit: Boolean;
|
||||
ExistingInstallIsPerUser: Boolean;
|
||||
ExistingInstallRemoved: Boolean;
|
||||
|
||||
function NormalizePathValue(const Value: String): String;
|
||||
begin
|
||||
Result := RemoveBackslashUnlessRoot(Trim(Value));
|
||||
end;
|
||||
|
||||
function CombinePath(const BasePath: String; const ChildName: String): String;
|
||||
begin
|
||||
if BasePath = '' then
|
||||
begin
|
||||
Result := ChildName;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Result := NormalizePathValue(BasePath) + '\' + ChildName;
|
||||
end;
|
||||
end;
|
||||
|
||||
function SamePath(const LeftPath: String; const RightPath: String): Boolean;
|
||||
begin
|
||||
Result := CompareText(NormalizePathValue(LeftPath), NormalizePathValue(RightPath)) = 0;
|
||||
end;
|
||||
|
||||
function ExtractExecutableFromCommand(const CommandLine: String): String;
|
||||
var
|
||||
CommandText: String;
|
||||
ClosingQuotePos: Integer;
|
||||
ExePos: Integer;
|
||||
begin
|
||||
Result := '';
|
||||
CommandText := Trim(CommandLine);
|
||||
if CommandText = '' then
|
||||
begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
if CommandText[1] = '"' then
|
||||
begin
|
||||
Delete(CommandText, 1, 1);
|
||||
ClosingQuotePos := Pos('"', CommandText);
|
||||
if ClosingQuotePos > 0 then
|
||||
begin
|
||||
Result := Copy(CommandText, 1, ClosingQuotePos - 1);
|
||||
end
|
||||
else
|
||||
begin
|
||||
Result := CommandText;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
ExePos := Pos('.exe', LowerCase(CommandText));
|
||||
if ExePos > 0 then
|
||||
begin
|
||||
Result := Copy(CommandText, 1, ExePos + 3);
|
||||
end
|
||||
else
|
||||
begin
|
||||
Result := CommandText;
|
||||
end;
|
||||
end;
|
||||
|
||||
Result := NormalizePathValue(RemoveQuotes(Result));
|
||||
end;
|
||||
|
||||
function GetExistingExecutablePath(): String;
|
||||
begin
|
||||
if ExistingInstallPath = '' then
|
||||
begin
|
||||
Result := '';
|
||||
end
|
||||
else
|
||||
begin
|
||||
Result := CombinePath(ExistingInstallPath, '{#MyAppExeName}');
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetDefaultInstallPath(): String;
|
||||
begin
|
||||
Result := NormalizePathValue(ExpandConstant('{autopf}\{#MyAppName}'));
|
||||
end;
|
||||
|
||||
function GetExistingInstallVersionText(): String;
|
||||
begin
|
||||
Result := Trim(ExistingInstallVersion);
|
||||
if Result = '' then
|
||||
begin
|
||||
Result := CustomMessage('UpgradeUnknownVersion');
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ShowUpgradeCleanupError(const MessageText: String);
|
||||
begin
|
||||
Log(MessageText);
|
||||
if not WizardSilent then
|
||||
begin
|
||||
MsgBox(MessageText, mbError, MB_OK);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TryLoadExistingInstallation(
|
||||
const RootKey: Integer;
|
||||
const Is64BitView: Boolean;
|
||||
const IsPerUser: Boolean): Boolean;
|
||||
var
|
||||
InstallLocation: String;
|
||||
AppPath: String;
|
||||
UninstallString: String;
|
||||
DisplayVersion: String;
|
||||
ResolvedPath: String;
|
||||
begin
|
||||
Result := False;
|
||||
InstallLocation := '';
|
||||
AppPath := '';
|
||||
UninstallString := '';
|
||||
DisplayVersion := '';
|
||||
|
||||
if not RegKeyExists(RootKey, UninstallRegSubkey) then
|
||||
begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
RegQueryStringValue(RootKey, UninstallRegSubkey, 'InstallLocation', InstallLocation);
|
||||
RegQueryStringValue(RootKey, UninstallRegSubkey, 'Inno Setup: App Path', AppPath);
|
||||
RegQueryStringValue(RootKey, UninstallRegSubkey, 'UninstallString', UninstallString);
|
||||
RegQueryStringValue(RootKey, UninstallRegSubkey, 'DisplayVersion', DisplayVersion);
|
||||
|
||||
ResolvedPath := NormalizePathValue(InstallLocation);
|
||||
if ResolvedPath = '' then
|
||||
begin
|
||||
ResolvedPath := NormalizePathValue(AppPath);
|
||||
end;
|
||||
if (ResolvedPath = '') and (UninstallString <> '') then
|
||||
begin
|
||||
ResolvedPath := NormalizePathValue(ExtractFileDir(ExtractExecutableFromCommand(UninstallString)));
|
||||
end;
|
||||
|
||||
if (ResolvedPath = '') or
|
||||
(not DirExists(ResolvedPath)) or
|
||||
(not FileExists(CombinePath(ResolvedPath, '{#MyAppExeName}'))) then
|
||||
begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
ExistingInstallFound := True;
|
||||
ExistingInstallPath := ResolvedPath;
|
||||
ExistingInstallVersion := Trim(DisplayVersion);
|
||||
ExistingUninstallCommand := Trim(UninstallString);
|
||||
ExistingInstallWas64Bit := Is64BitView;
|
||||
ExistingInstallIsPerUser := IsPerUser;
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
procedure DetectExistingInstallation;
|
||||
begin
|
||||
ExistingInstallFound := False;
|
||||
ExistingInstallPath := '';
|
||||
ExistingInstallVersion := '';
|
||||
ExistingUninstallCommand := '';
|
||||
ExistingInstallWas64Bit := False;
|
||||
ExistingInstallIsPerUser := False;
|
||||
ExistingInstallRemoved := False;
|
||||
|
||||
if IsWin64 then
|
||||
begin
|
||||
if TryLoadExistingInstallation(HKLM64, True, False) then
|
||||
begin
|
||||
exit;
|
||||
end;
|
||||
if TryLoadExistingInstallation(HKCU64, True, True) then
|
||||
begin
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
if TryLoadExistingInstallation(HKLM32, False, False) then
|
||||
begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
TryLoadExistingInstallation(HKCU32, False, True);
|
||||
end;
|
||||
|
||||
function SelectedUpgradeChoice(): Integer;
|
||||
begin
|
||||
if UpgradeModePage <> nil then
|
||||
begin
|
||||
Result := UpgradeModePage.SelectedValueIndex;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Result := UpgradeChoiceInPlace;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ApplySelectedInstallDirectory;
|
||||
var
|
||||
CurrentDir: String;
|
||||
begin
|
||||
if not ExistingInstallFound then
|
||||
begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
if SelectedUpgradeChoice() = UpgradeChoiceInPlace then
|
||||
begin
|
||||
WizardForm.DirEdit.Text := ExistingInstallPath;
|
||||
exit;
|
||||
end;
|
||||
|
||||
CurrentDir := NormalizePathValue(WizardDirValue);
|
||||
if (CurrentDir = '') or SamePath(CurrentDir, GetDefaultInstallPath()) then
|
||||
begin
|
||||
WizardForm.DirEdit.Text := ExistingInstallPath;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetSelectedInstallPath(): String;
|
||||
begin
|
||||
Result := NormalizePathValue(ExpandConstant('{app}'));
|
||||
if Result = '' then
|
||||
begin
|
||||
Result := NormalizePathValue(WizardDirValue);
|
||||
end;
|
||||
if Result = '' then
|
||||
begin
|
||||
Result := ExistingInstallPath;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ExistingInstallRequiresCleanup(): Boolean;
|
||||
var
|
||||
TargetPath: String;
|
||||
begin
|
||||
Result := False;
|
||||
if not ExistingInstallFound or ExistingInstallRemoved then
|
||||
begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
TargetPath := GetSelectedInstallPath();
|
||||
Result := ExistingInstallIsPerUser or
|
||||
(not SamePath(TargetPath, ExistingInstallPath)) or
|
||||
(ExistingInstallWas64Bit <> Is64BitInstallMode);
|
||||
end;
|
||||
|
||||
function RemoveExistingInstallation(): Boolean;
|
||||
var
|
||||
UninstallerPath: String;
|
||||
ResultCode: Integer;
|
||||
begin
|
||||
Result := True;
|
||||
|
||||
if not ExistingInstallRequiresCleanup() then
|
||||
begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
UninstallerPath := ExtractExecutableFromCommand(ExistingUninstallCommand);
|
||||
if (UninstallerPath = '') or (not FileExists(UninstallerPath)) then
|
||||
begin
|
||||
ShowUpgradeCleanupError(CustomMessage('UpgradeCleanupMissingUninstaller'));
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
|
||||
ResultCode := -1;
|
||||
if not Exec(
|
||||
UninstallerPath,
|
||||
'/VERYSILENT /SUPPRESSMSGBOXES /NORESTART',
|
||||
ExtractFileDir(UninstallerPath),
|
||||
SW_SHOWNORMAL,
|
||||
ewWaitUntilTerminated,
|
||||
ResultCode) or (ResultCode <> 0) then
|
||||
begin
|
||||
ShowUpgradeCleanupError(
|
||||
CustomMessage('UpgradeCleanupFailedPrefix') + ' ' + IntToStr(ResultCode) + '. ' +
|
||||
CustomMessage('UpgradeCleanupFailedSuffix'));
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
|
||||
ExistingInstallRemoved := True;
|
||||
end;
|
||||
|
||||
function IsWebView2RuntimeInstalled(): Boolean;
|
||||
var
|
||||
VersionValue: string;
|
||||
VersionValue: String;
|
||||
begin
|
||||
Result :=
|
||||
RegQueryStringValue(HKLM64, WebView2RuntimeKeyPath, 'pv', VersionValue) or
|
||||
@@ -92,16 +442,16 @@ begin
|
||||
end;
|
||||
|
||||
if MsgBox(
|
||||
'Microsoft Edge WebView2 Runtime is required for the browser component.'#13#10#13#10 +
|
||||
'Click "Yes" to open the official download page. Install it first, then run this installer again.',
|
||||
CustomMessage('WebView2MissingMessage') + #13#10#13#10 +
|
||||
CustomMessage('WebView2MissingAction'),
|
||||
mbConfirmation,
|
||||
MB_YESNO) = IDYES then
|
||||
begin
|
||||
if not ShellExec('open', WebView2RuntimeDownloadUrl, '', '', SW_SHOWNORMAL, ewNoWait, ErrorCode) then
|
||||
begin
|
||||
MsgBox(
|
||||
'Unable to open the download page automatically.'#13#10 +
|
||||
'Please open this URL manually:'#13#10 + WebView2RuntimeDownloadUrl,
|
||||
CustomMessage('WebView2OpenFailedMessage') + #13#10 +
|
||||
CustomMessage('WebView2OpenFailedAction') + #13#10 + WebView2RuntimeDownloadUrl,
|
||||
mbError,
|
||||
MB_OK);
|
||||
end;
|
||||
@@ -109,3 +459,84 @@ begin
|
||||
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
procedure InitializeWizard;
|
||||
var
|
||||
DetailsText: String;
|
||||
begin
|
||||
DetectExistingInstallation;
|
||||
|
||||
if not ExistingInstallFound then
|
||||
begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
DetailsText :=
|
||||
CustomMessage('UpgradeDetectedVersionLabel') + ' ' + GetExistingInstallVersionText() + #13#10 +
|
||||
CustomMessage('UpgradeCurrentLocationLabel') + ' ' + ExistingInstallPath + #13#10#13#10 +
|
||||
CustomMessage('UpgradePageSubCaption');
|
||||
|
||||
UpgradeModePage := CreateInputOptionPage(
|
||||
wpWelcome,
|
||||
CustomMessage('UpgradePageCaption'),
|
||||
CustomMessage('UpgradePageDescription'),
|
||||
DetailsText,
|
||||
True,
|
||||
False);
|
||||
UpgradeModePage.Add(CustomMessage('UpgradeOptionInPlace'));
|
||||
UpgradeModePage.Add(CustomMessage('UpgradeOptionRelocate'));
|
||||
UpgradeModePage.SelectedValueIndex := UpgradeChoiceInPlace;
|
||||
end;
|
||||
|
||||
function NextButtonClick(CurPageID: Integer): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
|
||||
if (UpgradeModePage <> nil) and (CurPageID = UpgradeModePage.ID) then
|
||||
begin
|
||||
ApplySelectedInstallDirectory;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ShouldSkipPage(PageID: Integer): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
|
||||
if (UpgradeModePage <> nil) and (PageID = UpgradeModePage.ID) then
|
||||
begin
|
||||
Result := not ExistingInstallFound;
|
||||
exit;
|
||||
end;
|
||||
|
||||
if PageID = wpSelectDir then
|
||||
begin
|
||||
Result := ExistingInstallFound and (SelectedUpgradeChoice() = UpgradeChoiceInPlace);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure RegisterExtraCloseApplicationsResources;
|
||||
var
|
||||
ExistingExecutablePath: String;
|
||||
begin
|
||||
if not ExistingInstallFound then
|
||||
begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
ExistingExecutablePath := GetExistingExecutablePath();
|
||||
if (ExistingExecutablePath <> '') and FileExists(ExistingExecutablePath) then
|
||||
begin
|
||||
RegisterExtraCloseApplicationsResource(False, ExistingExecutablePath);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CurStepChanged(CurStep: TSetupStep);
|
||||
begin
|
||||
if CurStep = ssInstall then
|
||||
begin
|
||||
if not RemoveExistingInstallation() then
|
||||
begin
|
||||
Abort;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user