node-automator 1.0.4 → 1.1.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/README.md +2 -2
- package/commands/mgr.js +2 -0
- package/commands/register_search_install_location.js +12 -0
- package/commands/which.js +8 -49
- package/package.json +1 -1
- package/utils/log_tool.js +1 -1
- package/utils/reg_tool.js +66 -0
- package/utils/request_tool.js +10 -21
- package/utils/shell_tool.js +2 -1
- package/utils/which_tool.js +54 -0
package/README.md
CHANGED
package/commands/mgr.js
CHANGED
|
@@ -113,6 +113,7 @@ const { AssertCommand } = require('./assert');
|
|
|
113
113
|
const { SvnAddCommand } = require('./svn_add');
|
|
114
114
|
const { ImageCropCommand } = require('./image_crop');
|
|
115
115
|
const { CursorUpCommand } = require('./cursor_up');
|
|
116
|
+
const { RegisterSearchInstallLocationCommand } = require('./register_search_install_location');
|
|
116
117
|
|
|
117
118
|
const globalData = {
|
|
118
119
|
"executed_cfg": [], // 执行过的配置文件
|
|
@@ -467,6 +468,7 @@ function init() {
|
|
|
467
468
|
register("svn_add", SvnAddCommand, false);
|
|
468
469
|
register("image_crop", ImageCropCommand, false);
|
|
469
470
|
register("cursor_up", CursorUpCommand, false);
|
|
471
|
+
register("register_search_install_location", RegisterSearchInstallLocationCommand, false);
|
|
470
472
|
}
|
|
471
473
|
|
|
472
474
|
module.exports = {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const { registerSearchInstallLocation } = require('../utils/reg_tool');
|
|
2
|
+
const { BaseCommand } = require("./base");
|
|
3
|
+
|
|
4
|
+
class RegisterSearchInstallLocationCommand extends BaseCommand {
|
|
5
|
+
async execute() {
|
|
6
|
+
return registerSearchInstallLocation(this.selfData.target);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
RegisterSearchInstallLocationCommand,
|
|
12
|
+
};
|
package/commands/which.js
CHANGED
|
@@ -1,57 +1,16 @@
|
|
|
1
|
+
const { warn } = require('../utils/log_tool');
|
|
2
|
+
const { registerSearchInstallLocation } = require('../utils/reg_tool');
|
|
3
|
+
const { which } = require('../utils/which_tool');
|
|
1
4
|
const { BaseCommand } = require("./base");
|
|
2
|
-
|
|
3
|
-
const { get_fst_file } = require("../utils/file_tool");
|
|
4
|
-
const path = require("path");
|
|
5
|
-
const fs = require("fs");
|
|
6
|
-
const { warn } = require("../utils/log_tool");
|
|
5
|
+
|
|
7
6
|
|
|
8
7
|
class WhichCommand extends BaseCommand {
|
|
9
8
|
async execute() {
|
|
10
|
-
let
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
cmd = "where";
|
|
14
|
-
break;
|
|
15
|
-
}
|
|
16
|
-
default: {
|
|
17
|
-
cmd = "which";
|
|
18
|
-
break;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
let file;
|
|
23
|
-
let stdout = await exec_shell({
|
|
24
|
-
cmd: `${cmd} ${this.selfData.target}`,
|
|
25
|
-
capture_stdout: true,
|
|
26
|
-
ignore_code: true,
|
|
27
|
-
});
|
|
28
|
-
if (stdout) {
|
|
29
|
-
/** @type {string[]} */
|
|
30
|
-
let files = stdout.split(/[\r\n]{1,2}/);
|
|
31
|
-
files = files.filter(v => v && v.trim());
|
|
32
|
-
// windows系统下,优先选择有 .cmd 或者 .exe
|
|
33
|
-
if (process.platform === "win32") {
|
|
34
|
-
let preferExts = ['.exe', '.cmd'];
|
|
35
|
-
files.sort((a, b) => {
|
|
36
|
-
let exta = path.extname(a);
|
|
37
|
-
let extb = path.extname(b);
|
|
38
|
-
if (preferExts.includes(exta)) {
|
|
39
|
-
return -1;
|
|
40
|
-
} else if (preferExts.includes(extb)) {
|
|
41
|
-
return 1;
|
|
42
|
-
}
|
|
43
|
-
return 0;
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
file = get_fst_file(files);
|
|
47
|
-
if (file) {
|
|
48
|
-
file = fs.realpathSync(file);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
if (!file) {
|
|
52
|
-
warn(`未找到 ${this.selfData.target}`);
|
|
9
|
+
let result = await which(this.selfData.target);
|
|
10
|
+
if (!result) {
|
|
11
|
+
warn(`未找到 ${this.selfData.target}`);
|
|
53
12
|
}
|
|
54
|
-
return
|
|
13
|
+
return result;
|
|
55
14
|
}
|
|
56
15
|
}
|
|
57
16
|
|
package/package.json
CHANGED
package/utils/log_tool.js
CHANGED
|
@@ -41,7 +41,7 @@ function log(msg, end = "\n", level = -1, force = true, with_date = false) {
|
|
|
41
41
|
}
|
|
42
42
|
// clearLine();
|
|
43
43
|
let color = colors[level];
|
|
44
|
-
if (color) {
|
|
44
|
+
if (color && ""[color]) {
|
|
45
45
|
process.stdout.write(msg.toString()[color] + end);
|
|
46
46
|
} else {
|
|
47
47
|
process.stdout.write(msg.toString() + end);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const { exec_shell } = require("./shell_tool");
|
|
3
|
+
const { which } = require("./which_tool");
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 查找指定软件的安装目录
|
|
7
|
+
* @param {*} target
|
|
8
|
+
* @returns
|
|
9
|
+
*/
|
|
10
|
+
async function registerSearchInstallLocation(target) {
|
|
11
|
+
const key = target;
|
|
12
|
+
var Uninstalls = [
|
|
13
|
+
"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
|
|
14
|
+
"HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
|
|
15
|
+
];
|
|
16
|
+
var result = "";
|
|
17
|
+
for (var i = 0; i < Uninstalls.length; i++) {
|
|
18
|
+
const Uninstall = Uninstalls[i];
|
|
19
|
+
result = await registerQuery(`${Uninstall}\\${key}`);
|
|
20
|
+
if (result) break;
|
|
21
|
+
}
|
|
22
|
+
const InstallLocation = registerGetProp(result, "InstallLocation");
|
|
23
|
+
if (InstallLocation) return InstallLocation;
|
|
24
|
+
const UninstallString = registerGetProp(result, "UninstallString");
|
|
25
|
+
if (UninstallString) return path.dirname(UninstallString);
|
|
26
|
+
return "";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 查找指定注册项
|
|
31
|
+
* @param {*} key
|
|
32
|
+
* @returns
|
|
33
|
+
*/
|
|
34
|
+
async function registerQuery(key) {
|
|
35
|
+
const REG_EXE = await which("reg");
|
|
36
|
+
return exec_shell({
|
|
37
|
+
cmd: [REG_EXE, "QUERY", key],
|
|
38
|
+
capture_stdout: true,
|
|
39
|
+
ignore_code: true,
|
|
40
|
+
quiet: true,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 获取注册项的属性
|
|
46
|
+
* @param {*} queryResult
|
|
47
|
+
* @param {*} key
|
|
48
|
+
* @returns
|
|
49
|
+
*/
|
|
50
|
+
function registerGetProp(queryResult, key) {
|
|
51
|
+
var matches = queryResult.match(new RegExp(key + "\\s+REG_SZ\\s+(.*)"));
|
|
52
|
+
if (matches && matches.length > 1) {
|
|
53
|
+
var value = matches[1];
|
|
54
|
+
if (value.startsWith('"') && value.endsWith('"')) {
|
|
55
|
+
return value.substring(1, value.length - 1);
|
|
56
|
+
}
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
return "";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
module.exports = {
|
|
63
|
+
registerSearchInstallLocation,
|
|
64
|
+
registerGetProp,
|
|
65
|
+
registerQuery,
|
|
66
|
+
};
|
package/utils/request_tool.js
CHANGED
|
@@ -41,25 +41,17 @@ async function doRequest(data) {
|
|
|
41
41
|
let hasProgress = false;
|
|
42
42
|
if (useCache) {
|
|
43
43
|
result = http_cache;
|
|
44
|
-
if (data.dst) {
|
|
45
|
-
let file = fs.createWriteStream(get_full_path(data.dst, "FILE"));
|
|
46
|
-
file.write(result);
|
|
47
|
-
}
|
|
48
44
|
} else {
|
|
45
|
+
let chunks = [];
|
|
49
46
|
result = await new Promise(resolve => {
|
|
50
47
|
let sizeTotal = 0;
|
|
51
|
-
let fileDst = data.dst || shareData.AUTOMATOR_SCRATCH + "/request_tool/" + cache_name;
|
|
52
|
-
let file = fs.createWriteStream(get_full_path(fileDst, "FILE"));
|
|
48
|
+
let fileDst = get_full_path(data.dst || shareData.AUTOMATOR_SCRATCH + "/request_tool/" + cache_name, "FILE");
|
|
53
49
|
let cacheDir = path.dirname(cache_path);
|
|
54
50
|
if (!fs.existsSync(cacheDir)) {
|
|
55
51
|
fs.mkdirSync(cacheDir, {
|
|
56
52
|
recursive: true
|
|
57
53
|
});
|
|
58
54
|
}
|
|
59
|
-
let cachedFile;
|
|
60
|
-
if (enable_http_cache) {
|
|
61
|
-
cachedFile = fs.createWriteStream(cache_path);
|
|
62
|
-
}
|
|
63
55
|
function send_request() {
|
|
64
56
|
let req = request(url, options, (err, res, result) => {
|
|
65
57
|
if (err) {
|
|
@@ -74,17 +66,15 @@ async function doRequest(data) {
|
|
|
74
66
|
resolve();
|
|
75
67
|
return;
|
|
76
68
|
}
|
|
69
|
+
const buffer = Buffer.concat(chunks);
|
|
77
70
|
sizeTotal = res.client.bytesRead;
|
|
78
71
|
!quiet && progress(sizeTotal, sizeTotal, { desc: "完成", format_bytes: true, color: "green" });
|
|
79
72
|
// 仅在响应码合法时,写入缓存
|
|
80
|
-
if (
|
|
81
|
-
if (
|
|
82
|
-
|
|
83
|
-
} else {
|
|
84
|
-
if (fs.existsSync(cache_path)) {
|
|
85
|
-
fs.unlinkSync(cache_path);
|
|
86
|
-
}
|
|
73
|
+
if (res.statusCode > 0 && res.statusCode < 400) {
|
|
74
|
+
if (enable_http_cache) {
|
|
75
|
+
fs.writeFileSync(cache_path, buffer);
|
|
87
76
|
}
|
|
77
|
+
fs.writeFileSync(fileDst, buffer);
|
|
88
78
|
}
|
|
89
79
|
if (!data.ignore_status_code) {
|
|
90
80
|
if (res.statusCode >= 400) {
|
|
@@ -125,10 +115,9 @@ async function doRequest(data) {
|
|
|
125
115
|
}
|
|
126
116
|
}
|
|
127
117
|
});
|
|
128
|
-
req.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
118
|
+
req.on("data", (chunk) => {
|
|
119
|
+
chunks.push(chunk);
|
|
120
|
+
});
|
|
132
121
|
request_progress(
|
|
133
122
|
req.on('progress', function (state) {
|
|
134
123
|
sizeTotal = state.size.total;
|
package/utils/shell_tool.js
CHANGED
|
@@ -31,6 +31,7 @@ async function exec_shell(data) {
|
|
|
31
31
|
let instant_stdout = data.instant_stdout;
|
|
32
32
|
let capture_stdout = isStdOut() || data.capture_stdout;
|
|
33
33
|
let acceptableErrors = data.acceptableErrors || [];
|
|
34
|
+
let quiet = data.quiet;;
|
|
34
35
|
const result = await new Promise((resolve, reject) => {
|
|
35
36
|
/** @type {string[]} */
|
|
36
37
|
let cmd = data.cmd;
|
|
@@ -63,7 +64,7 @@ async function exec_shell(data) {
|
|
|
63
64
|
let results = [];
|
|
64
65
|
let errors = [];
|
|
65
66
|
let encoding = data.encoding || "cp936";
|
|
66
|
-
whisper(`cmd:[${cmd}] cwd:${data.cwd} inputs:${data.inputs}`);
|
|
67
|
+
!quiet && whisper(`cmd:[${cmd}] cwd:${data.cwd} inputs:${data.inputs}`);
|
|
67
68
|
options.stdio = ["pipe", capture_stdout ? "pipe" : process.stdout, "pipe"];
|
|
68
69
|
const child = child_process.spawn(cmd[0], cmd.slice(1), options);
|
|
69
70
|
if (child.stdout) {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const { exec_shell } = require('./shell_tool');
|
|
4
|
+
const { get_fst_file } = require("./file_tool");
|
|
5
|
+
const { warn } = require("./log_tool");
|
|
6
|
+
async function which(target) {
|
|
7
|
+
let cmd;
|
|
8
|
+
switch (process.platform) {
|
|
9
|
+
case "win32": {
|
|
10
|
+
cmd = "where";
|
|
11
|
+
break;
|
|
12
|
+
}
|
|
13
|
+
default: {
|
|
14
|
+
cmd = "which";
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let file;
|
|
20
|
+
let stdout = await exec_shell({
|
|
21
|
+
cmd: `${cmd} ${target}`,
|
|
22
|
+
capture_stdout: true,
|
|
23
|
+
ignore_code: true,
|
|
24
|
+
quiet: true,
|
|
25
|
+
});
|
|
26
|
+
if (stdout) {
|
|
27
|
+
/** @type {string[]} */
|
|
28
|
+
let files = stdout.split(/[\r\n]{1,2}/);
|
|
29
|
+
files = files.filter((v) => v && v.trim());
|
|
30
|
+
// windows系统下,优先选择有 .cmd 或者 .exe
|
|
31
|
+
if (process.platform === "win32") {
|
|
32
|
+
let preferExts = [".exe", ".cmd"];
|
|
33
|
+
files.sort((a, b) => {
|
|
34
|
+
let exta = path.extname(a);
|
|
35
|
+
let extb = path.extname(b);
|
|
36
|
+
if (preferExts.includes(exta)) {
|
|
37
|
+
return -1;
|
|
38
|
+
} else if (preferExts.includes(extb)) {
|
|
39
|
+
return 1;
|
|
40
|
+
}
|
|
41
|
+
return 0;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
file = get_fst_file(files);
|
|
45
|
+
if (file) {
|
|
46
|
+
file = fs.realpathSync(file);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return file;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = {
|
|
53
|
+
which,
|
|
54
|
+
};
|