#30: Add uninstall feature with reboot to handle WinFSP upgrades/downgrades
This commit is contained in:
@@ -88,9 +88,9 @@ const unmountAllDrives = () => {
|
|||||||
mountedData = {};
|
mountedData = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
function createWindow() {
|
function createWindow() {
|
||||||
loadUiSettings();
|
loadUiSettings();
|
||||||
|
|
||||||
let extra = {};
|
let extra = {};
|
||||||
if (os.platform() === 'linux') {
|
if (os.platform() === 'linux') {
|
||||||
extra = {
|
extra = {
|
||||||
@@ -726,20 +726,45 @@ ipcMain.on(Constants.IPC_Install_Dependency, (event, data) => {
|
|||||||
}, error);
|
}, error);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
helpers
|
const execInstall = () => {
|
||||||
.executeAndWait(data.Source)
|
helpers
|
||||||
.then(() => {
|
.executeAndWait(data.Source)
|
||||||
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
.then(() => {
|
||||||
Source: data.Source,
|
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
||||||
URL: data.URL,
|
Source: data.Source,
|
||||||
|
URL: data.URL,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
||||||
|
Source: data.Source,
|
||||||
|
URL: data.URL,
|
||||||
|
}, error);
|
||||||
});
|
});
|
||||||
})
|
};
|
||||||
.catch(error => {
|
if (data.IsWinFSP) {
|
||||||
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
helpers
|
||||||
Source: data.Source,
|
.performWindowsUninstall(["WinFsp 2019.3 B1", "WinFsp 2019.3 B2"])
|
||||||
URL: data.URL,
|
.then(uninstalled => {
|
||||||
}, error);
|
if (uninstalled) {
|
||||||
});
|
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
||||||
|
RebootRequired: true,
|
||||||
|
Source: data.Source,
|
||||||
|
URL: data.URL,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
execInstall();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
||||||
|
Source: data.Source,
|
||||||
|
URL: data.URL,
|
||||||
|
}, error);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
execInstall();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
108
src/helpers.js
108
src/helpers.js
@@ -12,6 +12,55 @@ const _getDataDirectory = () => {
|
|||||||
return _resolvePath(Constants.DATA_LOCATIONS[os.platform()]);
|
return _resolvePath(Constants.DATA_LOCATIONS[os.platform()]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const _executeProcess = (command, args=[]) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const processOptions = {
|
||||||
|
detached: true,
|
||||||
|
shell: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const process = new spawn(command, args, processOptions);
|
||||||
|
const pid = process.pid;
|
||||||
|
|
||||||
|
process.on('error', (err) => {
|
||||||
|
reject(err, pid);
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('exit', (code) => {
|
||||||
|
resolve(code);
|
||||||
|
});
|
||||||
|
|
||||||
|
process.unref();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const _execProcessGetOutput = (cmd, args) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const proc = spawn(cmd, args, {
|
||||||
|
env: process.env,
|
||||||
|
stdio: ['ignore', 'pipe', 'pipe']
|
||||||
|
});
|
||||||
|
|
||||||
|
let output;
|
||||||
|
proc.stdout.on('data', data => {
|
||||||
|
output += data.toString();
|
||||||
|
});
|
||||||
|
|
||||||
|
proc.on('error', (err) => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
proc.on('exit', () => {
|
||||||
|
const lines = output
|
||||||
|
.replace(/\r\n/g, '\n')
|
||||||
|
.split('\n');
|
||||||
|
resolve(lines);
|
||||||
|
});
|
||||||
|
|
||||||
|
proc.unref();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const _resolvePath = str => {
|
const _resolvePath = str => {
|
||||||
if (os.platform() === 'win32') {
|
if (os.platform() === 'win32') {
|
||||||
return str.replace(/%([^%]+)%/g, (_, n) => {
|
return str.replace(/%([^%]+)%/g, (_, n) => {
|
||||||
@@ -484,6 +533,65 @@ module.exports.mkDirByPathSync = (targetDir, { isRelativeToScript = false } = {}
|
|||||||
}, initDir);
|
}, initDir);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports.performWindowsUninstall = names => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (os.platform() !== 'win32') {
|
||||||
|
reject('Windows OS is not being used');
|
||||||
|
} else {
|
||||||
|
const cmd = path.join(process.env.windir, 'system32', 'reg.exe');
|
||||||
|
const args = ["QUERY", "HKLM\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"];
|
||||||
|
_execProcessGetOutput(cmd, args)
|
||||||
|
.then(lines => {
|
||||||
|
const parseLine = index => {
|
||||||
|
if (index < lines.length) {
|
||||||
|
const line = lines[index];
|
||||||
|
if (line.startsWith('HKEY_LOCAL_MACHINE\\')) {
|
||||||
|
let args2 = JSON.parse(JSON.stringify(args));
|
||||||
|
args2[1] = 'HKLM\\' + line.substr(19);
|
||||||
|
args2.push('/v');
|
||||||
|
args2.push('DisplayName');
|
||||||
|
args2.push('/t');
|
||||||
|
args2.push('REG_SZ');
|
||||||
|
_execProcessGetOutput(cmd, args2)
|
||||||
|
.then(lines => {
|
||||||
|
const value = lines[2].trim().substr(args2[3].length).trim().substr(6).trim();
|
||||||
|
if (names.includes(value)) {
|
||||||
|
const items = line.split('\\');
|
||||||
|
const productCode = items[items.length - 1];
|
||||||
|
_executeProcess('msiexec.exe', ['/x', productCode, '/norestart'])
|
||||||
|
.then(code => {
|
||||||
|
if ((code === 0) || (code === 3010) || (code === 1641)) {
|
||||||
|
resolve(true);
|
||||||
|
} else {
|
||||||
|
reject('[' + value + '] uninstall failed: ' + code);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
parseLine(++index);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err=> {
|
||||||
|
parseLine(++index);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
parseLine(++index);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resolve(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
parseLine(0);
|
||||||
|
})
|
||||||
|
.catch( err => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
module.exports.removeDirectoryRecursively = (p) => {
|
module.exports.removeDirectoryRecursively = (p) => {
|
||||||
if (fs.existsSync(p)) {
|
if (fs.existsSync(p)) {
|
||||||
fs
|
fs
|
||||||
|
|||||||
Reference in New Issue
Block a user