UNPKG

winreg-ts

Version:

provides access to the windows registry through the REG tool

534 lines 18.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Registry = void 0; const util = require("util"); const path = require("path"); const child_process_1 = require("child_process"); var log = function (msg) { }, HKLM = 'HKLM', HKCU = 'HKCU', HKCR = 'HKCR', HKU = 'HKU', HKCC = 'HKCC', HIVES = [HKLM, HKCU, HKCR, HKU, HKCC], REG_SZ = 'REG_SZ', REG_MULTI_SZ = 'REG_MULTI_SZ', REG_EXPAND_SZ = 'REG_EXPAND_SZ', REG_DWORD = 'REG_DWORD', REG_QWORD = 'REG_QWORD', REG_BINARY = 'REG_BINARY', REG_NONE = 'REG_NONE', REG_TYPES = [REG_SZ, REG_MULTI_SZ, REG_EXPAND_SZ, REG_DWORD, REG_QWORD, REG_BINARY, REG_NONE], DEFAULT_VALUE = '', KEY_PATTERN = /(\\[a-zA-Z0-9_\s]+)*/, PATH_PATTERN = /^(HKEY_LOCAL_MACHINE|HKEY_CURRENT_USER|HKEY_CLASSES_ROOT|HKEY_USERS|HKEY_CURRENT_CONFIG)(.*)$/, ITEM_PATTERN = /^(.*)\s(REG_SZ|REG_MULTI_SZ|REG_EXPAND_SZ|REG_DWORD|REG_QWORD|REG_BINARY|REG_NONE)\s+([^\s].*)$/, ARCH_X86 = 'x86', ARCH_X64 = 'x64', ARCHS = [ARCH_X86, ARCH_X64]; class ProcessUncleanExitError extends Error { constructor(message, code) { super(message); this._code = code; Object.setPrototypeOf(this, ProcessUncleanExitError.prototype); Error.captureStackTrace(this, this.constructor); } get code() { return this._code; } } function captureOutput(child) { var output = { 'stdout': '', 'stderr': '' }; child.stdout.on('data', function (data) { output["stdout"] += data.toString(); }); child.stderr.on('data', function (data) { output["stderr"] += data.toString(); }); return output; } function mkErrorMsg(registryCommand, code, output) { var stdout = output['stdout'].trim(); var stderr = output['stderr'].trim(); var msg = util.format("%s command exited with code %d:\n%s\n%s", registryCommand, code, stdout, stderr); return new ProcessUncleanExitError(msg, code); } function convertArchString(archString) { if (archString == 'x64') { return '64'; } else if (archString == 'x86') { return '32'; } else { throw new Error('illegal architecture: ' + archString + ' (use x86 or x64)'); } } function pushArch(args, arch) { if (arch) { args.push('/reg:' + convertArchString(arch)); } } function getRegExePath(utf8) { if (process.platform === 'win32') { if (utf8) { return path.join(process.env.windir, 'system32', 'chcp.com') + ' 65001 | ' + path.join(process.env.windir, 'system32', 'reg.exe'); } else { return path.join(process.env.windir, 'system32', 'reg.exe'); } } else { return "REG"; } } class RegistryItemImpl { constructor(_host, _hive, _key, _name, _type, _value, _arch) { this._host = _host; this._hive = _hive; this._key = _key; this._name = _name; this._type = _type; this._value = _value; this._arch = _arch; } get host() { return this._host; } get hive() { return this._hive; } get key() { return this._key; } get name() { return this._name; } get type() { return this._type; } get value() { return this._value; } get arch() { return this._arch; } } class Registry { constructor(options) { const _options = options || {}; this._host = '' + (_options.host || '') , this._hive = (_options.hive || HKLM) , this._key = '' + (_options.key || '') , this._arch = _options.arch || null , this._utf8 = _options.utf8 || false; if (HIVES.indexOf(this._hive) == -1) { throw new Error('illegal hive specified.'); } if (!KEY_PATTERN.test(this._key)) { throw new Error('illegal key specified.'); } if (this._arch && ARCHS.indexOf(this._arch) == -1) { throw new Error('illegal architecture specified (use x86 or x64)'); } } get host() { return this._host; } get hive() { return this._hive; } get key() { return this._key; } get path() { return (this._host.length == 0 ? '' : '\\\\' + this._host + '\\') + this._hive + this._key; } get arch() { return this._arch; } get utf8() { return this._utf8; } get parent() { var i = this._key.lastIndexOf('\\'); return new Registry({ host: this.host, hive: this.hive, key: (i == -1) ? '' : this._key.substring(0, i), arch: this.arch, utf8: this.utf8, }); } values(cb) { if (typeof cb !== 'function') throw new TypeError('must specify a callback'); const pathArg = this.utf8 ? `"${this.path}"` : this.path; var args = ['QUERY', pathArg]; pushArch(args, this.arch); var proc = child_process_1.spawn(getRegExePath(this.utf8), args, { cwd: undefined, env: process.env, stdio: ['ignore', 'pipe', 'pipe'], shell: this.utf8 }), buffer = '', self = this, error = null; var output = captureOutput(proc); proc.on('close', function (code) { if (error) { return; } else if (code !== 0) { log('process exited with code ' + code); cb(mkErrorMsg('QUERY', code, output), null); } else { var items = [], result = [], lines = buffer.split('\n'), lineNumber = 0; for (var i = 0, l = lines.length; i < l; i++) { var line = lines[i].trim(); if (line.length > 0) { log(line); if (lineNumber != 0) { items.push(line); } ++lineNumber; } } for (var i = 0, l = items.length; i < l; i++) { var match = ITEM_PATTERN.exec(items[i]), name, type, value; if (match) { name = match[1].trim(); type = match[2].trim(); value = match[3]; result.push(new RegistryItemImpl(self.host, self.hive, self.key, name, type, value, self.arch)); } } cb(null, result); } }); proc.stdout.on('data', function (data) { buffer += data.toString(); }); proc.on('error', function (err) { error = err; cb(err); }); return this; } ; keys(cb) { if (typeof cb !== 'function') throw new TypeError('must specify a callback'); const pathArg = this.utf8 ? `"${this.path}"` : this.path; var args = ['QUERY', pathArg]; pushArch(args, this.arch); var proc = child_process_1.spawn(getRegExePath(this.utf8), args, { cwd: undefined, env: process.env, stdio: ['ignore', 'pipe', 'pipe'], shell: this.utf8 }), buffer = '', self = this, error = null; var output = captureOutput(proc); proc.on('close', function (code) { if (error) { return; } else if (code !== 0) { log('process exited with code ' + code); cb(mkErrorMsg('QUERY', code, output), null); } }); proc.stdout.on('data', function (data) { buffer += data.toString(); }); proc.stdout.on('end', function () { var items = [], result = [], lines = buffer.split('\n'); for (var i = 0, l = lines.length; i < l; i++) { var line = lines[i].trim(); if (line.length > 0) { log(line); items.push(line); } } for (var i = 0, l = items.length; i < l; i++) { var match = PATH_PATTERN.exec(items[i]), key; if (match) { key = match[2]; if (key && (key !== self.key)) { result.push(new Registry({ host: self.host, hive: self.hive, key: key, arch: self.arch })); } } } cb(null, result); }); proc.on('error', function (err) { error = err; cb(err); }); return this; } ; get(name, cb) { if (typeof cb !== 'function') throw new TypeError('must specify a callback'); const pathArg = this.utf8 ? `"${this.path}"` : this.path; var args = ['QUERY', pathArg]; if (name == '') args.push('/ve'); else args = args.concat(['/v', name]); pushArch(args, this.arch); var proc = child_process_1.spawn(getRegExePath(this.utf8), args, { cwd: undefined, env: process.env, stdio: ['ignore', 'pipe', 'pipe'], shell: this.utf8 }), buffer = '', self = this, error = null; var output = captureOutput(proc); proc.on('close', function (code) { if (error) { return; } else if (code !== 0) { log('process exited with code ' + code); cb(mkErrorMsg('QUERY', code, output), null); } else { var items = [], result = null, lines = buffer.split('\n'), lineNumber = 0; for (var i = 0, l = lines.length; i < l; i++) { var line = lines[i].trim(); if (line.length > 0) { log(line); if (lineNumber != 0) { items.push(line); } ++lineNumber; } } var item = items[items.length - 1] || '', match = ITEM_PATTERN.exec(item), name, type, value; if (match) { name = match[1].trim(); type = match[2].trim(); value = match[3]; result = new RegistryItemImpl(self.host, self.hive, self.key, name, type, value, self.arch); } cb(null, result); } }); proc.stdout.on('data', function (data) { buffer += data.toString(); }); proc.on('error', function (err) { error = err; cb(err); }); return this; } ; set(name, type, value, cb) { if (typeof cb !== 'function') throw new TypeError('must specify a callback'); if (REG_TYPES.indexOf(type) == -1) throw Error('illegal type specified.'); const pathArg = this.utf8 ? `"${this.path}"` : this.path; var args = ['ADD', pathArg]; if (name == '') args.push('/ve'); else args = args.concat(['/v', name]); args = args.concat(['/t', type, '/d', value, '/f']); pushArch(args, this.arch); var proc = child_process_1.spawn(getRegExePath(this.utf8), args, { cwd: undefined, env: process.env, stdio: ['ignore', 'pipe', 'pipe'], shell: this.utf8 }), error = null; var output = captureOutput(proc); proc.on('close', function (code) { if (error) { return; } else if (code !== 0) { log('process exited with code ' + code); cb(mkErrorMsg('ADD', code, output), null); } else { cb(null); } }); proc.stdout.on('data', function (data) { log('' + data); }); proc.on('error', function (err) { error = err; cb(err); }); return this; } ; remove(name, cb) { if (typeof cb !== 'function') throw new TypeError('must specify a callback'); const pathArg = this.utf8 ? `"${this.path}"` : this.path; var args = name ? ['DELETE', pathArg, '/f', '/v', name] : ['DELETE', pathArg, '/f', '/ve']; pushArch(args, this.arch); var proc = child_process_1.spawn(getRegExePath(this.utf8), args, { cwd: undefined, env: process.env, stdio: ['ignore', 'pipe', 'pipe'], shell: this.utf8 }), error = null; var output = captureOutput(proc); proc.on('close', function (code) { if (error) { return; } else if (code !== 0) { log('process exited with code ' + code); cb(mkErrorMsg('DELETE', code, output), null); } else { cb(null); } }); proc.stdout.on('data', function (data) { log('' + data); }); proc.on('error', function (err) { error = err; cb(err); }); return this; } ; clear(cb) { if (typeof cb !== 'function') throw new TypeError('must specify a callback'); const pathArg = this.utf8 ? `"${this.path}"` : this.path; var args = ['DELETE', pathArg, '/f', '/va']; pushArch(args, this.arch); var proc = child_process_1.spawn(getRegExePath(this.utf8), args, { cwd: undefined, env: process.env, stdio: ['ignore', 'pipe', 'pipe'], shell: this.utf8 }), error = null; var output = captureOutput(proc); proc.on('close', function (code) { if (error) { return; } else if (code !== 0) { log('process exited with code ' + code); cb(mkErrorMsg("DELETE", code, output), null); } else { cb(null); } }); proc.stdout.on('data', function (data) { log('' + data); }); proc.on('error', function (err) { error = err; cb(err); }); return this; } ; erase(cb) { return this.clear(cb); } destroy(cb) { if (typeof cb !== 'function') throw new TypeError('must specify a callback'); const pathArg = this.utf8 ? `"${this.path}"` : this.path; var args = ['DELETE', pathArg, '/f']; pushArch(args, this.arch); var proc = child_process_1.spawn(getRegExePath(this.utf8), args, { cwd: undefined, env: process.env, stdio: ['ignore', 'pipe', 'pipe'], shell: this.utf8 }), error = null; var output = captureOutput(proc); proc.on('close', function (code) { if (error) { return; } else if (code !== 0) { log('process exited with code ' + code); cb(mkErrorMsg('DELETE', code, output), null); } else { cb(null); } }); proc.stdout.on('data', function (data) { log('' + data); }); proc.on('error', function (err) { error = err; cb(err); }); return this; } ; create(cb) { if (typeof cb !== 'function') throw new TypeError('must specify a callback'); const pathArg = this.utf8 ? `"${this.path}"` : this.path; var args = ['ADD', pathArg, '/f']; pushArch(args, this.arch); var proc = child_process_1.spawn(getRegExePath(this.utf8), args, { cwd: undefined, env: process.env, stdio: ['ignore', 'pipe', 'pipe'], shell: this.utf8 }), error = null; var output = captureOutput(proc); proc.on('close', function (code) { if (error) { return; } else if (code !== 0) { log('process exited with code ' + code); cb(mkErrorMsg('ADD', code, output), null); } else { cb(null); } }); proc.stdout.on('data', function (data) { log('' + data); }); proc.on('error', function (err) { error = err; cb(err); }); return this; } ; keyExists(cb) { this.values(function (err, items) { if (err) { if (err instanceof ProcessUncleanExitError && err.code == 1) { return cb(null, false); } return cb(err); } cb(null, true); }); return this; } ; valueExists(name, cb) { this.get(name, function (err, item) { if (err) { if (err instanceof ProcessUncleanExitError && err.code == 1) { return cb(null, false); } return cb(err); } cb(null, true); }); return this; } } exports.Registry = Registry; Registry.HKLM = HKLM; Registry.HKCU = HKCU; Registry.HKCR = HKCR; Registry.HKU = HKU; Registry.HKCC = HKCC; Registry.HIVES = HIVES; Registry.REG_SZ = REG_SZ; Registry.REG_MULTI_SZ = REG_MULTI_SZ; Registry.REG_EXPAND_SZ = REG_EXPAND_SZ; Registry.REG_DWORD = REG_DWORD; Registry.REG_QWORD = REG_QWORD; Registry.REG_BINARY = REG_BINARY; Registry.REG_NONE = REG_NONE; Registry.REG_TYPES = REG_TYPES; Registry.DEFAULT_VALUE = DEFAULT_VALUE; //# sourceMappingURL=registry.js.map