zusbdll 0.0.1

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/index.js ADDED
@@ -0,0 +1,438 @@
1
+ const { spawn } = require("child_process");
2
+ const fs = require("fs");
3
+ const fsp = require("fs/promises");
4
+ const os = require("os");
5
+ const path = require("path");
6
+ const crypto = require('crypto');
7
+
8
+ const EXECUTABLE_NAME = "zdll.exe";
9
+ const EXECUTABLE_DIR = path.join(__dirname, "lib");
10
+ const EXECUTABLE_PATH = path.join(EXECUTABLE_DIR, EXECUTABLE_NAME);
11
+ const DEFAULT_SCENARIO_PATH = path.join(EXECUTABLE_DIR, "scenario.json");
12
+ const DEFAULT_ALIAS = "lib";
13
+ const DEFAULT_DLL_RELATIVE = "./SG.dll";
14
+ const DEFAULT_SEARCH_PATHS = ["."];
15
+
16
+ // 计算文件的MD5值
17
+ function calculateMD5(filePath) {
18
+ return new Promise((resolve, reject) => {
19
+ const hash = crypto.createHash('md5');
20
+ const stream = fs.createReadStream(filePath);
21
+
22
+ stream.on('data', (data) => {
23
+ hash.update(data);
24
+ });
25
+
26
+ stream.on('end', () => {
27
+ const md5sum = hash.digest('hex');
28
+ resolve(md5sum);
29
+ });
30
+
31
+ stream.on('error', (err) => {
32
+ reject(err);
33
+ });
34
+ });
35
+ }
36
+
37
+ function normaliseArgs(args) {
38
+ if (!Array.isArray(args)) {
39
+ return undefined;
40
+ }
41
+ return args.map((arg) => {
42
+ if (arg === null || arg === undefined) {
43
+ return "";
44
+ }
45
+ if (typeof arg === "string") {
46
+ return arg;
47
+ }
48
+ if (typeof arg === "object") {
49
+ if (Object.prototype.hasOwnProperty.call(arg, "raw")) {
50
+ return String(arg.raw);
51
+ }
52
+ const type = arg.type || arg.t;
53
+ const value = arg.value;
54
+ if (!type) {
55
+ throw new Error("Argument objects must include a type property.");
56
+ }
57
+ if (value === undefined || value === null) {
58
+ return `${type}=`;
59
+ }
60
+ return `${type}=${value}`;
61
+ }
62
+ return String(arg);
63
+ });
64
+ }
65
+
66
+ function normaliseDllPath(dll) {
67
+ if (!dll) {
68
+ return DEFAULT_DLL_RELATIVE;
69
+ }
70
+ if (path.isAbsolute(dll)) {
71
+ return dll;
72
+ }
73
+ if (/[\\/]/.test(dll)) {
74
+ return dll;
75
+ }
76
+ return `./${dll}`;
77
+ }
78
+
79
+ function normaliseScenario(scenario) {
80
+ if (!scenario || typeof scenario !== "object") {
81
+ throw new Error("Scenario definition must be an object.");
82
+ }
83
+ const searchPaths = Array.isArray(scenario.searchPaths) && scenario.searchPaths.length > 0
84
+ ? scenario.searchPaths
85
+ : DEFAULT_SEARCH_PATHS;
86
+ const commands = (scenario.commands || []).map((command) => {
87
+ if (!command || typeof command !== "object") {
88
+ throw new Error("Each scenario command must be an object.");
89
+ }
90
+ const copy = { ...command };
91
+ if (Array.isArray(copy.args)) {
92
+ copy.args = normaliseArgs(copy.args);
93
+ }
94
+ return copy;
95
+ });
96
+ if (commands.length === 0) {
97
+ throw new Error("Scenario requires at least one command.");
98
+ }
99
+ return { searchPaths, commands };
100
+ }
101
+
102
+ function buildScenarioFromControl(control) {
103
+ if (!control || typeof control !== "object") {
104
+ return null;
105
+ }
106
+
107
+ if (control.scenario && typeof control.scenario === "object") {
108
+ return normaliseScenario(control.scenario);
109
+ }
110
+
111
+ if (Array.isArray(control)) {
112
+ return normaliseScenario({ commands: control });
113
+ }
114
+
115
+ if (Array.isArray(control.commands)) {
116
+ return normaliseScenario({
117
+ searchPaths: control.searchPaths,
118
+ commands: control.commands
119
+ });
120
+ }
121
+
122
+ const relevantKeys = [
123
+ "function",
124
+ "calls",
125
+ "dll",
126
+ "dllPath",
127
+ "keepLoaded",
128
+ "openUsbkey",
129
+ "logout",
130
+ "alias",
131
+ "openArgs",
132
+ "logoutArgs"
133
+ ];
134
+ const shouldBuild = relevantKeys.some((key) => Object.prototype.hasOwnProperty.call(control, key));
135
+ if (!shouldBuild) {
136
+ return null;
137
+ }
138
+
139
+ const alias = control.alias || DEFAULT_ALIAS;
140
+ const dllPath = normaliseDllPath(control.dllPath || control.dll);
141
+ const searchPaths = Array.isArray(control.searchPaths) && control.searchPaths.length > 0
142
+ ? control.searchPaths
143
+ : DEFAULT_SEARCH_PATHS;
144
+ const commands = [];
145
+
146
+ commands.push({ type: "load", path: dllPath, alias });
147
+
148
+ const openUsbkey = control.openUsbkey !== false;
149
+ if (openUsbkey) {
150
+ const openFunction = control.openFunction || "OpenUsbkey";
151
+ commands.push({
152
+ type: "call",
153
+ alias,
154
+ function: openFunction,
155
+ args: normaliseArgs(control.openArgs)
156
+ });
157
+ }
158
+
159
+ const callList = Array.isArray(control.calls) ? control.calls.slice() : [];
160
+ if (control.function) {
161
+ callList.unshift({ function: control.function, args: control.args, alias: control.callAlias });
162
+ }
163
+
164
+ callList.forEach((call) => {
165
+ if (!call || typeof call !== "object") {
166
+ throw new Error("Each call entry must be an object.");
167
+ }
168
+ if (!call.function) {
169
+ throw new Error("Call entry missing function name.");
170
+ }
171
+ const callAlias = call.alias || alias;
172
+ commands.push({
173
+ type: "call",
174
+ alias: callAlias,
175
+ function: call.function,
176
+ args: normaliseArgs(call.args)
177
+ });
178
+ });
179
+
180
+ const logout = control.logout !== false;
181
+ if (logout) {
182
+ const logoutFunction = control.logoutFunction || "LgoutServer";
183
+ commands.push({
184
+ type: "call",
185
+ alias,
186
+ function: logoutFunction,
187
+ args: normaliseArgs(control.logoutArgs)
188
+ });
189
+ }
190
+
191
+ const keepLoaded = control.keepLoaded === true;
192
+ if (!keepLoaded) {
193
+ commands.push({ type: "unload", alias });
194
+ }
195
+
196
+ return normaliseScenario({ searchPaths, commands });
197
+ }
198
+
199
+ async function writeScenarioFile(scenario) {
200
+ const dir = await fsp.mkdtemp(path.join(os.tmpdir(), "zusbdll-"));
201
+ const scenarioPath = path.join(dir, "scenario.json");
202
+ await fsp.writeFile(scenarioPath, JSON.stringify(scenario, null, 2), "utf8");
203
+ const cleanup = async () => {
204
+ try {
205
+ if (fsp.rm) {
206
+ await fsp.rm(dir, { recursive: true, force: true });
207
+ } else {
208
+ await fsp.rmdir(dir, { recursive: true });
209
+ }
210
+ } catch (err) {
211
+ // ignore cleanup errors
212
+ }
213
+ };
214
+ return { path: scenarioPath, cleanup };
215
+ }
216
+
217
+ async function resolveScenarioPath(candidate) {
218
+ const scenarioPath = path.isAbsolute(candidate)
219
+ ? candidate
220
+ : path.join(EXECUTABLE_DIR, candidate);
221
+ await fsp.access(scenarioPath, fs.constants.F_OK);
222
+ return scenarioPath;
223
+ }
224
+
225
+ async function prepareScenario(control) {
226
+ if (control === null || control === undefined) {
227
+ return { path: DEFAULT_SCENARIO_PATH, cleanup: null };
228
+ }
229
+
230
+ if (typeof control === "string") {
231
+ const scenarioPath = await resolveScenarioPath(control);
232
+ return { path: scenarioPath, cleanup: null };
233
+ }
234
+
235
+ if (typeof control === "object") {
236
+ if (control.scenarioFile || control.file || control.path) {
237
+ const scenarioPath = await resolveScenarioPath(control.scenarioFile || control.file || control.path);
238
+ return { path: scenarioPath, cleanup: null };
239
+ }
240
+
241
+ const scenario = buildScenarioFromControl(control);
242
+ if (scenario) {
243
+ return writeScenarioFile(scenario);
244
+ }
245
+ }
246
+
247
+ return { path: DEFAULT_SCENARIO_PATH, cleanup: null };
248
+ }
249
+
250
+ function parseOutput(stdout) {
251
+ const trimmed = stdout ? stdout.trim() : "";
252
+ if (!trimmed) {
253
+ return { primary: null, json: [], text: "" };
254
+ }
255
+
256
+ const lines = trimmed.split(/\r?\n/);
257
+ const jsonEntries = [];
258
+ const textEntries = [];
259
+
260
+ lines.forEach((line) => {
261
+ const candidate = line.trim();
262
+ if (!candidate) {
263
+ return;
264
+ }
265
+ try {
266
+ jsonEntries.push(JSON.parse(candidate));
267
+ } catch (err) {
268
+ textEntries.push(line);
269
+ }
270
+ });
271
+
272
+ let primary = null;
273
+ if (jsonEntries.length === 1 && textEntries.length === 0) {
274
+ primary = jsonEntries[0];
275
+ } else if (jsonEntries.length > 0) {
276
+ primary = jsonEntries;
277
+ } else {
278
+ primary = textEntries.join(os.EOL);
279
+ }
280
+
281
+ return { primary, json: jsonEntries, text: textEntries.join(os.EOL) };
282
+ }
283
+
284
+ function runExecutable(args) {
285
+ return new Promise((resolve, reject) => {
286
+ console.log(`正在执行: ${EXECUTABLE_PATH} ${args.join(' ')}`);
287
+ const child = spawn(EXECUTABLE_PATH, args, {
288
+ cwd: EXECUTABLE_DIR,
289
+ windowsHide: true
290
+ });
291
+ let stdout = "";
292
+ let stderr = "";
293
+
294
+ child.stdout.on("data", (chunk) => {
295
+ stdout += chunk.toString();
296
+ });
297
+
298
+ child.stderr.on("data", (chunk) => {
299
+ stderr += chunk.toString();
300
+ });
301
+
302
+ child.on("error", (err) => {
303
+ reject(err);
304
+ });
305
+
306
+ child.on("close", (code) => {
307
+ resolve({ code, stdout, stderr });
308
+ });
309
+ });
310
+ }
311
+
312
+
313
+ async function executeZusbdll(control) {
314
+ if (process.platform !== "win32") {
315
+ throw new Error("zusbdll requires Windows to execute zdll.exe (win-x86 target).");
316
+ }
317
+
318
+ try {
319
+ await fsp.access(EXECUTABLE_PATH, fs.constants.F_OK);
320
+ } catch (accessErr) {
321
+ throw new Error(`zdll executable not found at ${EXECUTABLE_PATH}`);
322
+ }
323
+
324
+ let scenarioInfo;
325
+
326
+ try {
327
+ scenarioInfo = await prepareScenario(control);
328
+ } catch (scenarioErr) {
329
+ throw new Error(`Invalid scenario: ${scenarioErr.message}`);
330
+ }
331
+
332
+ let cleanup = null;
333
+ if (scenarioInfo.cleanup) {
334
+ cleanup = scenarioInfo.cleanup;
335
+ }
336
+
337
+ try {
338
+ const args = ["run", scenarioInfo.path];
339
+ // console.log(`准备运行 zdll.exe,参数: ${args.join(' ')}`);
340
+ // console.log(`工作目录: ${EXECUTABLE_DIR}`);
341
+ const result = await runExecutable(args);
342
+ // console.log(`zdll.exe 执行完成,退出代码: ${result.code}`);
343
+ // console.log(`stdout: ${result.stdout}`);
344
+ // console.log(`stderr: ${result.stderr}`);
345
+
346
+ const parsed = parseOutput(result.stdout);
347
+
348
+ const output = {
349
+ exitCode: result.code,
350
+ stdout: result.stdout,
351
+ stderr: result.stderr,
352
+ scenario: scenarioInfo.path,
353
+ parsed: parsed.json
354
+ };
355
+
356
+ if (parsed.primary !== null) {
357
+ output.payload = parsed.primary;
358
+ } else {
359
+ output.payload = result.stdout;
360
+ }
361
+
362
+ if (result.stderr) {
363
+ console.warn(result.stderr.trim());
364
+ }
365
+
366
+ if (result.code !== 0) {
367
+ throw new Error(`zdll.exe exited with code ${result.code}\nstdout: ${result.stdout}\nstderr: ${result.stderr}`);
368
+ }
369
+
370
+ return output;
371
+ } finally {
372
+ if (cleanup) {
373
+ try {
374
+ await cleanup();
375
+ } catch (cleanupErr) {
376
+ console.warn(`Failed to clean temporary scenario: ${cleanupErr.message}`);
377
+ }
378
+ }
379
+ }
380
+
381
+ }
382
+
383
+ async function autoRun() {
384
+ let res={
385
+ code:1,
386
+ data:null,
387
+ msg:'error'
388
+ }
389
+ try {
390
+ const scenarioPath = path.join(__dirname, "lib", "scenario.json");
391
+ const result = await executeZusbdll(scenarioPath);
392
+ // res.result=result;
393
+ // 解析返回的 JSON 数据
394
+ let parsedResults;
395
+ try {
396
+ parsedResults = JSON.parse(result.stdout);
397
+ res.code=0;
398
+ res.data=parsedResults;
399
+ res.msg='success'
400
+ } catch (parseErr) {
401
+ // console.log("解析结果失败:", parseErr.message);
402
+ res.data=parseErr;
403
+ res.msg=parseErr.message;
404
+ return res;
405
+ }
406
+ }
407
+ catch (err) {
408
+ // console.log("测试失败!", err.message);
409
+ // console.log("错误详情:", err);
410
+ res.data=err;
411
+ res.msg=err.message;
412
+ }
413
+ return res
414
+ }
415
+
416
+ async function autoMD5() {
417
+ let res={
418
+ code:1,
419
+ data:null,
420
+ msg:'error'
421
+ }
422
+ try {
423
+ let md5v=await calculateMD5('./lib/SG.dll')
424
+ res.code=0;
425
+ res.data=md5v;
426
+ res.msg='success';
427
+ } catch (error) {
428
+ res.data=err;
429
+ res.msg=err.message;
430
+ }
431
+ return res
432
+ }
433
+
434
+ module.exports = executeZusbdll;
435
+ module.exports.executeZusbdll = executeZusbdll;
436
+ module.exports.calculateMD5 = calculateMD5
437
+ module.exports.autoMD5 = autoMD5
438
+ module.exports.autoRun = autoRun;
package/lib/SG.auth ADDED
Binary file
package/lib/SG.dll ADDED
Binary file
package/lib/SG.h ADDED
@@ -0,0 +1,23 @@
1
+ #ifndef _SG_H_20251117
2
+ #define _SG_H_20251117
3
+ #include <Windows.h>
4
+
5
+ #ifdef __cplusplus
6
+ extern "C" {
7
+ #endif
8
+ /**************************************************************************/
9
+ // 函数名称:login
10
+ // 函数功能:用ukey认证登录
11
+ // 函数参数:
12
+ // [IN] id 标识
13
+ // [OUT] error 失败时返回的错误码,需要外部开空间(至少32字节)
14
+ // 返回值:1:成功;0:失败
15
+ // 备注:
16
+ /**************************************************************************/
17
+ BOOL login(int id ,char *error);
18
+
19
+ #ifdef __cplusplus
20
+ }
21
+ #endif
22
+
23
+ #endif
package/lib/SG.lib ADDED
Binary file
package/lib/SG_API.dll ADDED
Binary file
package/lib/SG_SKF.dll ADDED
Binary file
Binary file
package/lib/SG_md5.txt ADDED
@@ -0,0 +1 @@
1
+ d9931e97114daa3a30af8caf3c142443
Binary file
Binary file
@@ -0,0 +1,54 @@
1
+ {
2
+ "searchPaths": ["."],
3
+ "commands": [
4
+ {
5
+ "type": "load",
6
+ "path": "./SG.dll",
7
+ "alias": "SG"
8
+ },
9
+ {
10
+ "type": "call",
11
+ "alias": "SG",
12
+ "function": "login",
13
+ "args": [
14
+ "int=0",
15
+ "stringbuilder[32]="
16
+ ],
17
+ "returns": "int"
18
+ },
19
+ {
20
+ "type": "call",
21
+ "alias": "SG",
22
+ "function": "login",
23
+ "args": [
24
+ "int=1",
25
+ "stringbuilder[32]="
26
+ ],
27
+ "returns": "int"
28
+ },
29
+ {
30
+ "type": "call",
31
+ "alias": "SG",
32
+ "function": "login",
33
+ "args": [
34
+ "int=3",
35
+ "stringbuilder[32]="
36
+ ],
37
+ "returns": "int"
38
+ },
39
+ {
40
+ "type": "call",
41
+ "alias": "SG",
42
+ "function": "login",
43
+ "args": [
44
+ "int=4",
45
+ "stringbuilder[32]="
46
+ ],
47
+ "returns": "int"
48
+ },
49
+ {
50
+ "type": "unload",
51
+ "alias": "SG"
52
+ }
53
+ ]
54
+ }
package/lib/zdll.exe ADDED
Binary file
package/package.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "zusbdll",
3
+ "version": "0.0.1",
4
+ "description": "node for zusb dll",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "author": "zhows",
10
+ "license": "ISC",
11
+ "dependencies": {
12
+ "crypto": "^1.0.1"
13
+ }
14
+ }
package/test.js ADDED
@@ -0,0 +1,65 @@
1
+ const {executeZusbdll,autoRun,autoMD5} = require('./index');
2
+ const path = require('path');
3
+
4
+ async function runDemo() {
5
+ console.log("开始测试 login 函数...");
6
+
7
+ try {
8
+ // 使用之前验证过的工作正常的场景文件
9
+ const scenarioPath = path.join(__dirname, "lib", "scenario.json");
10
+ const result = await executeZusbdll(scenarioPath);
11
+
12
+ // 解析返回的 JSON 数据
13
+ let parsedResults;
14
+ try {
15
+ parsedResults = JSON.parse(result.stdout);
16
+ } catch (parseErr) {
17
+ console.log("解析结果失败:", parseErr.message);
18
+ return;
19
+ }
20
+
21
+ // 遍历所有结果,找出 login 调用的结果
22
+ for (let i = 0; i < parsedResults.length; i++) {
23
+ const callResult = parsedResults[i];
24
+ if (callResult.command === "login") {
25
+ // login 函数的返回值在 returnCode 字段中
26
+ const success = callResult.returnCode === 1;
27
+
28
+ // 获取 id 值(从第一个参数中获取)
29
+ const id = callResult.outputs && callResult.outputs[0] ? callResult.outputs[0].value : i;
30
+
31
+ console.log(success ? `id(${id})测试成功!` : `id(${id})测试失败!`);
32
+
33
+ // 显示错误信息(如果有的话)
34
+ if (callResult.outputs && callResult.outputs.length > 1) {
35
+ const errorOutput = callResult.outputs[1];
36
+ if (errorOutput.value) {
37
+ console.log(` 错误信息: ${errorOutput.value}`);
38
+ }
39
+ }
40
+ }
41
+ }
42
+ } catch (err) {
43
+ console.log("测试失败!", err.message);
44
+ console.log("错误详情:", err);
45
+ }
46
+
47
+ console.log("测试完成!");
48
+ }
49
+
50
+ // 执行 demo
51
+ if (require.main === module) {
52
+ // runDemo().catch(console.error);
53
+ }
54
+ (async function(){
55
+ try {
56
+ console.log('start')
57
+ res = await autoRun();
58
+ resmd5 = await autoMD5();
59
+ console.log(resmd5)
60
+ } catch (error) {
61
+ console.log("错误详情:", error);
62
+ }
63
+ })()
64
+
65
+ module.exports = { runDemo };