Comparing version 0.5.0 to 2.0.0
@@ -21,3 +21,6 @@ var errors = {} | ||
errors[25127] = new Error('empty line written to vbscript stdin') | ||
errors[25127].code = 25127 | ||
//TODO: this is an error that is caused by trying to create a registry key somewhere I dont have permissions to | ||
@@ -28,2 +31,5 @@ // where is the reference for these codes....??? | ||
errors[2] = new Error('registry path does not exist') | ||
errors[2].code = 2 | ||
// *** generated errors ***// | ||
@@ -30,0 +36,0 @@ var e0 = new Error('wbemErrFailed') |
162
index.js
var util = require('util') | ||
var child = require('child_process') | ||
var childProcess = require('child_process') | ||
var path = require('path') | ||
@@ -7,2 +7,5 @@ var debug = require('debug')('regedit') | ||
var os = require('os') | ||
var StreamSlicer = require('stream-slicer') | ||
var through2 = require('through2') | ||
var helper = require('./lib/helper.js') | ||
@@ -33,3 +36,8 @@ /* | ||
module.exports.list = function (keys, architecture, callback) { | ||
if (typeof architecture === 'function') { | ||
//console.log('list with callback will be deprecated in future versions, use list streaming interface') | ||
if (architecture === undefined) { | ||
callback = undefined | ||
architecture = OS_ARCH_AGNOSTIC | ||
} else if (typeof architecture === 'function') { | ||
callback = architecture | ||
@@ -39,4 +47,21 @@ architecture = OS_ARCH_AGNOSTIC | ||
var args = toCommandArgs('regList.wsf', architecture, keys) | ||
execute(args, callback) | ||
if (typeof keys === 'string') { | ||
keys = [keys] | ||
} | ||
if (typeof callback === 'function') { | ||
execute(toCommandArgs('regList.wsf', architecture, keys), callback) | ||
} else { | ||
var child = spawn(baseCommand('regListStream.wsf', architecture)) | ||
child.stderr.pipe(process.stderr) | ||
var slicer = new StreamSlicer({ sliceBy: helper.WIN_EOL }) | ||
var stream = child.stdout.pipe(slicer).pipe(through2.obj(helper.vbsOutputTransform)) | ||
helper.writeArrayToStream(keys, child.stdin) | ||
return stream | ||
} | ||
} | ||
@@ -50,4 +75,13 @@ | ||
var args = toCommandArgs('regCreateKey.wsf', architecture, keys) | ||
execute(args, callback) | ||
if (typeof keys === 'string') { | ||
keys = [keys] | ||
} | ||
var args = baseCommand('regCreateKey.wsf', architecture) | ||
var child = spawn(args) | ||
handleErrorsAndClose(child, callback) | ||
helper.writeArrayToStream(keys, child.stdin) | ||
} | ||
@@ -61,4 +95,12 @@ | ||
var args = toCommandArgs('regDeleteKey.wsf', architecture, keys) | ||
execute(args, callback) | ||
if (typeof keys === 'string') { | ||
keys = [keys] | ||
} | ||
var args = baseCommand('regDeleteKey.wsf', architecture) | ||
var child = spawn(args) | ||
handleErrorsAndClose(child, callback) | ||
helper.writeArrayToStream(keys, child.stdin) | ||
} | ||
@@ -73,15 +115,23 @@ | ||
var args = baseCommand('regPutValue.wsf', architecture) | ||
var child = spawn(args) | ||
var values = [] | ||
for (var key in map) { | ||
var values = map[key] | ||
for (var valueName in values) { | ||
var entry = values[valueName] | ||
args.push(key) | ||
args.push(valueName) | ||
args.push(renderValueByType(entry.value, entry.type)) | ||
args.push(entry.type) | ||
var keyValues = map[key] | ||
for (var valueName in keyValues) { | ||
var entry = keyValues[valueName] | ||
// helper writes the array to the stream in reversed order | ||
values.push(entry.type) | ||
values.push(renderValueByType(entry.value, entry.type)) | ||
values.push(valueName) | ||
values.push(key) | ||
} | ||
} | ||
execute(args, callback) | ||
handleErrorsAndClose(child, callback) | ||
helper.writeArrayToStream(values, child.stdin) | ||
} | ||
@@ -92,47 +142,47 @@ | ||
module.exports.arch.list = function(keys, callback) { | ||
module.exports.list(keys, OS_ARCH_SPECIFIC, callback) | ||
return module.exports.list(keys, OS_ARCH_SPECIFIC, callback) | ||
} | ||
module.exports.arch.list32 = function (keys, callback) { | ||
module.exports.list(keys, OS_ARCH_32BIT, callback) | ||
return module.exports.list(keys, OS_ARCH_32BIT, callback) | ||
} | ||
module.exports.arch.list64 = function (keys, callback) { | ||
module.exports.list(keys, OS_ARCH_64BIT, callback) | ||
return module.exports.list(keys, OS_ARCH_64BIT, callback) | ||
} | ||
module.exports.arch.createKey = function (keys, callback) { | ||
module.exports.createKey(keys, OS_ARCH_SPECIFIC, callback) | ||
return module.exports.createKey(keys, OS_ARCH_SPECIFIC, callback) | ||
} | ||
module.exports.arch.createKey32 = function (keys, callback) { | ||
module.exports.createKey(keys, OS_ARCH_32BIT, callback) | ||
return module.exports.createKey(keys, OS_ARCH_32BIT, callback) | ||
} | ||
module.exports.arch.createKey64 = function (keys, callback) { | ||
module.exports.createKey(keys, OS_ARCH_64BIT, callback) | ||
return module.exports.createKey(keys, OS_ARCH_64BIT, callback) | ||
} | ||
module.exports.arch.deleteKey = function (keys, callback) { | ||
module.exports.deleteKey(keys, OS_ARCH_SPECIFIC, callback) | ||
return module.exports.deleteKey(keys, OS_ARCH_SPECIFIC, callback) | ||
} | ||
module.exports.arch.deleteKey32 = function (keys, callback) { | ||
module.exports.deleteKey(keys, OS_ARCH_32BIT, callback) | ||
return module.exports.deleteKey(keys, OS_ARCH_32BIT, callback) | ||
} | ||
module.exports.arch.deleteKey64 = function (keys, callback) { | ||
module.exports.deleteKey(keys, OS_ARCH_64BIT, callback) | ||
return module.exports.deleteKey(keys, OS_ARCH_64BIT, callback) | ||
} | ||
module.exports.arch.putValue = function (keys, callback) { | ||
module.exports.putValue(keys, OS_ARCH_SPECIFIC, callback) | ||
return module.exports.putValue(keys, OS_ARCH_SPECIFIC, callback) | ||
} | ||
module.exports.arch.putValue32 = function (keys, callback) { | ||
module.exports.putValue(keys, OS_ARCH_32BIT, callback) | ||
return module.exports.putValue(keys, OS_ARCH_32BIT, callback) | ||
} | ||
module.exports.arch.putValue64 = function (keys, callback) { | ||
module.exports.putValue(keys, OS_ARCH_64BIT, callback) | ||
return module.exports.putValue(keys, OS_ARCH_64BIT, callback) | ||
} | ||
@@ -149,3 +199,3 @@ | ||
child.execFile('cscript.exe', args, function (err, stdout, stderr) { | ||
childProcess.execFile('cscript.exe', args, function (err, stdout, stderr) { | ||
@@ -170,16 +220,56 @@ if (err) { | ||
if (stderr) return callback(new Error(stderr)) | ||
if (!stdout) return callback() | ||
debug(stdout) | ||
var result | ||
var result, err | ||
try { | ||
result = JSON.parse(stdout) | ||
} catch (e) { | ||
result = stdout | ||
e.stdout = stdout | ||
err = e | ||
} | ||
callback(null, result) | ||
callback(err, result) | ||
}) | ||
} | ||
function spawn (args) { | ||
debug(args) | ||
return childProcess.spawn('cscript.exe', args, { encoding: 'utf8' }) | ||
} | ||
function handleErrorsAndClose (child, callback) { | ||
var error | ||
child.once('error', function(e) { | ||
debug('process error %s', e) | ||
error = e | ||
}) | ||
child.once('close', function (code) { | ||
debug('process exit with code %d', code) | ||
if (error) { | ||
if (error.code in errors) { | ||
return callback(errors[err.code]) | ||
} else { | ||
return callback(err) | ||
} | ||
} | ||
if (code !== 0) { | ||
if (code in errors) { | ||
return callback(errors[code]) | ||
} else { | ||
return callback(new Error('vbscript process reported unknown error code ' + code)) | ||
} | ||
} | ||
callback() | ||
}) | ||
} | ||
//TODO: move to helper.js? | ||
function renderValueByType(value, type) { | ||
@@ -206,2 +296,3 @@ type = type.toUpperCase() | ||
//TODO: move to helper.js? | ||
function toCommandArgs(cmd, arch, keys) { | ||
@@ -214,3 +305,3 @@ var result = baseCommand(cmd, arch) | ||
} else { | ||
debug('creating command without using keys %s', keys) | ||
debug('creating command without using keys %s', keys ? keys : '') | ||
} | ||
@@ -221,4 +312,5 @@ | ||
//TODO: move to helper.js? | ||
function baseCommand(cmd, arch) { | ||
return ['/Nologo', path.join(__dirname, 'vbs', cmd), arch] | ||
} | ||
return ['//Nologo', path.join(__dirname, 'vbs', cmd), arch] | ||
} |
{ | ||
"name": "regedit", | ||
"version": "0.5.0", | ||
"version": "2.0.0", | ||
"description": "Read, Write, List and do all sorts of funky stuff to the windows registry using node.js and windows script host", | ||
@@ -14,3 +14,5 @@ "keywords": [ | ||
"dependencies": { | ||
"debug": "^2.1.1" | ||
"debug": "^2.1.1", | ||
"stream-slicer": "0.0.6", | ||
"through2": "^0.6.3" | ||
}, | ||
@@ -17,0 +19,0 @@ "author": "Yaniv Kessler", |
127
README.md
@@ -11,3 +11,3 @@ # regedit | ||
## example | ||
## Example | ||
```javascript | ||
@@ -19,5 +19,21 @@ var regedit = require('regedit') | ||
}) | ||
regedit.putValue({ | ||
'HKCU\\SOFTWARE\\MyApp': { | ||
'Company': { | ||
value: 'Moo corp', | ||
type: 'REG_SZ' | ||
}, | ||
'Version': { ... } | ||
}, | ||
'HKLM\\SOFTWARE\\MyApp2': { ... } | ||
}, function(err) { | ||
... | ||
}) | ||
regedit.createKey(['HKLM\\SOFTWARE\\Moo', 'HKCU\\SOFTWARE\\Foo'], function(err) { | ||
... | ||
}) | ||
``` | ||
### Friendly warning regarding 32bit and 64bit OS / Process | ||
#### Friendly warning regarding 32bit and 64bit OS / Process | ||
When launching a 32bit application in 64bit environment, some of your paths will be relative to wow6432node. Things might get a little unexpected if you try to find something you thought was in HKLM\Software when in fact it is located at HKLM\Software\wow6432node. To overcome this the [arch](#regeditarchlist32stringarray-function) methods were added. | ||
@@ -27,5 +43,7 @@ | ||
## API | ||
# API | ||
Every command executes a sub process that runs vbscript code. To boost efficiency, every command supports batching. | ||
## Reading keys and values | ||
### regedit.list([String|Array], [Function]) | ||
@@ -36,3 +54,3 @@ Lists the direct content of one or more sub keys. Specify an array instead of a string to query multiple keys in the same run. | ||
```javascript | ||
regedit.list(['HKCU\\SOFTWARE', 'HKLM\\SOFTWARE', function(err, result) { | ||
regedit.list(['HKCU\\SOFTWARE', 'HKLM\\SOFTWARE'], function(err, result) { | ||
... | ||
@@ -42,3 +60,3 @@ }) | ||
The result will look something like the following: | ||
*Result* will be an object with the following structure: | ||
```javascript | ||
@@ -63,3 +81,3 @@ { | ||
} | ||
... more direct child values of HKCU\\SOFTWARE | ||
... more direct child values of HKLM\\SOFTWARE | ||
} | ||
@@ -70,11 +88,75 @@ } | ||
### regedit.arch.list32([String|Array], [Function]) | ||
same as list, only force a 32bit architecture on the registry | ||
##### Note about listing default values | ||
In the windows registry a key may have a default value. When enumarting value names, the default value's name will be empty. | ||
This presents a minor problem when including the empty value in a set with other values since it cannot be safely named with anything but the empty string, for fear of collision with other values. | ||
### regedit.arch.list64([String|Array], [Function]) | ||
Thus, accessing the default value becomes slightly awkward: | ||
```javascript | ||
regedit.list('path\\to\\default\\value', function (err, result) { | ||
var defaultValue = result['path\\to\\default\\value'].values[''].value | ||
}) | ||
``` | ||
For now this is how its going to be, but in the future this will probably change, possibly in a way that will effect the whole interface. | ||
***list with callback api will be deperecated and eventually removed in future versions, take a look at the streaming interface below*** | ||
### regedit.list([String|Array]) - streaming interface | ||
Same as **regedit.list([String|Array], [Function])** exposes a streaming interface instead of a callback. This is useful for situations where you have a lot of data coming in and out of the list process. Eventually this will completely replace the list() with callback api | ||
Example: | ||
```javascript | ||
regedit.list(['HKCU\\SOFTWARE', 'HKLM\\SOFTWARE']) | ||
.on('data', function(entry) { | ||
console.log(entry.key) | ||
console.log(entry.data) | ||
}) | ||
.on('finish', function () { | ||
console.log('list operation finished') | ||
}) | ||
``` | ||
This code output will look like this: | ||
``` | ||
HKCU\\SOFTWARE | ||
{ | ||
keys: [ 'Google', 'Microsoft', ... more direct sub keys ] | ||
values: { | ||
'valueName': { | ||
value: '123', | ||
type: 'REG_SZ' | ||
} | ||
... more direct child values of HKCU\\SOFTWARE | ||
} | ||
} | ||
HKLM\\SOFTWARE | ||
{ | ||
keys: [ 'Google', 'Microsoft', ... more direct sub keys ] | ||
values: { | ||
'valueName': { | ||
value: '123', | ||
type: 'REG_SZ' | ||
} | ||
... more direct child values of HKLM\\SOFTWARE | ||
} | ||
} | ||
``` | ||
#### regedit.arch.list32([String|Array], [Function]) | ||
same as *regedit.list([String|Array], [Function])*, only force a 32bit architecture on the registry | ||
#### regedit.arch.list32([String|Array]) | ||
streaming interface, see *regedit.list([String|Array])* | ||
#### regedit.arch.list64([String|Array], [Function]) | ||
same as list, only force a 64bit architecture on the registry | ||
### regedit.arch.list([String|Array], [Function]) | ||
#### regedit.arch.list64([String|Array]) | ||
streaming interface, see *regedit.list([String|Array])* | ||
#### regedit.arch.list([String|Array], [Function]) | ||
same as list, only force your system architecture on the registry (select automatically between list64 and list32) | ||
#### regedit.arch.list([String|Array]) | ||
streaming interface, see *regedit.list([String|Array])* | ||
## Manipulating the registry | ||
### regedit.createKey([String|Array], [Function]) | ||
@@ -119,3 +201,26 @@ Creates one or more keys in the registry | ||
- REG_BINARY: an array of numbers (representing bytes) | ||
- REG_DEFAULT: see note about default values below | ||
##### Note about setting default values | ||
When including a default value in a putValue operation, one must use the REG_DEFAULT type. Further more, the name of the value is insignificant since in the registry the default value has no name, but because of the way the node and the vb processes communicate a name must be used. Please note that the only legal value type of a default value is REG_SZ | ||
this is a temporary solution and is subject to change in future versions | ||
```javascript | ||
var values = { | ||
'HKCU\\Software\\MySoftware': { | ||
'someNameIDontCareAbout': { | ||
value: 'Must be a string', | ||
type: 'REG_DEFAULT' | ||
}, | ||
'myValue2': { | ||
value: 'aString', | ||
type: 'REG_SZ' | ||
} | ||
} | ||
} | ||
regedit.putValue(values, function (err) { | ||
}) | ||
``` | ||
For now this is how its going to be, but in the future this will probably change, possibly in a way that will effect the whole interface. | ||
## Develop | ||
@@ -122,0 +227,0 @@ |
@@ -22,3 +22,4 @@ // TODO need to find a better way to test the 32bit/64bit specific scenarios | ||
key.values.should.have.property('ProgramFilesDir') | ||
key.values.ProgramFilesDir.should.have.property('value', 'C:\\Program Files') | ||
key.values.ProgramFilesDir.should.have.property('value') | ||
key.values.ProgramFilesDir.value.indexOf('C:\\Program Files').should.eql(0) | ||
key.values.ProgramFilesDir.should.have.property('type', 'REG_SZ') | ||
@@ -42,3 +43,4 @@ | ||
key.values.should.have.property('ProgramFilesDir') | ||
key.values.ProgramFilesDir.should.have.property('value', 'C:\\Program Files') | ||
key.values.ProgramFilesDir.should.have.property('value') | ||
key.values.ProgramFilesDir.value.indexOf('C:\\Program Files').should.eql(0) | ||
key.values.ProgramFilesDir.should.have.property('type', 'REG_SZ') | ||
@@ -117,2 +119,16 @@ | ||
it.skip('reads unicode characters from the registry - need to manually create', function (done) { | ||
var key = 'HKCU\\software\\ironsource\\' | ||
index.list(key, function(err, result) { | ||
if (err) return done(err) | ||
result[key].should.have.property('keys') | ||
result[key].keys.should.containEql('测试') | ||
done() | ||
}) | ||
}) | ||
it('will fail for unknown hives', function(done) { | ||
@@ -125,2 +141,11 @@ index.list('lala\\software', function(err, result) { | ||
}) | ||
it('lists default values', function (done) { | ||
index.list('HKCR\\Directory\\shell\\cmd\\command', function (err, results) { | ||
if (err) return done(err) | ||
results['HKCR\\Directory\\shell\\cmd\\command'].should.have.property('values') | ||
results['HKCR\\Directory\\shell\\cmd\\command'].values.should.have.property('') | ||
done() | ||
}) | ||
}) | ||
}) | ||
@@ -154,2 +179,17 @@ | ||
it(key + now + '测试', function(done) { | ||
index.createKey(key + now + '测试', function (err) { | ||
if (err) return done(err) | ||
index.list(key, function (err, results) { | ||
if (err) return done(err) | ||
results[key].should.have.property('keys') | ||
results[key].keys.should.containEql(now + '测试') | ||
done() | ||
}) | ||
}) | ||
}) | ||
it(key + now + ' S', function (done) { | ||
@@ -321,3 +361,7 @@ index.arch.createKey(key + now, function(err) { | ||
index.list(key + now, function(err, result) { | ||
if (err) return done(err) | ||
if (err) { | ||
console.error(result) | ||
return done(err) | ||
} | ||
var values = result[key + now].values | ||
@@ -358,2 +402,24 @@ | ||
it('default value in ' + key + now, function(done) { | ||
var values = {} | ||
values[key + now] = { | ||
'default': { | ||
type: 'reg_default', | ||
value: 'default' | ||
} | ||
} | ||
index.putValue(values, function(err) { | ||
index.list(key + now, function (err, results) { | ||
if (err) return done(err) | ||
results[key + now].should.have.property('values') | ||
results[key + now].values.should.have.property('', { | ||
type: 'REG_SZ', | ||
value: 'default' | ||
}) | ||
done() | ||
}) | ||
}) | ||
}) | ||
it('in ' + key + now + ' S', function (done) { | ||
@@ -482,3 +548,3 @@ index.arch.putValue(map, function(err) { | ||
beforeEach(function (done) { | ||
beforeEach(function (done) { | ||
index.createKey(key + now, done) | ||
@@ -485,0 +551,0 @@ map[key + now] = { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
154476
27
1927
0
232
3
2
+ Addedstream-slicer@0.0.6
+ Addedthrough2@^0.6.3
+ Addedcore-util-is@1.0.3(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedisarray@0.0.1(transitive)
+ Addedreadable-stream@1.0.34(transitive)
+ Addedstream-slicer@0.0.6(transitive)
+ Addedstring_decoder@0.10.31(transitive)
+ Addedthrough2@0.6.5(transitive)
+ Addedxtend@4.0.2(transitive)