Add installer

This commit is contained in:
driftingsun 2020-12-16 06:02:22 +03:00
parent c9bc8aa8c1
commit a2a5cafc5f
73 changed files with 4354 additions and 488 deletions

View file

@ -0,0 +1,329 @@
var requestToQuitFromApp = false;
var updaterCompleted = 0;
var desktopAppProcessRunning = false;
var appInstalledUninstallerPath;
function appName()
{
return installer.value("Name");
}
function appAlreadyInstalled()
{
return installer.fileExists(appInstalledUninstallerPath);
}
function appExecutableFileName()
{
if (runningOnWindows()) {
return appName() + ".exe";
} else {
return appName();
}
}
function appInstalled()
{
if (runningOnWindows()) {
appInstalledUninstallerPath = installer.value("TargetDir") + "\\maintenancetool.exe";
} else if (runningOnMacOS()){
appInstalledUninstallerPath = "/Applications/" + appName() + ".app/maintenancetool.app/Contents/MacOS/maintenancetool";
}
return appAlreadyInstalled();
}
function endsWith(str, suffix)
{
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
function runningOnWindows()
{
return (installer.value("os") === "win");
}
function runningOnMacOS()
{
return (installer.value("os") === "mac");
}
function sleep(miliseconds) {
var currentTime = new Date().getTime();
while (currentTime + miliseconds >= new Date().getTime()) {}
}
function raiseInstallerWindow()
{
if (!runningOnMacOS()) {
return;
}
var result = installer.execute("/bin/bash", ["-c", "ps -A | grep -m1 '" + appName() + "' | awk '{print $1}'"]);
if (Number(result[0]) > 0) {
var arg = 'tell application \"System Events\" ' +
'\n set frontmost of the first process whose unix id is ' + Number(result[0]) + ' to true ' +
'\n end tell' +
'\n ';
installer.execute("osascript", ["-e", arg]);
}
}
function appProcessIsRunning()
{
if (runningOnWindows()) {
var cmdArgs = ["/FI", "WINDOWTITLE eq " + appName()];
var result = installer.execute("tasklist", cmdArgs);
if ( Number(result[1]) === 0 ) {
if (result[0].indexOf(appExecutableFileName()) !== -1) {
return true;
}
}
} else {
return checkProccesIsRunning("pgrep -x '" + appName() + "'")
}
return false;
}
function checkProccesIsRunning(arg)
{
var cmdArgs = ["-c", arg];
var result = installer.execute("/bin/bash", cmdArgs);
var resultArg1 = Number(result[0])
if (resultArg1 >= 3) {
return true;
}
return false;
}
function requestToQuit(installer,gui)
{
requestToQuitFromApp = true;
installer.setDefaultPageVisible(QInstaller.IntroductionPage, false);
installer.setDefaultPageVisible(QInstaller.TargetDirectory, false);
installer.setDefaultPageVisible(QInstaller.ComponentSelection, false);
installer.setDefaultPageVisible(QInstaller.LicenseCheck, false);
installer.setDefaultPageVisible(QInstaller.StartMenuSelection, false);
installer.setDefaultPageVisible(QInstaller.ReadyForInstallation, false);
installer.setDefaultPageVisible(QInstaller.PerformInstallation, false);
installer.setDefaultPageVisible(QInstaller.FinishedPage, false);
gui.clickButton(buttons.NextButton);
gui.clickButton(buttons.FinishButton);
gui.clickButton(buttons.CancelButton);
if (runningOnWindows()) {
installer.setCancelled();
}
}
Controller.prototype.PerformInstallationPageCallback = function()
{
gui.clickButton(buttons.NextButton);
}
Controller.prototype.LicenseAgreementPageCallback = function()
{
gui.clickButton(buttons.NextButton);
}
Controller.prototype.FinishedPageCallback = function ()
{
if (desktopAppProcessRunning) {
gui.clickButton(buttons.FinishButton);
} else if (installer.isUpdater()) {
installer.autoAcceptMessageBoxes();
gui.clickButton(buttons.FinishButton);
}
}
Controller.prototype.RestartPageCallback = function ()
{
updaterCompleted = 1;
gui.clickButton(buttons.FinishButton);
}
Controller.prototype.StartMenuDirectoryPageCallback = function()
{
gui.clickButton(buttons.NextButton);
}
Controller.prototype.ComponentSelectionPageCallback = function()
{
gui.clickButton(buttons.NextButton);
}
Controller.prototype.ReadyForInstallationPageCallback = function()
{
if (installer.isUpdater()) {
gui.clickButton(buttons.CommitButton);
}
}
Controller.prototype.TargetDirectoryPageCallback = function ()
{
var widget = gui.pageById(QInstaller.TargetDirectory);
if (widget !== null) {
widget.BrowseDirectoryButton.clicked.disconnect(onBrowseButtonClicked);
widget.BrowseDirectoryButton.clicked.connect(onBrowseButtonClicked);
gui.clickButton(buttons.NextButton);
}
}
Controller.prototype.IntroductionPageCallback = function ()
{
var widget = gui.currentPageWidget();
if (installer.isUpdater() && updaterCompleted === 1) {
gui.clickButton(buttons.FinishButton);
gui.clickButton(buttons.CancelButton);
return;
}
if (installer.isUninstaller()) {
if (widget !== null) {
widget.findChild("PackageManagerRadioButton").visible = false;
widget.findChild("UpdaterRadioButton").visible = false;
}
}
if (installer.isUpdater()) {
gui.clickButton(buttons.NextButton);
}
}
onBrowseButtonClicked = function()
{
var widget = gui.pageById(QInstaller.TargetDirectory);
if (widget !== null) {
if (runningOnWindows()) {
// On Windows we are appending \<APP_NAME> if selected path don't ends with <APP_NAME>
var targetDir = widget.TargetDirectoryLineEdit.text;
if (! endsWith(targetDir, appName())) {
targetDir = targetDir + "\\" + appName();
}
installer.setValue("TargetDir", targetDir);
widget.TargetDirectoryLineEdit.setText(installer.value("TargetDir"));
}
}
}
onNextButtonClicked = function()
{
var widget = gui.pageById(QInstaller.TargetDirectory);
if (widget !== null) {
installer.setValue("APP_BUNDLE_TARGET_DIR", widget.TargetDirectoryLineEdit.text);
}
}
function Controller () {
console.log("OS: %1, architecture: %2".arg(systemInfo.prettyProductName).arg(systemInfo.currentCpuArchitecture));
if (installer.isInstaller() || installer.isUpdater()) {
console.log("Check if app already installed: " + appInstalled());
}
if (runningOnWindows()) {
installer.setValue("AllUsers", "true");
}
if (installer.isInstaller()) {
installer.setDefaultPageVisible(QInstaller.ComponentSelection, false);
installer.setDefaultPageVisible(QInstaller.TargetDirectory, false);
installer.setDefaultPageVisible(QInstaller.StartMenuDirectoryPage, false);
installer.setDefaultPageVisible(QInstaller.LicenseCheck, false);
isDesktopAppProcessRunningMessageLoop();
if (requestToQuitFromApp === true) {
requestToQuit(installer, gui);
return;
}
if (runningOnMacOS()) {
installer.setMessageBoxAutomaticAnswer("OverwriteTargetDirectory", QMessageBox.Yes);
}
if (appAlreadyInstalled()) {
if (QMessageBox.Ok === QMessageBox.information("os.information", appName(),
qsTr("The application is already installed.") + " " +
qsTr("We need to remove the old installation first. Do you wish to proceed?"),
QMessageBox.Ok | QMessageBox.Cancel)) {
if (appAlreadyInstalled()) {
var resultArray = installer.execute(appInstalledUninstallerPath);
console.log("Uninstaller finished with code: " + resultArray[1])
if (Number(resultArray[1]) !== 0) {
console.log("Uninstallation aborted by user");
installer.setCancelled();
return;
} else {
for (var i = 0; i < 100; i++) {
sleep(100);
if (!installer.fileExists(appInstalledUninstallerPath)) {
break;
}
}
}
}
raiseInstallerWindow();
} else {
console.log("Request to quit from user");
installer.setCancelled();
return;
}
}
} else if (installer.isUninstaller()) {
isDesktopAppProcessRunningMessageLoop();
if (requestToQuitFromApp === true) {
requestToQuit(installer, gui);
return;
}
} else if (installer.isUpdater()) {
installer.setMessageBoxAutomaticAnswer("cancelInstallation", QMessageBox.No);
installer.installationFinished.connect(function() {
gui.clickButton(buttons.NextButton);
});
}
}
isDesktopAppProcessRunningMessageLoop = function ()
{
if (requestToQuitFromApp === true) {
return;
}
if (installer.isUpdater()) {
for (var i = 0; i < 400; i++) {
desktopAppProcessRunning = appProcessIsRunning();
if (!desktopAppProcessRunning) {
break;
}
}
}
desktopAppProcessRunning = appProcessIsRunning();
if (desktopAppProcessRunning) {
var result = QMessageBox.warning("QMessageBox", appName() + " installer",
appName() + " is active. Close the app and press \"Retry\" button to continue installation. Press \"Abort\" button to abort the installer and exit.",
QMessageBox.Retry | QMessageBox.Abort);
if (result === QMessageBox.Retry) {
isDesktopAppProcessRunningMessageLoop();
} else {
requestToQuitFromApp = true;
return;
}
}
}

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<Installer>
<Name>AmneziaVPN</Name>
<Version>1.0.0</Version>
<Title>AmneziaVPN</Title>
<Publisher>AmneziaVPN</Publisher>
<StartMenuDir>AmneziaVPN</StartMenuDir>
<TargetDir>/Applications/AmneziaVPN.app</TargetDir>
<WizardDefaultWidth>600</WizardDefaultWidth>
<WizardDefaultHeight>380</WizardDefaultHeight>
<WizardStyle>Modern</WizardStyle>
<RemoveTargetDir>true</RemoveTargetDir>
<AllowSpaceInPath>true</AllowSpaceInPath>
<AllowNonAsciiCharacters>false</AllowNonAsciiCharacters>
<ControlScript>controlscript.js</ControlScript>
<RepositorySettingsPageVisible>false</RepositorySettingsPageVisible>
<DependsOnLocalInstallerBinary>true</DependsOnLocalInstallerBinary>
<SupportsModify>false</SupportsModify>
<DisableAuthorizationFallback>true</DisableAuthorizationFallback>
<RemoteRepositories>
<Repository>
<Url>https://amneziavpn.org/updates/macos</Url>
<Enabled>true</Enabled>
<DisplayName>AmneziaVPN - repository for macOS</DisplayName>
</Repository>
</RemoteRepositories>
</Installer>

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<Installer>
<Name>AmneziaVPN</Name>
<Version>1.0.0</Version>
<Title>AmneziaVPN</Title>
<Publisher>AmneziaVPN</Publisher>
<StartMenuDir>AmneziaVPN</StartMenuDir>
<TargetDir>@ApplicationsDir@/AmneziaVPN</TargetDir>
<WizardDefaultWidth>600</WizardDefaultWidth>
<WizardDefaultHeight>380</WizardDefaultHeight>
<WizardStyle>Modern</WizardStyle>
<RemoveTargetDir>true</RemoveTargetDir>
<AllowSpaceInPath>true</AllowSpaceInPath>
<AllowNonAsciiCharacters>false</AllowNonAsciiCharacters>
<ControlScript>controlscript.js</ControlScript>
<RepositorySettingsPageVisible>false</RepositorySettingsPageVisible>
<DependsOnLocalInstallerBinary>true</DependsOnLocalInstallerBinary>
<SupportsModify>false</SupportsModify>
<DisableAuthorizationFallback>true</DisableAuthorizationFallback>
<RemoteRepositories>
<Repository>
<Url>https://amneziavpn.org/updates/windows</Url>
<Enabled>true</Enabled>
<DisplayName>AmneziaVPN - repository for Windows</DisplayName>
</Repository>
</RemoteRepositories>
</Installer>

View file

@ -0,0 +1,115 @@
function appName()
{
return installer.value("Name")
}
function serviceName()
{
return (appName() + "-service")
}
function appExecutableFileName()
{
if (runningOnWindows()) {
return appName() + ".exe";
} else {
return appName();
}
}
function runningOnWindows()
{
return (systemInfo.kernelType === "winnt");
}
function runningOnMacOS()
{
return (systemInfo.kernelType === "darwin");
}
function vcRuntimeIsInstalled()
{
return (installer.findPath("msvcp140.dll", [installer.value("RootDir")+ "\\Windows\\System32\\"]).length !== 0)
}
function Component()
{
component.loaded.connect(this, Component.prototype.componentLoaded);
installer.installationFinished.connect(this, Component.prototype.installationFinishedPageIsShown);
installer.finishButtonClicked.connect(this, Component.prototype.installationFinished);
}
Component.prototype.componentLoaded = function ()
{
}
Component.prototype.installationFinishedPageIsShown = function()
{
if (installer.isInstaller() && installer.status === QInstaller.Success) {
gui.clickButton(buttons.FinishButton);
}
}
Component.prototype.createOperations = function()
{
component.createOperations();
if (runningOnWindows()) {
component.addOperation("CreateShortcut", "@TargetDir@/" + appExecutableFileName(),
QDesktopServices.storageLocation(QDesktopServices.DesktopLocation) + "/" + appName() + ".lnk",
"workingDirectory=@TargetDir@", "iconPath=@TargetDir@\\" + appExecutableFileName(), "iconId=0");
component.addElevatedOperation("CreateShortcut", "@TargetDir@/" + appExecutableFileName(),
installer.value("AllUsersStartMenuProgramsPath") + "/" + appName() + ".lnk",
"workingDirectory=@TargetDir@", "iconPath=@TargetDir@\\" + appExecutableFileName(), "iconId=0");
if (!vcRuntimeIsInstalled()) {
component.addElevatedOperation("Execute", "@TargetDir@\\" + "vc_redist.x86.exe", "/install", "/quiet", "/norestart", "/log", "vc_redist_2017_x86.log");
} else {
console.log("Microsoft Visual C++ 2017 Redistributable already installed");
}
component.addElevatedOperation("Execute",
["sc", "create", serviceName(), "binpath=", installer.value("TargetDir").replace(/\//g, '\\') + "\\" + serviceName() + ".exe",
"start=", "auto", "depend=", "BFE/nsi"],
"UNDOEXECUTE", ["post-uninstall.exe"]);
} else if (runningOnMacOS()) {
component.addElevatedOperation("Execute", "@TargetDir@/post_install.sh", "UNDOEXECUTE", "@TargetDir@/post_uninstall.sh");
}
}
Component.prototype.installationFinished = function()
{
var command = "";
var args = [];
if ((installer.status === QInstaller.Success) && (installer.isInstaller() || installer.isUpdater())) {
if (!installer.gainAdminRights()) {
console.log("Fatal error! Cannot get admin rights!")
return
}
if (runningOnWindows()) {
command = "@TargetDir@/" + appExecutableFileName()
var status1 = installer.execute("net", ["start", serviceName()])
console.log(("%1 started with status: %2 ").arg(serviceName()).arg(status1))
var status2 = installer.execute("sc", ["failure", serviceName(), "reset=", "100", "actions=", "restart/2000/restart/2000/restart/2000"])
console.log(("Changed settings for %1 with status: %2 ").arg(serviceName()).arg(status2))
} else if (runningOnMacOS()) {
command = "/Applications/" + appName() + ".app/Contents/MacOS/" + appName();
}
installer.dropAdminRights()
processStatus = installer.executeDetached(command, args, installer.value("TargetDir"));
}
}

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<Package>
<DisplayName>AmneziaVPN</DisplayName>
<Description>Installation package for AmneziaVPN</Description>
<Version>1.0.0</Version>
<ReleaseDate>1970-01-01</ReleaseDate>
<Default>true</Default>
<ForcedInstallation>true</ForcedInstallation>
<RequiresAdminRights>true</RequiresAdminRights>
<Script>componentscript.js</Script>
</Package>