winreg-ts
Version:
provides access to the windows registry through the REG tool
534 lines • 18.6 kB
JavaScript
"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