Skip to content

Commit 0b32c35

Browse files
authored
Merge pull request #16 from tidev/v3
2 parents cd8df3c + 52665db commit 0b32c35

29 files changed

+3158
-1532
lines changed

.gitattributes

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# .gitattributes snippet to force users to use same line endings for project.
2+
#
3+
# Handle line endings automatically for files detected as text
4+
# and leave all files detected as binary untouched.
5+
* text=auto
6+
7+
8+
# These files are text and should be normalized (Convert crlf => lf)
9+
*.php text
10+
*.css text
11+
*.js text eol=lf
12+
*.json text
13+
*.htm text
14+
*.html text
15+
*.xml text
16+
*.txt text
17+
*.ini text
18+
*.inc text
19+
*.pl text
20+
*.rb text
21+
*.py text
22+
*.scm text
23+
*.sql text
24+
.htaccess text
25+
*.sh text
26+
27+
# These files are binary and should be left untouched
28+
# (binary is a macro for -text -diff)
29+
*.png binary
30+
*.jpg binary
31+
*.jpeg binary
32+
*.gif binary
33+
*.ico binary
34+
*.mov binary
35+
*.mp4 binary
36+
*.mp3 binary
37+
*.flv binary
38+
*.fla binary
39+
*.swf binary
40+
*.gz binary
41+
*.zip binary
42+
*.7z binary
43+
*.ttf binary
44+
*.pyc binary

.github/workflows/publish.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
- name: Setup node
1616
uses: actions/setup-node@v4
1717
with:
18-
node-version: 18
18+
node-version: 20
1919
registry-url: 'https://registry.npmjs.org/'
2020

2121
- name: Install pnpm
@@ -26,10 +26,10 @@ jobs:
2626
- name: Install dependencies
2727
run: pnpm install
2828

29+
- name: Lint
30+
run: pnpm check
31+
2932
- name: Publish to npm
3033
env:
31-
GH_TOKEN: ${{ github.token }}
32-
GITHUB_TOKEN: ${{ github.token }}
3334
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
34-
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
3535
run: npm publish --tag ${{ github.event.release.prerelease && 'next' || 'latest' }}

.github/workflows/test.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Tests
2+
3+
on: [push, pull_request]
4+
5+
concurrency:
6+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
7+
group: ${{ github.workflow }}-${{ github.ref }}
8+
9+
jobs:
10+
test:
11+
name: Test on node ${{ matrix.node }}
12+
runs-on: windows-latest
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
node: [18, 20, 22]
17+
18+
steps:
19+
- name: Checkout repository
20+
uses: actions/checkout@v4
21+
22+
- name: Use Node.js ${{ matrix.node }}
23+
uses: actions/setup-node@v4
24+
with:
25+
node-version: ${{ matrix.node }}
26+
27+
- name: Install pnpm
28+
uses: pnpm/action-setup@v2
29+
with:
30+
version: latest
31+
32+
- name: Install dependencies
33+
run: pnpm install
34+
35+
- name: Lint
36+
run: pnpm check
37+
38+
- name: Build
39+
run: pnpm build
40+
41+
- name: Run tests
42+
run: pnpm coverage

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@
22
.DS_Store*
33
.nyc_output
44
.vscode
5+
coverage
6+
dist
57
/build
68
/prebuilds
79
junit.xml
810
node_modules
911
npm-debug.log
10-
yarn-error.log
12+
.pnpm-debug.log
13+
tmp
14+
*.tsbuildinfo
15+
*.tgz

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
# v3.0.0
2+
3+
* BREAKING CHANGE: Require Node.js 18.17 or newer.
4+
* fix: Fixed order of child key events when parent key is deleted.
5+
* fix: Fixed seg fault during cleanup that occurs when using winreglib in a
6+
worker.
7+
* fix: Fixed bug where the Windows Registry worker thread was being spawned
8+
when adding the first listener. The idea was don't spawn the thread until
9+
there was a listener, however thread shutdown is async and not worth the
10+
hassle in a destructor, so now the background thread is always running.
11+
112
# v2.0.4 (July 2, 2024)
213

314
* fix: Fixed crash when app exits (thanks TitusQian)

README.md

Lines changed: 124 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,37 @@
1-
# Windows Registry Utility Library
1+
<br>
2+
<div align="center">
3+
<img width="640" height="240" src="media/winreglib.webp" alt="winreglib">
4+
</div>
5+
<br>
26

3-
A library for querying and watching the Windows Registry.
7+
`winreglib` is a native C++ addon for Node.js for querying and watching Windows
8+
Registry keys. It provides a read-only, synchronous API for accessing the
9+
Windows Registry.
410

5-
## Prerequisites
11+
## Features
612

7-
`winreglib` requires N-API version 3 and the following Node.js versions:
13+
- Get, list, and watch registry keys _without_ spawning `reg.exe`
14+
- Written in TypeScript
15+
- Packaged as an ESM module
16+
- Supports x64 (64-bit) and ia32 (32-bit) CPU architectures
817

9-
* v10.2.0 or newer
18+
## Requirements
1019

11-
## Installation
12-
13-
npm install winreglib
14-
15-
## Introduction
16-
17-
`winreglib` is a native Node.js addon for querying the Windows Registry. The API is synchronous.
18-
19-
Currently `winreglib` only supports read operations. It can support write operations someday if
20-
need and time exists.
20+
`winreglib` requires Node.js >=18.17.0 (Node-API 8) and ships with pre-built
21+
binaries for x64 and ia32 architectures. ARM-based architectures are not
22+
officially supported, but should technically work as long as you have the
23+
build tools installed.
2124

2225
## Example
2326

24-
```js
27+
```javascript
2528
import winreglib from 'winreglib';
2629

2730
const key = 'HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion';
2831
const results = winreglib.list(key);
2932

30-
console.log(`${results.root}\\${results.path}`);
33+
console.log(`Resolved ${results.resolvedRoot}`);
34+
console.log(`${results.key} has ${results.subkeys.length} subkeys`);
3135

3236
console.log(' Subkeys:');
3337
for (const subkey of results.subkeys) {
@@ -40,6 +44,20 @@ for (const valueName of results.values) {
4044
}
4145
```
4246

47+
## Supported Root Keys
48+
49+
| Name | Abbreviation |
50+
| ---------------------------------- | ------------ |
51+
| `HKEY_CLASSES_ROOT` | `HKCR` |
52+
| `HKEY_CURRENT_CONFIG` | `HKCC` |
53+
| `HKEY_CURRENT_USER` | `HKCU` |
54+
| `HKEY_CURRENT_USER_LOCAL_SETTINGS` | |
55+
| `HKEY_LOCAL_MACHINE` | `HKLM` |
56+
| `HKEY_PERFORMANCE_DATA` | |
57+
| `HKEY_PERFORMANCE_NLSTEXT` | |
58+
| `HKEY_PERFORMANCE_TEXT` | |
59+
| `HKEY_USERS` | `HKU` |
60+
4361
## API
4462

4563
### `get(key, valueName)`
@@ -51,12 +69,16 @@ Get a value for the given key and value name.
5169
| `key` | String | The key beginning with the root. |
5270
| `valueName` | String | The name of the value to get. |
5371

54-
Returns a `String`, `Number`, `Buffer`, `Array.<String>`, or `null` depending on the value.
72+
Returns a `String`, `Number`, `Buffer`, `Array.<String>`, or `null`
73+
depending on the value.
5574

5675
If `key` or `valueName` is not found, an `Error` is thrown.
5776

5877
```js
59-
const value = winreglib.get('HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion', 'ProgramFilesDir');
78+
const value = winreglib.get(
79+
'HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion',
80+
'ProgramFilesDir'
81+
);
6082

6183
console.log(value);
6284
```
@@ -73,20 +95,31 @@ Retreives all subkeys and value names for a give key.
7395
| -------- | ------ | -------------------------------- |
7496
| `key` | String | The key beginning with the root. |
7597

76-
Returns an `Object` with the resolved `resolvedRoot` (String), `key` (String), `subkeys`
77-
(Array[String]), and `values` (Array[String]).
98+
Returns an `RegistryKey` object:
99+
100+
```
101+
type RegistryKey = {
102+
resolvedRoot: string;
103+
key: string;
104+
subkeys: string[];
105+
values: unknown[];
106+
};
107+
```
78108

79109
If `key` is not found, an `Error` is thrown.
80110

81111
```js
82-
const result = winreglib.list('HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup');
112+
const result = winreglib.list(
113+
'HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup
114+
);
83115
84116
console.log(result);
85117
```
86118
87119
```js
88120
{ resolvedRoot: 'HKEY_LOCAL_MACHINE',
89-
key: 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup',
121+
key:
122+
'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup',
90123
subkeys:
91124
[ 'DPI',
92125
'ImageServicingData',
@@ -109,8 +142,8 @@ Watches a key for changes in subkeys or values.
109142
| -------- | ------ | -------------------------------- |
110143
| `key` | String | The key beginning with the root. |
111144
112-
Returns a handle (`EventEmitter`) that emits `"change"` events. Call `handle.stop()` to stop watching
113-
the key.
145+
Returns a handle (`WinRegLibWatchHandle` which extends `EventEmitter`) that
146+
emits `"change"` events. Call `handle.stop()` to stop watching the key.
114147
115148
```js
116149
const handle = winreglib.watch('HKLM\\SOFTWARE');
@@ -120,44 +153,92 @@ handle.on('change', evt => {
120153
});
121154
```
122155
123-
The `"change"` event object contains a change `"type"` and the affected `"key"`.
156+
The `"change"` event object contains a change `"type"` and the affected
157+
`"key"`.
124158
125159
| Event Type | Description |
126160
| ---------- | ---------------------------------- |
127161
| `add` | The `key` was added. |
128162
| `change` | A subkey or value was added, changed, deleted, or permissions modified, but we don't know exactly what. |
129163
| `delete` | The `key` was deleted. |
130164

131-
`watch()` can track keys that do not exist and when they are created, a change event will be
132-
emitted. You can watch the same key multiple times, however each returned handle is unique and you
133-
must call `handle.stop()` for each.
165+
`watch()` can track keys that do not exist and when they are created, a
166+
change event will be emitted. You can watch the same key multiple times,
167+
however each returned handle is unique and you must call `handle.stop()` for
168+
each.
134169

135-
Due to limitations of the Win32 API, `watch()` is unable to determine what actually changed during
136-
a `change` event type. You will need to call `list()` and cache the subkeys and values, then call
137-
`list()` again when a change is emitted and compare the before and after.
170+
Due to limitations of the Win32 API, `watch()` is unable to determine what
171+
actually changed during a `change` event type. You will need to call `list()`
172+
and cache the subkeys and values, then call `list()` again when a change is
173+
emitted and compare the before and after.
138174

139-
Note that `watch()` does not support recursively watching for changes.
175+
Note that `watch()` does not support recursively watching for changes. The
176+
Win32 API does support recursive watching, so this could be added in the
177+
future.
140178

141179
## Advanced
142180

143181
### Debug Logging
144182

145-
`winreglib` exposes an event emitter that emits debug log messages. This is intended to help debug
146-
issues under the hood. The average user will never need to use this, however it would be handy when
147-
filing a bug.
183+
`winreglib` exposes an event emitter that emits debug log messages. This is
184+
intended to help debug issues under the hood. The average user will never
185+
need to use this, however it would be handy when filing a bug.
148186

149187
```js
150188
winreglib.on('log', msg => console.log(msg));
151189
```
152190

153-
Alternatively, `winreglib` uses the amazing [`snooplogg`][2] debug logger where you simply set the
154-
`SNOOPLOGG` environment variable to `winreglib` (or `*`) and it will print the debug log to stdout.
191+
Alternatively, `winreglib` uses the amazing [`snooplogg`][2] debug logger
192+
where you simply set the `SNOOPLOGG` environment variable to `winreglib` (or
193+
`*`) and it will print the debug log to `stderr`.
194+
195+
```bash
196+
$ SNOOPLOGG=winreglib node myapp.js
197+
6.150s winreglib:Watchman Initializing async work (thread 16764576586047274673)
198+
6.150s winreglib:Watchman::run Initializing run loop (thread 12502165600786624632)
199+
6.151s winreglib:Watchman::run Populating active copy (count=0)
200+
6.151s winreglib:Watchman::run Waiting on 2 objects...
201+
6.152s winreglib:list key="HKLM" subkey="SOFTWARE\Microsoft\Windows\CurrentVersion"
202+
6.152s winreglib:list 170 keys (max 30), 11 values (max 24)
203+
```
204+
205+
### Building `winreglib`
206+
207+
`winreglib` has two components: the public interface written in TypeScript and
208+
the native addon written in C++.
209+
210+
To compile the C++ code, you will need the Microsoft Visual Studio (not VSCode)
211+
or the Microsoft Build Tools. You may also need Python 3 installed.
212+
213+
| Command | Description |
214+
| -------------------- | ----------- |
215+
| `pnpm build` | Compiles the TypeScript and the Node.js native C++ addon for the current architecture |
216+
| `pnpm build:bundle` | Compiles only the TypeScript code |
217+
| `pnpm build:local` | Compiles only the Node.js native C++ addon |
218+
| `pnpm rebuild:local` | Cleans and re-compiles only the Node.js native C++ addon |
219+
220+
When publishing, the native C++ addon is prebuilt for x64 and ia32
221+
architectures. Generally you shouldn't need be concerned with the prebuilt
222+
binaries, however the following commands will compile the prebuilds:
223+
224+
| Command | Description |
225+
| --------------------- | ------------------------------ |
226+
| `pnpm build:prebuild` | Prebuild for x64 and ia32 |
227+
| `pnpm prebuild-arm` | Prebuild for arm (32-bit) |
228+
| `pnpm prebuild-arm64` | Prebuild for arm64 |
229+
| `pnpm prebuild-ia32` | Prebuild for ia32 (x86 32-bit) |
230+
| `pnpm prebuild-x64` | Prebuild for x64 |
231+
232+
### Architecture
233+
234+
When `winreglib` is imported, it immediately spawns a background thread in the
235+
event the app is going to watch a key. If a key is added/changed/deleted, the
236+
background thread sends a message to the main thread which emits the change
237+
event.
155238
156-
## License
239+
## Legal
157240
158-
This project is open source under the [Apache Public License v2][1] and is developed by
159-
[Axway, Inc](http://www.axway.com/) and the community. Please read the [`LICENSE`][1] file included
160-
in this distribution for more information.
241+
Titanium is a registered trademark of TiDev Inc. All Titanium trademark and patent rights were transferred and assigned to TiDev Inc. on 4/7/2022. Please see the LEGAL information about using our trademarks, privacy policy, terms of usage and other legal information at https://tidev.io/legal.
161242
162-
[1]: https://github.com/appcelerator/winreglib/blob/master/LICENSE
243+
[1]: https://github.com/tidev/winreglib/blob/master/LICENSE
163244
[2]: https://www.npmjs.com/package/snooplogg

0 commit comments

Comments
 (0)