codekingpro/portable-devtools
115k
1'use strict'
2
3const cp = require('child_process')
4const path = require('path')
5const { openSync, closeSync } = require('graceful-fs')
6const log = require('./log')
7
8const execFile = async (...args) => new Promise((resolve) => {
9 const child = cp.execFile(...args, (...a) => resolve(a))
10 child.stdin.end()
11})
12
13async function regGetValue (key, value, addOpts) {
14 const outReValue = value.replace(/\W/g, '.')
15 const outRe = new RegExp(`^\\s+${outReValue}\\s+REG_\\w+\\s+(\\S.*)$`, 'im')
16 const reg = path.join(process.env.SystemRoot, 'System32', 'reg.exe')
17 const regArgs = ['query', key, '/v', value].concat(addOpts)
18
19 log.silly('reg', 'running', reg, regArgs)
20 const [err, stdout, stderr] = await execFile(reg, regArgs, { encoding: 'utf8' })
21
22 log.silly('reg', 'reg.exe stdout = %j', stdout)
23 if (err || stderr.trim() !== '') {
24 log.silly('reg', 'reg.exe err = %j', err && (err.stack || err))
25 log.silly('reg', 'reg.exe stderr = %j', stderr)
26 if (err) {
27 throw err
28 }
29 throw new Error(stderr)
30 }
31
32 const result = outRe.exec(stdout)
33 if (!result) {
34 log.silly('reg', 'error parsing stdout')
35 throw new Error('Could not parse output of reg.exe')
36 }
37
38 log.silly('reg', 'found: %j', result[1])
39 return result[1]
40}
41
42async function regSearchKeys (keys, value, addOpts) {
43 for (const key of keys) {
44 try {
45 return await regGetValue(key, value, addOpts)
46 } catch {
47 continue
48 }
49 }
50}
51
52/**
53 * Returns the first file or directory from an array of candidates that is
54 * readable by the current user, or undefined if none of the candidates are
55 * readable.
56 */
57function findAccessibleSync (logprefix, dir, candidates) {
58 for (let next = 0; next < candidates.length; next++) {
59 const candidate = path.resolve(dir, candidates[next])
60 let fd
61 try {
62 fd = openSync(candidate, 'r')
63 } catch (e) {
64 // this candidate was not found or not readable, do nothing
65 log.silly(logprefix, 'Could not open %s: %s', candidate, e.message)
66 continue
67 }
68 closeSync(fd)
69 log.silly(logprefix, 'Found readable %s', candidate)
70 return candidate
71 }
72
73 return undefined
74}
75
76module.exports = {
77 execFile,
78 regGetValue,
79 regSearchKeys,
80 findAccessibleSync
81}
82 