@flun/windows 4.0.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -11
- package/README.md +33 -33
- package/bin/cli.js +43 -35
- package/copy-files.js +5 -4
- package/index.d.ts +25 -25
- package/index.js +1 -1
- package/lib/binaries.js +21 -21
- package/lib/daemon.js +14 -14
- package/lib/eventlog.js +1 -1
- package/lib/shared.js +14 -14
- package/lib/winsw.js +7 -7
- package/lib/wrapper.js +2 -2
- package/package.json +65 -61
- package/win-service.config.js +7 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# 变更日志
|
|
2
2
|
|
|
3
|
+
## [5.0.0] - 2026-11-13 11:48
|
|
4
|
+
### 破坏性变更
|
|
5
|
+
- 命令行服务管理改为 `windows s <命令>`,`s` 可写全称 `service`;原 `windows install` 等形式不再支持;
|
|
6
|
+
动机:`windows` 既是包名又是平台名,直接跟子命令语义不清;
|
|
7
|
+
- `win-service.config.js` 改为具名声明 `winServiceConfig`,并同时提供默认导出与命名导出;
|
|
8
|
+
`import x from` 与 `import { winServiceConfig } from` 均可用,但不再为匿名 `export default`;
|
|
9
|
+
|
|
10
|
+
### 优化
|
|
11
|
+
- 全包 JS 与 `.d.ts` 的导入、声明、导出顺序按规范统一;导入按项目外依赖在前、相对路径在后各自字母序;
|
|
12
|
+
导入花括号内按被导入项在源模块的类型分组;声明与导出按变量 > 函数 > 类分组;
|
|
13
|
+
- JSDoc 补全 `@see`、`@param`、`@returns`,并使 `@see` 位于所有其它 `@` 条目前;
|
|
14
|
+
|
|
15
|
+
### 修复
|
|
16
|
+
- 各文件 JSDoc 示例中 `win-service.config.js` 的导入名与 `new Service(...)` 实参不一致;
|
|
17
|
+
- `index.d.ts` 主聚合块的代码块、`@see`、`declare module` 导出三处顺序不一致,现同序;
|
|
18
|
+
- `binaries.js` 的 `platform` JSDoc 在导入重排后与其声明分离,现随声明一同移动;
|
|
19
|
+
|
|
20
|
+
### 文档
|
|
21
|
+
- README 命令行章节同步为 `windows s <命令>` 形式,命令表、状态码说明、示例一并更新;
|
|
22
|
+
|
|
23
|
+
## [4.0.1] - 2026-11-06 10:24
|
|
24
|
+
### 优化
|
|
25
|
+
- 优化了部分细节;
|
|
26
|
+
|
|
3
27
|
## [4.0.0] - 2026-11-03 22:34
|
|
4
28
|
### 破坏性变更
|
|
5
29
|
- `Service#install()` 默认在安装成功后启动服务;旧行为只安装不启动,如需保持旧行为传 `autoStart = false`;
|
|
@@ -23,14 +47,4 @@
|
|
|
23
47
|
### 文档
|
|
24
48
|
- README 新增「命令行」章节,含快速开始、命令表(按服务类与其它分组)、命令行参数、服务配置;
|
|
25
49
|
- README 新增「参考配置」章节,逐字段说明含义与默认值;
|
|
26
|
-
- README 函数方式示例改为导入 `win-service.config.js`,并补 `quiet` 说明;
|
|
27
|
-
|
|
28
|
-
## [3.0.11] - 2026-10-25 15:57
|
|
29
|
-
### 优化
|
|
30
|
-
- 项目标点已改为以英文标点为主;
|
|
31
|
-
- 行宽改为以 123 为主,部分超宽表格改为了列表;
|
|
32
|
-
|
|
33
|
-
## [3.0.10] - 2026-09-29 19:29
|
|
34
|
-
### 更改
|
|
35
|
-
- 加固了拷贝文件的一些逻辑;
|
|
36
|
-
- 升级了依赖;
|
|
50
|
+
- README 函数方式示例改为导入 `win-service.config.js`,并补 `quiet` 说明;
|
package/README.md
CHANGED
|
@@ -33,8 +33,9 @@
|
|
|
33
33
|
|
|
34
34
|
```
|
|
35
35
|
@flun/windows/
|
|
36
|
-
├──
|
|
37
|
-
├──
|
|
36
|
+
├── bin/winsw/ winsw 可执行文件(内部资源,非命令)
|
|
37
|
+
├── bin/cli.js 命令行入口
|
|
38
|
+
├── bin/elevate.vbs UAC 提权脚本(内部资源,非命令)
|
|
38
39
|
├── lib/binaries.js 外部二进制定位与提权调用
|
|
39
40
|
├── lib/cmd.js 进程列表与终止
|
|
40
41
|
├── lib/daemon.js Windows 服务管理类
|
|
@@ -42,15 +43,14 @@
|
|
|
42
43
|
├── lib/winsw.js winsw 配置生成
|
|
43
44
|
├── lib/wrapper.js 进程包装器
|
|
44
45
|
├── lib/shared.js 共享工具函数
|
|
45
|
-
├── bin/winsw/ winsw 可执行文件(内部资源,非命令)
|
|
46
|
-
├── bin/elevate.vbs UAC 提权脚本(内部资源,非命令)
|
|
47
|
-
├── bin/cli.js 命令行入口
|
|
48
|
-
├── win-service.config.js 服务配置模板(全量字段,必填项带 *)
|
|
49
|
-
├── copy-files.js postinstall 复制二进制资源
|
|
50
|
-
├── package.json 包配置
|
|
51
46
|
├── README.md 本文件
|
|
52
47
|
├── CHANGELOG.md 更新日志
|
|
53
|
-
|
|
48
|
+
├── copy-files.js postinstall 复制二进制资源
|
|
49
|
+
├── index.js 库入口,导出 elevate / sudo / isAdminUser / kill / list / Service / EventLogger
|
|
50
|
+
├── win-service.config.js 服务配置模板(全量字段,必填项带 *)
|
|
51
|
+
├── index.d.ts 类型声明
|
|
52
|
+
├── LICENSE 许可
|
|
53
|
+
└── package.json 包配置
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
## 安装前准备
|
|
@@ -107,9 +107,9 @@ windows <命令> [--键 值]
|
|
|
107
107
|
编辑`win-service.config.js`文件,填写带 `*` 的必填项 `name` 与 `script`;
|
|
108
108
|
|
|
109
109
|
```bash
|
|
110
|
-
windows install # 按配置文件安装并启动服务
|
|
110
|
+
windows s install # 按配置文件安装并启动服务
|
|
111
111
|
|
|
112
|
-
windows install --name MyApp --script D:\app\main.js # 带参安装并启动
|
|
112
|
+
windows s install --name MyApp --script D:\app\main.js # 带参安装并启动
|
|
113
113
|
```
|
|
114
114
|
|
|
115
115
|
安装后默认启动服务;若只需安装,加 `--no-start`;
|
|
@@ -120,16 +120,16 @@ windows install --name MyApp --script D:\app\main.js # 带参安装并启动
|
|
|
120
120
|
|
|
121
121
|
#### 服务类
|
|
122
122
|
|
|
123
|
-
| 命令
|
|
124
|
-
|
|
|
125
|
-
| `install` | 安装服务,装完默认启动;`--no-start` 只装不启动 |
|
|
126
|
-
| `uninstall` | 卸载服务 |
|
|
127
|
-
| `start` | 启动服务 |
|
|
128
|
-
| `stop` | 停止服务 |
|
|
129
|
-
| `restart` | 重启服务 |
|
|
130
|
-
| `status` | 查询状态,输出 0-3 |
|
|
131
|
-
| `xml` | 输出 winsw 配置 XML |
|
|
132
|
-
| `exe [--dir 目录]` | 生成 winsw 可执行文件 |
|
|
123
|
+
| 命令 | 说明 |
|
|
124
|
+
| -------------------- | --------------------------------------------- |
|
|
125
|
+
| `s install` | 安装服务,装完默认启动;`--no-start` 只装不启动 |
|
|
126
|
+
| `s uninstall` | 卸载服务 |
|
|
127
|
+
| `s start` | 启动服务 |
|
|
128
|
+
| `s stop` | 停止服务 |
|
|
129
|
+
| `s restart` | 重启服务 |
|
|
130
|
+
| `s status` | 查询状态,输出 0-3 |
|
|
131
|
+
| `s xml` | 输出 winsw 配置 XML |
|
|
132
|
+
| `s exe [--dir 目录]` | 生成 winsw 可执行文件 |
|
|
133
133
|
|
|
134
134
|
#### 其它
|
|
135
135
|
|
|
@@ -143,7 +143,7 @@ windows install --name MyApp --script D:\app\main.js # 带参安装并启动
|
|
|
143
143
|
| `example` | 生成 `win-service.config.js` 模板到当前项目 |
|
|
144
144
|
| `help` | 显示帮助 |
|
|
145
145
|
|
|
146
|
-
`status` 输出状态码:`0` 不存在;`1` 有服务无文件;`2` 有文件无服务;`3` 完整存在;
|
|
146
|
+
`s status` 输出状态码:`0` 不存在;`1` 有服务无文件;`2` 有文件无服务;`3` 完整存在;
|
|
147
147
|
|
|
148
148
|
`log` 的级别取 `info`、`warn`、`error`、`success`、`failure`;`success` 与 `failure`
|
|
149
149
|
分别对应 `auditSuccess` 与 `auditFailure`;可加 `--source <名>` 指定事件源,`--id <号>` 指定事件 ID;
|
|
@@ -154,13 +154,13 @@ windows install --name MyApp --script D:\app\main.js # 带参安装并启动
|
|
|
154
154
|
# 前提:win-service.config.js 已提供 name 与 script;以下每条只覆盖部分字段
|
|
155
155
|
|
|
156
156
|
# 1. 覆盖描述:装出的服务在服务管理器中显示为该描述
|
|
157
|
-
windows install --description "我的服务"
|
|
157
|
+
windows s install --description "我的服务"
|
|
158
158
|
|
|
159
159
|
# 2. 覆盖 node 启动参数:服务以 --harmony 模式运行
|
|
160
|
-
windows install --nodeOptions '["--harmony"]'
|
|
160
|
+
windows s install --nodeOptions '["--harmony"]'
|
|
161
161
|
|
|
162
162
|
# 3. 打开出错退出:脚本运行出错时进程直接退出(省略值即 true)
|
|
163
|
-
windows install --abortOnError
|
|
163
|
+
windows s install --abortOnError
|
|
164
164
|
```
|
|
165
165
|
|
|
166
166
|
字符串值用双引号,JSON 值用单引号(避免 shell 解析方括号);值先按 JSON 解析,失败则按字符串处理;
|
|
@@ -175,9 +175,9 @@ windows install --abortOnError
|
|
|
175
175
|
```js
|
|
176
176
|
// 创建并安装一个 Windows 服务:
|
|
177
177
|
import { Service } from '@flun/windows';
|
|
178
|
-
import
|
|
178
|
+
import winServiceConfig from './win-service.config.js';
|
|
179
179
|
|
|
180
|
-
const svc = new Service(
|
|
180
|
+
const svc = new Service(winServiceConfig);
|
|
181
181
|
|
|
182
182
|
// 安装并自动启动服务(默认)
|
|
183
183
|
svc.install();
|
|
@@ -209,9 +209,9 @@ svc.install();
|
|
|
209
209
|
|
|
210
210
|
```js
|
|
211
211
|
import { Service } from '@flun/windows';
|
|
212
|
-
import
|
|
212
|
+
import winServiceConfig from './win-service.config.js';
|
|
213
213
|
|
|
214
|
-
const svc = new Service(
|
|
214
|
+
const svc = new Service(winServiceConfig);
|
|
215
215
|
|
|
216
216
|
// 安装并自动启动服务(默认)
|
|
217
217
|
svc.install();
|
|
@@ -273,9 +273,9 @@ export default {
|
|
|
273
273
|
|
|
274
274
|
```js
|
|
275
275
|
import { Service } from '@flun/windows';
|
|
276
|
-
import
|
|
276
|
+
import winServiceConfig from './win-service.config.js';
|
|
277
277
|
|
|
278
|
-
const svc = new Service(
|
|
278
|
+
const svc = new Service(winServiceConfig);
|
|
279
279
|
|
|
280
280
|
// 安装后指定特定用户或凭据以登录运行
|
|
281
281
|
svc.logOnAs.domain = 'mydomain.local';
|
|
@@ -291,9 +291,9 @@ svc.logOnAs.mungeCredentialsAfterInstall = true; // 默认
|
|
|
291
291
|
|
|
292
292
|
```js
|
|
293
293
|
import { Service } from '@flun/windows';
|
|
294
|
-
import
|
|
294
|
+
import winServiceConfig from './win-service.config.js';
|
|
295
295
|
|
|
296
|
-
const svc = new Service(
|
|
296
|
+
const svc = new Service(winServiceConfig);
|
|
297
297
|
svc.on('uninstall', ()=>{
|
|
298
298
|
console.log('卸载完成');
|
|
299
299
|
console.log('服务是否存在:', svc.exists);
|
package/bin/cli.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { execSync } from 'child_process';
|
|
2
4
|
import fs from 'fs';
|
|
3
5
|
import path from 'path';
|
|
4
|
-
import { execSync } from 'child_process';
|
|
5
6
|
import { pathToFileURL } from 'url';
|
|
6
|
-
import chalk from 'chalk';
|
|
7
|
-
import { Service, kill, list, elevate, EventLogger } from '../index.js';
|
|
8
7
|
import { copyFile } from '../copy-files.js';
|
|
8
|
+
import { elevate, kill, list, EventLogger, Service } from '../index.js';
|
|
9
9
|
|
|
10
10
|
const [, , sub, ...args] = process.argv,
|
|
11
11
|
/**
|
|
@@ -122,19 +122,19 @@ const [, , sub, ...args] = process.argv,
|
|
|
122
122
|
* 输出用法;
|
|
123
123
|
*/
|
|
124
124
|
printHelp = () => {
|
|
125
|
-
const cmd = (name, desc) => `
|
|
125
|
+
const cmd = (name, desc) => ` ${chalk.cyanBright(name.padEnd(26))}${chalk.gray(desc)}`;
|
|
126
126
|
console.log([
|
|
127
|
-
|
|
128
|
-
`
|
|
129
|
-
cmd('install', '安装服务,装完默认启动;--no-start 关闭自动启动'),
|
|
130
|
-
cmd('uninstall', '卸载服务'),
|
|
131
|
-
cmd('start', '启动服务'),
|
|
132
|
-
cmd('stop', '停止服务'),
|
|
133
|
-
cmd('restart', '重启服务'),
|
|
134
|
-
cmd('status', '
|
|
135
|
-
cmd('xml', '输出 winsw 配置 XML'),
|
|
136
|
-
cmd('exe', '生成 winsw 可执行文件;--dir
|
|
137
|
-
`
|
|
127
|
+
` ${chalk.blueBright('用法:')} windows <命令> [--键 值]`, '',
|
|
128
|
+
` ${chalk.cyan('服务')} ${chalk.gray('(windows s|service;读 win-service.config.js)')}`,
|
|
129
|
+
cmd('s install', '安装服务,装完默认启动;--no-start 关闭自动启动'),
|
|
130
|
+
cmd('s uninstall', '卸载服务'),
|
|
131
|
+
cmd('s start', '启动服务'),
|
|
132
|
+
cmd('s stop', '停止服务'),
|
|
133
|
+
cmd('s restart', '重启服务'),
|
|
134
|
+
cmd('s status', '查询状态;0 不存在 1 有服务无文件 2 有文件无服务 3 完整'),
|
|
135
|
+
cmd('s xml', '输出 winsw 配置 XML'),
|
|
136
|
+
cmd('s exe', '生成 winsw 可执行文件;--dir 指定输出目录,默认 daemon'), '',
|
|
137
|
+
` ${chalk.cyan('其它')}`,
|
|
138
138
|
cmd('example', '生成 win-service.config.js 模板到当前项目'),
|
|
139
139
|
cmd('list', '列出运行中的进程;--verbose 显示详细信息'),
|
|
140
140
|
cmd('kill', '结束进程,参数为进程 PID;例如 kill 1234,--force 强制结束'),
|
|
@@ -150,6 +150,30 @@ const [, , sub, ...args] = process.argv,
|
|
|
150
150
|
*/
|
|
151
151
|
main = async () => {
|
|
152
152
|
if (!sub || sub === 'help' || sub === '-h' || sub === '--help') return printHelp(), process.exit(0);
|
|
153
|
+
if (sub === 's' || sub === 'service') {
|
|
154
|
+
const [svcCmd, ...svcArgs] = args;
|
|
155
|
+
if (!svcCmd || svcCmd === 'help' || svcCmd === '-h' || svcCmd === '--help') return printHelp(), process.exit(0);
|
|
156
|
+
if (svcCmd === 'xml') {
|
|
157
|
+
const { svc } = await buildService(svcArgs);
|
|
158
|
+
return console.log(svc.toXml()), process.exit(0);
|
|
159
|
+
}
|
|
160
|
+
if (svcCmd === 'exe') {
|
|
161
|
+
const { svc, flags } = await buildService(svcArgs);
|
|
162
|
+
try { await svc.toExe(flags.dir), console.log(chalk.green('✓ 已生成: ') + svc.root), process.exit(0) }
|
|
163
|
+
catch (e) { console.error(chalk.red('✗ ') + e.message), process.exit(1) }
|
|
164
|
+
}
|
|
165
|
+
if (svcCmd === 'status') {
|
|
166
|
+
const { svc } = await buildService(svcArgs), code = svc.exists,
|
|
167
|
+
color = code === 3 ? chalk.green : code === 0 ? chalk.red : chalk.yellow;
|
|
168
|
+
return console.log(chalk.gray('状态码: ') + color(code)), process.exit(0);
|
|
169
|
+
}
|
|
170
|
+
if (['install', 'uninstall', 'start', 'stop', 'restart'].includes(svcCmd)) {
|
|
171
|
+
try { await runService(svcCmd, svcArgs), process.exit(0) }
|
|
172
|
+
catch (e) { console.error(chalk.red('✗ ') + e.message), process.exit(1) }
|
|
173
|
+
}
|
|
174
|
+
console.error(chalk.red('✗ 未知服务命令: ') + chalk.yellow(svcCmd));
|
|
175
|
+
console.log(''), printHelp(), process.exit(1);
|
|
176
|
+
}
|
|
153
177
|
if (sub === 'example') return copyFile() ? process.exit(0) : process.exit(1);
|
|
154
178
|
if (sub === 'is-admin') {
|
|
155
179
|
try {
|
|
@@ -185,8 +209,10 @@ const [, , sub, ...args] = process.argv,
|
|
|
185
209
|
const { flags, rest } = parseFlags(args), [level, ...msgParts] = rest,
|
|
186
210
|
methodMap = { info: 'info', warn: 'warn', error: 'error', success: 'auditSuccess', failure: 'auditFailure' },
|
|
187
211
|
method = methodMap[level];
|
|
188
|
-
if (!method)
|
|
189
|
-
|
|
212
|
+
if (!method) {
|
|
213
|
+
console.error(chalk.red('✗ ') + `未知级别: ${level};可用:info|warn|error|success|failure`);
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
190
216
|
if (!msgParts.length) return console.error(chalk.red('✗ ') + '缺少消息'), process.exit(1);
|
|
191
217
|
const logger = new EventLogger(flags.source ? { source: flags.source } : {});
|
|
192
218
|
return logger[method](msgParts.join(' '), flags.id ?? 1000, err => {
|
|
@@ -194,24 +220,6 @@ const [, , sub, ...args] = process.argv,
|
|
|
194
220
|
console.log(chalk.green('✓ ') + chalk.greenBright('已写入')), process.exit(0);
|
|
195
221
|
});
|
|
196
222
|
}
|
|
197
|
-
if (sub === 'xml') {
|
|
198
|
-
const { svc } = await buildService(args);
|
|
199
|
-
return console.log(svc.toXml()), process.exit(0);
|
|
200
|
-
}
|
|
201
|
-
if (sub === 'exe') {
|
|
202
|
-
const { svc, flags } = await buildService(args);
|
|
203
|
-
try { await svc.toExe(flags.dir), console.log(chalk.green('✓ 已生成: ') + svc.root), process.exit(0) }
|
|
204
|
-
catch (e) { console.error(chalk.red('✗ ') + e.message), process.exit(1) }
|
|
205
|
-
}
|
|
206
|
-
if (sub === 'status') {
|
|
207
|
-
const { svc } = await buildService(args), code = svc.exists,
|
|
208
|
-
color = code === 3 ? chalk.green : code === 0 ? chalk.red : chalk.yellow;
|
|
209
|
-
return console.log(chalk.gray('状态码: ') + color(code)), process.exit(0);
|
|
210
|
-
}
|
|
211
|
-
if (['install', 'uninstall', 'start', 'stop', 'restart'].includes(sub)) {
|
|
212
|
-
try { await runService(sub, args), process.exit(0) }
|
|
213
|
-
catch (e) { console.error(chalk.red('✗ ') + e.message), process.exit(1) }
|
|
214
|
-
}
|
|
215
223
|
console.error(chalk.red('✗ 未知命令: ') + chalk.yellow(sub)), console.log(''), printHelp(), process.exit(1);
|
|
216
224
|
};
|
|
217
225
|
|
package/copy-files.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
1
2
|
import fs from 'fs';
|
|
2
3
|
import path from 'path';
|
|
3
4
|
import { fileURLToPath } from 'url';
|
|
@@ -13,19 +14,19 @@ const __filename = fileURLToPath(import.meta.url), __dirname = path.dirname(__fi
|
|
|
13
14
|
* @returns {boolean} - 复制是否成功
|
|
14
15
|
*/
|
|
15
16
|
const copyFile = () => {
|
|
16
|
-
console.log(
|
|
17
|
+
console.log(chalk.gray('项目根目录: ') + targetDir);
|
|
17
18
|
try {
|
|
18
19
|
// 目标目录不是 Node 项目 || 包自身的 npm install(开发调试)→ 跳过
|
|
19
20
|
if (!fs.existsSync(path.join(targetDir, 'package.json'))) return true;
|
|
20
21
|
if (targetDir === path.resolve(__dirname, '..')) return true;
|
|
21
22
|
if (fs.existsSync(targetFile)) return true; // 目标文件已存在 → 直接返回
|
|
22
|
-
console.log(
|
|
23
|
+
console.log(chalk.cyan('· ') + `未找到 ${fileName},正在创建...`);
|
|
23
24
|
|
|
24
25
|
fs.copyFileSync(sourceFile, targetFile); // 复制源文件到项目根目录
|
|
25
|
-
console.log(
|
|
26
|
+
console.log(chalk.green('✓ ') + chalk.greenBright(`已生成 ${fileName}: `) + chalk.gray(targetFile));
|
|
26
27
|
return true;
|
|
27
28
|
} catch (error) {
|
|
28
|
-
console.error(
|
|
29
|
+
console.error(chalk.red('✗ ') + `创建 ${fileName} 失败: ` + error.message);
|
|
29
30
|
return false;
|
|
30
31
|
}
|
|
31
32
|
};
|
package/index.d.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { platform, elevate, isAdminUser, sudo } from './lib/binaries.js';
|
|
2
2
|
import { kill, list } from './lib/cmd.js';
|
|
3
3
|
import { Service } from './lib/daemon.js';
|
|
4
4
|
import { EventLogger } from './lib/eventlog.js';
|
|
5
5
|
import {
|
|
6
|
-
exec, execSync, fork,
|
|
6
|
+
EventEmitter, exec, execSync, fork, fs, path, promisify, execPromise, getDirname, isPermissionError
|
|
7
7
|
} from './lib/shared.js';
|
|
8
|
-
import {
|
|
8
|
+
import { createExe, generateXml } from './lib/winsw.js';
|
|
9
9
|
|
|
10
10
|
// =================================== lib/binaries.js ===================================
|
|
11
11
|
/**
|
|
12
12
|
* ```js
|
|
13
13
|
* // 文件导出内容
|
|
14
|
+
* platform(); // 获取操作系统平台字符串,用于判断当前运行环境是否为Windows
|
|
14
15
|
* elevate(); // 提升当前进程权限(Windows UAC)
|
|
15
|
-
* sudo(); // 使用sudo.exe提升权限(适用于Windows 10及以上版本)
|
|
16
16
|
* isAdminUser(); // 检查当前用户是否拥有管理员权限
|
|
17
|
-
*
|
|
17
|
+
* sudo(); // 使用sudo.exe提升权限(适用于Windows 10及以上版本)
|
|
18
18
|
* ```
|
|
19
|
-
* >查看定义:@see {@link
|
|
19
|
+
* >查看定义:@see {@link platform}、{@link elevate}、{@link isAdminUser}、{@link sudo}
|
|
20
20
|
*/
|
|
21
21
|
declare module './lib/binaries.js' {
|
|
22
22
|
export * from './lib/binaries.js';
|
|
@@ -63,22 +63,22 @@ declare module './lib/eventlog.js' {
|
|
|
63
63
|
/**
|
|
64
64
|
* 共享模块,导出在多个文件中使用的常用函数和模块
|
|
65
65
|
* ```js
|
|
66
|
-
* //
|
|
66
|
+
* // 外部包参数
|
|
67
|
+
* class EventEmitter{}; // Node.js内置模块,提供事件驱动编程的功能,允许对象之间进行事件通信
|
|
67
68
|
* exec(); // 子进程执行命令的函数,提供回调和Promise两种接口
|
|
68
69
|
* execSync; // 子进程执行命令的同步函数,返回命令输出结果
|
|
69
70
|
* fork(); // 创建一个新的Node.js子进程来运行指定的模块,提供与父进程的通信通道
|
|
71
|
+
* fs; // Node.js内置模块,提供文件系统操作功能
|
|
72
|
+
* path; // Node.js内置模块,提供文件路径处理功能
|
|
70
73
|
* promisify(); // 将Node.js回调风格的函数转换为返回Promise的函数
|
|
71
|
-
*
|
|
72
|
-
* path, fs; // Node.js内置模块,提供文件路径处理、文件系统操作等功能
|
|
73
|
-
* class EventEmitter{}; // Node.js内置模块,提供事件驱动编程的功能,允许对象之间进行事件通信
|
|
74
|
-
* // 自定义函数:
|
|
74
|
+
* // 自定义变量:
|
|
75
75
|
* execPromise(); // 基于exec函数的Promise版本,用于执行命令并以Promise方式获取结果
|
|
76
|
-
*
|
|
76
|
+
* // 自定义函数:
|
|
77
77
|
* getDirname(); // 获取当前模块目录路径的函数,用于在ES模块环境中替代__dirname变量的功能
|
|
78
|
+
* isPermissionError(); // 检查错误对象是否表示权限错误的函数,用于判断操作失败是否由于权限不足引起
|
|
78
79
|
* ```
|
|
79
|
-
* >查看定义:@see {@link exec}、{@link execSync}、{@link fork}、{@link
|
|
80
|
-
* {@link
|
|
81
|
-
* - 自定义函数:{@link execPromise}、{@link isPermissionError}、{@link getDirname}
|
|
80
|
+
* >查看定义:@see {@link EventEmitter}、{@link exec}、{@link execSync}、{@link fork}、{@link fs}、{@link path}、
|
|
81
|
+
* {@link promisify}、{@link execPromise}、{@link getDirname}、{@link isPermissionError}
|
|
82
82
|
*/
|
|
83
83
|
declare module './lib/shared.js' {
|
|
84
84
|
export * from './lib/shared.js';
|
|
@@ -88,10 +88,10 @@ declare module './lib/shared.js' {
|
|
|
88
88
|
/**
|
|
89
89
|
* ```js
|
|
90
90
|
* // 文件导出内容
|
|
91
|
-
* generateXml(); // 生成 winsw 配置文件的 XML;
|
|
92
91
|
* createExe(); // 创建 winsw 可执行文件,将 XML 配置文件和 Node.js 脚本打包成一个独立的 Windows 服务可执行文件;
|
|
92
|
+
* generateXml(); // 生成 winsw 配置文件的 XML;
|
|
93
93
|
* ```
|
|
94
|
-
* >查看定义:@see {@link
|
|
94
|
+
* >查看定义:@see {@link createExe}、{@link generateXml}
|
|
95
95
|
*/
|
|
96
96
|
declare module './lib/winsw.js' {
|
|
97
97
|
export * from './lib/winsw.js';
|
|
@@ -101,23 +101,23 @@ declare module './lib/winsw.js' {
|
|
|
101
101
|
/**
|
|
102
102
|
* Windows功能模块 主要功能:
|
|
103
103
|
* ```js
|
|
104
|
-
* Service{}; // 服务管理类
|
|
105
|
-
* EventLogger{}; // 事件日志记录器类
|
|
106
104
|
* elevate(); // 权限提升(机制:ShellExecute + "runas")
|
|
107
|
-
* sudo(); // 权限提升(机制:sudo.exe)
|
|
108
105
|
* isAdminUser(); // 检查当前用户是否拥有管理员权限
|
|
106
|
+
* sudo(); // 权限提升(机制:sudo.exe)
|
|
109
107
|
* kill(); // 结束指定PID进程
|
|
110
108
|
* list(); // 列出服务器上正在运行的进程
|
|
109
|
+
* Service{}; // 服务管理类
|
|
110
|
+
* EventLogger{}; // 事件日志记录器类
|
|
111
111
|
* ```
|
|
112
112
|
* ---
|
|
113
|
-
* >查看定义:@see {@link
|
|
114
|
-
* {@link
|
|
113
|
+
* >查看定义:@see {@link elevate}、{@link isAdminUser}、{@link sudo}、{@link kill}、{@link list}、
|
|
114
|
+
* {@link Service}、{@link EventLogger}
|
|
115
115
|
* @example
|
|
116
116
|
* // 基础示例
|
|
117
117
|
* import { Service } from '@flun/windows';
|
|
118
|
-
* import
|
|
118
|
+
* import winServiceConfig from './win-service.config.js';
|
|
119
119
|
*
|
|
120
|
-
* const svc = new Service(
|
|
120
|
+
* const svc = new Service(winServiceConfig);
|
|
121
121
|
*
|
|
122
122
|
* // 安装并自动启动服务(默认)
|
|
123
123
|
* svc.install();
|
|
@@ -127,7 +127,7 @@ declare module './lib/winsw.js' {
|
|
|
127
127
|
*
|
|
128
128
|
*/
|
|
129
129
|
declare module './index.js' {
|
|
130
|
-
export { elevate,
|
|
130
|
+
export { elevate, isAdminUser, sudo } from './lib/binaries.js';
|
|
131
131
|
export { kill, list } from './lib/cmd.js';
|
|
132
132
|
export { Service } from './lib/daemon.js';
|
|
133
133
|
export { EventLogger } from './lib/eventlog.js';
|
package/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { platform } from './lib/binaries.js';
|
|
|
3
3
|
// 平台检查
|
|
4
4
|
if (!platform().startsWith('win')) throw new Error('@flun/windows 仅支持在Windows系统上运行');
|
|
5
5
|
|
|
6
|
-
export { elevate,
|
|
6
|
+
export { elevate, isAdminUser, sudo } from './lib/binaries.js';
|
|
7
7
|
export { kill, list } from './lib/cmd.js';
|
|
8
8
|
export { Service } from './lib/daemon.js';
|
|
9
9
|
export { EventLogger } from './lib/eventlog.js';
|
package/lib/binaries.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { path, fs, exec, getDirname } from './shared.js';
|
|
2
1
|
/**
|
|
3
2
|
* 从 Node.js `os` 模块导入的 `platform` 函数,用于获取操作系统平台字符串;
|
|
4
3
|
* >查看定义:@see {@link platform}
|
|
5
4
|
* @type {() => string}
|
|
6
5
|
*/
|
|
7
6
|
import { platform, tmpdir } from 'os';
|
|
7
|
+
import { exec, fs, path, getDirname } from './shared.js';
|
|
8
8
|
|
|
9
9
|
const __dirname = getDirname(import.meta.url), vbsPath = path.resolve(__dirname, '../bin/elevate.vbs'),
|
|
10
10
|
/** 参数处理函数,用于标准化 options 和 callback 参数 */
|
|
@@ -80,6 +80,25 @@ const elevate = (cmd, options, callback) => {
|
|
|
80
80
|
});
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
+
/**
|
|
84
|
+
* 检查当前用户是否拥有管理员权限
|
|
85
|
+
* >查看定义:@see {@link isAdminUser}
|
|
86
|
+
* @param {(isAdmin: boolean) => void} callback - 回调函数,接收布尔值表示是否为管理员
|
|
87
|
+
* @returns {void}
|
|
88
|
+
* @example
|
|
89
|
+
* import { isAdminUser } from '@flun/windows';
|
|
90
|
+
* isAdminUser(isAdmin => {
|
|
91
|
+
* if (isAdmin) console.log('当前用户是管理员');
|
|
92
|
+
* else console.log('当前用户不是管理员');
|
|
93
|
+
* });
|
|
94
|
+
*/
|
|
95
|
+
const isAdminUser = callback => {
|
|
96
|
+
exec('NET SESSION', (err, so, se) => {
|
|
97
|
+
if (se.length !== 0) elevate('NET SESSION', (_err, _so, _se) => callback(_se.length === 0));
|
|
98
|
+
else callback(true);
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
|
|
83
102
|
/**
|
|
84
103
|
* 使用 sudo 方式提升权限(与 elevate 相似但体验更好)
|
|
85
104
|
* >查看定义:@see {@link sudo}
|
|
@@ -112,23 +131,4 @@ const sudo = (cmd, options, callback) => {
|
|
|
112
131
|
exec(`sudo ${cmd}`, p.options, p.callback);
|
|
113
132
|
};
|
|
114
133
|
|
|
115
|
-
|
|
116
|
-
* 检查当前用户是否拥有管理员权限
|
|
117
|
-
* >查看定义:@see {@link isAdminUser}
|
|
118
|
-
* @param {(isAdmin: boolean) => void} callback - 回调函数,接收布尔值表示是否为管理员
|
|
119
|
-
* @returns {void}
|
|
120
|
-
* @example
|
|
121
|
-
* import { isAdminUser } from '@flun/windows';
|
|
122
|
-
* isAdminUser(isAdmin => {
|
|
123
|
-
* if (isAdmin) console.log('当前用户是管理员');
|
|
124
|
-
* else console.log('当前用户不是管理员');
|
|
125
|
-
* });
|
|
126
|
-
*/
|
|
127
|
-
const isAdminUser = callback => {
|
|
128
|
-
exec('NET SESSION', (err, so, se) => {
|
|
129
|
-
if (se.length !== 0) elevate('NET SESSION', (_err, _so, _se) => callback(_se.length === 0));
|
|
130
|
-
else callback(true);
|
|
131
|
-
});
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
export { elevate, sudo, isAdminUser, platform };
|
|
134
|
+
export { platform, elevate, isAdminUser, sudo };
|
package/lib/daemon.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { execSync, execPromise, promisify, path, fs, EventEmitter, isPermissionError, getDirname } from './shared.js';
|
|
2
1
|
import { elevate, sudo } from './binaries.js';
|
|
3
|
-
import { generateXml, createExe } from './winsw.js';
|
|
4
2
|
import { EventLogger } from './eventlog.js';
|
|
3
|
+
import { EventEmitter, execSync, fs, path, promisify, execPromise, getDirname, isPermissionError } from './shared.js';
|
|
4
|
+
import { createExe, generateXml } from './winsw.js';
|
|
5
5
|
|
|
6
6
|
const __dirname = getDirname(import.meta.url), writeFileAsync = promisify(fs.writeFile), mkdirAsync = promisify(fs.mkdir),
|
|
7
7
|
daemonDir = 'daemon', wrapper = path.resolve(path.join(__dirname, './wrapper.js')), nameRegex = /[<>:"\\/|?*]/g;
|
|
@@ -13,9 +13,9 @@ const __dirname = getDirname(import.meta.url), writeFileAsync = promisify(fs.wri
|
|
|
13
13
|
* {@link restart}、{@link exists}
|
|
14
14
|
* @example
|
|
15
15
|
* import { Service } from '@flun/windows';
|
|
16
|
-
* import
|
|
16
|
+
* import winServiceConfig from './win-service.config.js';
|
|
17
17
|
*
|
|
18
|
-
* const svc = new Service(
|
|
18
|
+
* const svc = new Service(winServiceConfig);
|
|
19
19
|
* // 安装并自动启动服务(默认)
|
|
20
20
|
* svc.install();
|
|
21
21
|
*
|
|
@@ -248,9 +248,9 @@ class Service extends EventEmitter {
|
|
|
248
248
|
* @event error - 在错误发生时触发
|
|
249
249
|
* @example
|
|
250
250
|
* import { Service } from '@flun/windows';
|
|
251
|
-
* import
|
|
251
|
+
* import winServiceConfig from './win-service.config.js';
|
|
252
252
|
*
|
|
253
|
-
* const svc = new Service(
|
|
253
|
+
* const svc = new Service(winServiceConfig);
|
|
254
254
|
*
|
|
255
255
|
* // 安装并在完成后自动启动(默认)
|
|
256
256
|
* svc.install();
|
|
@@ -290,9 +290,9 @@ class Service extends EventEmitter {
|
|
|
290
290
|
* @event uninstall - 当卸载过程完成时触发
|
|
291
291
|
* @example
|
|
292
292
|
* import { Service } from '@flun/windows';
|
|
293
|
-
* import
|
|
293
|
+
* import winServiceConfig from './win-service.config.js';
|
|
294
294
|
*
|
|
295
|
-
* const svc = new Service(
|
|
295
|
+
* const svc = new Service(winServiceConfig);
|
|
296
296
|
*
|
|
297
297
|
* svc.on('uninstall', ()=>{
|
|
298
298
|
* console.log('卸载完成');
|
|
@@ -326,9 +326,9 @@ class Service extends EventEmitter {
|
|
|
326
326
|
* @event start - 当服务启动时触发
|
|
327
327
|
* @example
|
|
328
328
|
* import { Service } from '@flun/windows';
|
|
329
|
-
* import
|
|
329
|
+
* import winServiceConfig from './win-service.config.js';
|
|
330
330
|
*
|
|
331
|
-
* const svc = new Service(
|
|
331
|
+
* const svc = new Service(winServiceConfig);
|
|
332
332
|
*
|
|
333
333
|
* svc.on('start', ()=>{
|
|
334
334
|
* console.log('服务已启动');
|
|
@@ -357,9 +357,9 @@ class Service extends EventEmitter {
|
|
|
357
357
|
* @event alreadystopped - 当服务已经停止时触发
|
|
358
358
|
* @example
|
|
359
359
|
* import { Service } from '@flun/windows';
|
|
360
|
-
* import
|
|
360
|
+
* import winServiceConfig from './win-service.config.js';
|
|
361
361
|
*
|
|
362
|
-
* const svc = new Service(
|
|
362
|
+
* const svc = new Service(winServiceConfig);
|
|
363
363
|
* svc.on('stop', ()=>{
|
|
364
364
|
* console.log('服务已停止');
|
|
365
365
|
* });
|
|
@@ -381,9 +381,9 @@ class Service extends EventEmitter {
|
|
|
381
381
|
* @returns {Promise<void>}
|
|
382
382
|
* @example
|
|
383
383
|
* import { Service } from '@flun/windows';
|
|
384
|
-
* import
|
|
384
|
+
* import winServiceConfig from './win-service.config.js';
|
|
385
385
|
*
|
|
386
|
-
* const svc = new Service(
|
|
386
|
+
* const svc = new Service(winServiceConfig);
|
|
387
387
|
*
|
|
388
388
|
* svc.restart();
|
|
389
389
|
*/
|
package/lib/eventlog.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { execPromise, execSync, isPermissionError } from './shared.js';
|
|
2
1
|
import { elevate } from './binaries.js';
|
|
2
|
+
import { execSync, execPromise, isPermissionError } from './shared.js';
|
|
3
3
|
|
|
4
4
|
const eventLogs = ['APPLICATION', 'SYSTEM', 'SECURITY'],
|
|
5
5
|
validTypes = ['ERROR', 'WARNING', 'INFORMATION', 'SUCCESSAUDIT', 'FAILUREAUDIT'];
|
package/lib/shared.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 共享模块,导出在多个文件中使用的常用函数和模块
|
|
3
|
-
* >查看定义:@see {@link exec}、{@link execSync}、{@link fork}、{@link
|
|
4
|
-
* {@link
|
|
3
|
+
* >查看定义:@see {@link exec}、{@link execSync}、{@link fork}、{@link EventEmitter}、{@link fs}、{@link path}、
|
|
4
|
+
* {@link promisify}}
|
|
5
5
|
*/
|
|
6
6
|
import { exec, execSync, fork } from 'child_process';
|
|
7
|
-
import { promisify } from 'util';
|
|
8
|
-
import path from 'path';
|
|
9
|
-
import fs from 'fs';
|
|
10
7
|
import { EventEmitter } from 'events';
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
11
10
|
import { fileURLToPath } from 'url';
|
|
11
|
+
import { promisify } from 'util';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* 将 child_process.exec 包装成 Promise
|
|
@@ -17,6 +17,14 @@ import { fileURLToPath } from 'url';
|
|
|
17
17
|
*/
|
|
18
18
|
const execPromise = promisify(exec);
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* 获取当前模块所在目录的路径(类似 CommonJS 的 __dirname)
|
|
22
|
+
* >查看定义:@see {@link getDirname}
|
|
23
|
+
* @param {string} metaUrl - 传入 `import.meta.url`
|
|
24
|
+
* @returns {string} 当前模块的目录路径
|
|
25
|
+
*/
|
|
26
|
+
const getDirname = metaUrl => path.dirname(fileURLToPath(metaUrl));
|
|
27
|
+
|
|
20
28
|
/**
|
|
21
29
|
* 检查错误是否为权限不足的错误
|
|
22
30
|
* >查看定义:@see {@link isPermissionError}
|
|
@@ -32,12 +40,4 @@ const isPermissionError = error => {
|
|
|
32
40
|
return permissionErrors.some(keyword => lowerMessage.includes(keyword.toLowerCase()));
|
|
33
41
|
}
|
|
34
42
|
|
|
35
|
-
|
|
36
|
-
* 获取当前模块所在目录的路径(类似 CommonJS 的 __dirname)
|
|
37
|
-
* >查看定义:@see {@link getDirname}
|
|
38
|
-
* @param {string} metaUrl - 传入 `import.meta.url`
|
|
39
|
-
* @returns {string} 当前模块的目录路径
|
|
40
|
-
*/
|
|
41
|
-
const getDirname = metaUrl => path.dirname(fileURLToPath(metaUrl));
|
|
42
|
-
|
|
43
|
-
export { exec, execSync, fork, execPromise, promisify, path, fs, EventEmitter, isPermissionError, getDirname };
|
|
43
|
+
export { EventEmitter, exec, execSync, fork, fs, path, promisify, execPromise, getDirname, isPermissionError };
|
package/lib/winsw.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { fs, path, getDirname } from './shared.js';
|
|
2
1
|
import xmlBuilder from 'xml';
|
|
2
|
+
import { fs, path, getDirname } from './shared.js';
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
const __dirname = getDirname(import.meta.url);
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* 生成 winsw 配置文件的 XML
|
|
8
8
|
* >查看定义:@see {@link generateXml}
|
|
9
9
|
* @param {Object} config - 配置对象,必须包含以下必需属性:
|
|
10
10
|
* - *id* 服务的标识符,只能包含字母和数字,不能有空格
|
|
@@ -87,13 +87,13 @@ const generateXml = config => {
|
|
|
87
87
|
};
|
|
88
88
|
|
|
89
89
|
/**
|
|
90
|
-
*
|
|
91
|
-
|
|
90
|
+
* 创建 winsw 可执行文件及其配置文件
|
|
91
|
+
* >查看定义:@see {@link createExe}
|
|
92
92
|
* @param {string} name - 可执行文件名称(不含扩展名);
|
|
93
93
|
* @param {string} dir - 输出目录(默认:当前工作目录)
|
|
94
94
|
* @param {() => void} [callback] - 完成后的回调函数
|
|
95
|
-
* @
|
|
96
|
-
*
|
|
95
|
+
* @returns {void} 无返回值
|
|
96
|
+
* @description 将 winsw.exe 的安装版本复制为根据服务id重命名的特定版本,并复制 .exe.config 文件以支持 .NET 4+ 运行时环境;
|
|
97
97
|
*/
|
|
98
98
|
const createExe = (name, dir, callback) => {
|
|
99
99
|
if (!name || !dir) throw "createExe 方法需要 name 和 dir 两个参数!";
|
|
@@ -110,4 +110,4 @@ const createExe = (name, dir, callback) => {
|
|
|
110
110
|
callback?.();
|
|
111
111
|
};
|
|
112
112
|
|
|
113
|
-
export {
|
|
113
|
+
export { createExe, generateXml };
|
package/lib/wrapper.js
CHANGED
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
* -s, --stopparentfirst: 是否允许优雅退出
|
|
22
22
|
* --scriptoptions: 传递给脚本的选项
|
|
23
23
|
*/
|
|
24
|
-
import { path, fs, fork } from './shared.js';
|
|
25
24
|
import { createServer } from 'net';
|
|
26
|
-
import yargs from 'yargs/yargs';
|
|
27
25
|
import { hideBin } from 'yargs/helpers';
|
|
26
|
+
import yargs from 'yargs/yargs';
|
|
28
27
|
import { EventLogger } from './eventlog.js';
|
|
28
|
+
import { fork, fs, path } from './shared.js';
|
|
29
29
|
|
|
30
30
|
// 时间窗口(秒),默认时间窗口内最大重启次数,默认重启等待时间(秒),默认等待时间增长系数
|
|
31
31
|
const timeWindow = 60, defaultMaxRestarts = 3, defaultWaitTime = 1, defaultGrowth = 0.25,
|
package/package.json
CHANGED
|
@@ -1,62 +1,66 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@flun/windows",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "支持 Windows 服务、事件日志、UAC 以及多种与操作系统交互的辅助方法",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"windows",
|
|
7
|
-
"service",
|
|
8
|
-
"daemon",
|
|
9
|
-
"logging",
|
|
10
|
-
"event",
|
|
11
|
-
"event logging",
|
|
12
|
-
"elevate",
|
|
13
|
-
"sudo",
|
|
14
|
-
"task"
|
|
15
|
-
],
|
|
16
|
-
"author": "flun <open@flun.top>",
|
|
17
|
-
"publishConfig": {
|
|
18
|
-
"access": "public"
|
|
19
|
-
},
|
|
20
|
-
"type": "module",
|
|
21
|
-
"types": "index.d.ts",
|
|
22
|
-
"exports": {
|
|
23
|
-
".": "./index.js"
|
|
24
|
-
},
|
|
25
|
-
"main": "index.js",
|
|
26
|
-
"bin": {
|
|
27
|
-
"windows": "bin/cli.js"
|
|
28
|
-
},
|
|
29
|
-
"files": [
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"LICENSE"
|
|
39
|
-
],
|
|
40
|
-
"preferGlobal": true,
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"chalk": "^6.0.1",
|
|
43
|
-
"xml": "1.0.1",
|
|
44
|
-
"yargs": "^18.2.0"
|
|
45
|
-
},
|
|
46
|
-
"engines": {
|
|
47
|
-
"node": ">=22.12.0",
|
|
48
|
-
"npm": ">=10.0.0"
|
|
49
|
-
},
|
|
50
|
-
"repository": {
|
|
51
|
-
"type": "git",
|
|
52
|
-
"url": "git+https://github.com/OpenFlun/windows.git"
|
|
53
|
-
},
|
|
54
|
-
"
|
|
55
|
-
|
|
56
|
-
"url": "https://
|
|
57
|
-
},
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@flun/windows",
|
|
3
|
+
"version": "5.0.0",
|
|
4
|
+
"description": "支持 Windows 服务、事件日志、UAC 以及多种与操作系统交互的辅助方法",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"windows",
|
|
7
|
+
"service",
|
|
8
|
+
"daemon",
|
|
9
|
+
"logging",
|
|
10
|
+
"event",
|
|
11
|
+
"event logging",
|
|
12
|
+
"elevate",
|
|
13
|
+
"sudo",
|
|
14
|
+
"task"
|
|
15
|
+
],
|
|
16
|
+
"author": "flun <open@flun.top>",
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"type": "module",
|
|
21
|
+
"types": "index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": "./index.js"
|
|
24
|
+
},
|
|
25
|
+
"main": "index.js",
|
|
26
|
+
"bin": {
|
|
27
|
+
"windows": "bin/cli.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"bin",
|
|
31
|
+
"lib",
|
|
32
|
+
"CHANGELOG.md",
|
|
33
|
+
"README.md",
|
|
34
|
+
"copy-files.js",
|
|
35
|
+
"index.d.ts",
|
|
36
|
+
"index.js",
|
|
37
|
+
"win-service.config.js",
|
|
38
|
+
"LICENSE"
|
|
39
|
+
],
|
|
40
|
+
"preferGlobal": true,
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"chalk": "^6.0.1",
|
|
43
|
+
"xml": "1.0.1",
|
|
44
|
+
"yargs": "^18.2.0"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=22.12.0",
|
|
48
|
+
"npm": ">=10.0.0"
|
|
49
|
+
},
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "git+https://github.com/OpenFlun/windows.git"
|
|
53
|
+
},
|
|
54
|
+
"gitee": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "git+https://gitee.com/openflun/windows.git"
|
|
57
|
+
},
|
|
58
|
+
"homepage": "https://github.com/OpenFlun/windows#readme",
|
|
59
|
+
"bugs": {
|
|
60
|
+
"url": "https://github.com/OpenFlun/windows/issues"
|
|
61
|
+
},
|
|
62
|
+
"license": "ISC",
|
|
63
|
+
"scripts": {
|
|
64
|
+
"postinstall": "node copy-files.js 2>&1"
|
|
65
|
+
}
|
|
62
66
|
}
|
package/win-service.config.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Windows 服务配置模板
|
|
3
3
|
* 带 * 的为必填项,其余可删除或按需保留;
|
|
4
|
-
* 本配置既支持命令行方式(如 windows install),
|
|
5
|
-
* 也支持在函数方式中导入:import
|
|
4
|
+
* 本配置既支持命令行方式(如 windows s install),
|
|
5
|
+
* 也支持在函数方式中导入:import winServiceConfig from './win-service.config.js';
|
|
6
6
|
* 具体用法见 README 的「命令行」与「函数方式」章节;
|
|
7
7
|
*
|
|
8
8
|
* 关于 quiet:默认 false,各方法执行后会在终端打印结果(如"服务安装完成;");
|
|
9
9
|
* 若本包嵌入到自己的生产项目,终端输出会混入宿主日志,此时设为 true,
|
|
10
10
|
* 库只发事件不打印,由宿主自行监听 install/start/stop/uninstall/error 等事件;
|
|
11
11
|
* 命令行方式恒为 quiet,不受此字段影响;
|
|
12
|
+
* >查看定义:@see {@link winServiceConfig}
|
|
12
13
|
*/
|
|
13
|
-
|
|
14
|
+
const winServiceConfig = {
|
|
14
15
|
// * 服务名称,用于服务管理与注册表标识;不能含 <>:"\/|?*
|
|
15
16
|
name: 'MyApp',
|
|
16
17
|
// * 启动服务的入口脚本绝对路径
|
|
@@ -65,4 +66,6 @@ export default {
|
|
|
65
66
|
|
|
66
67
|
// 为 true 时不打印执行结果,只发事件;嵌入生产项目时建议开启
|
|
67
68
|
quiet: false,
|
|
68
|
-
};
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export { winServiceConfig, winServiceConfig as default };
|