#30: Add uninstall feature with reboot to handle WinFSP upgrades/downgrades

This commit is contained in:
2019-08-14 10:39:12 -05:00
parent 1c7565d863
commit 5fd3067dd7
2 changed files with 148 additions and 15 deletions

View File

@@ -726,6 +726,7 @@ ipcMain.on(Constants.IPC_Install_Dependency, (event, data) => {
}, error);
});
} else {
const execInstall = () => {
helpers
.executeAndWait(data.Source)
.then(() => {
@@ -740,6 +741,30 @@ ipcMain.on(Constants.IPC_Install_Dependency, (event, data) => {
URL: data.URL,
}, error);
});
};
if (data.IsWinFSP) {
helpers
.performWindowsUninstall(["WinFsp 2019.3 B1", "WinFsp 2019.3 B2"])
.then(uninstalled => {
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();
}
}
});

View File

@@ -12,6 +12,55 @@ const _getDataDirectory = () => {
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 => {
if (os.platform() === 'win32') {
return str.replace(/%([^%]+)%/g, (_, n) => {
@@ -484,6 +533,65 @@ module.exports.mkDirByPathSync = (targetDir, { isRelativeToScript = false } = {}
}, 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) => {
if (fs.existsSync(p)) {
fs