first commit
This commit is contained in:
commit
afbb62d536
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
exe
|
43
README.MD
Normal file
43
README.MD
Normal file
@ -0,0 +1,43 @@
|
||||
## Installation
|
||||
```
|
||||
npm install git+https://git.wm-app.xyz/dev/csharp-process.git
|
||||
```
|
||||
or
|
||||
```
|
||||
yarn add git+https://git.wm-app.xyz/dev/csharp-process.git
|
||||
```
|
||||
|
||||
## Usage
|
||||
in C#
|
||||
```cs
|
||||
class Program : NodeProcess
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
NodeSharp.Start(new Program());
|
||||
}
|
||||
|
||||
public override void OnAction(NodeParam param, RPCHandle rpc)
|
||||
{
|
||||
|
||||
rpc.Send(" ==> test " + param.data);
|
||||
}
|
||||
}
|
||||
```
|
||||
in node
|
||||
```js
|
||||
import Porcess from 'csharp-process'
|
||||
|
||||
const service = new Process('./demo.exe',result => {
|
||||
console.log('result:',result)
|
||||
},error => {
|
||||
console.log('error:',error)
|
||||
});
|
||||
|
||||
try {
|
||||
const result = await service.send('hello csharp', 'test');
|
||||
console.log('process result:', result)
|
||||
} catch (e) {
|
||||
console.log('process Error:', e)
|
||||
}
|
||||
```
|
194
csharp-process.js
Normal file
194
csharp-process.js
Normal file
@ -0,0 +1,194 @@
|
||||
const iconv = require('iconv-lite');
|
||||
class childProcess {
|
||||
/**
|
||||
*
|
||||
* @param {String|any} option
|
||||
* @param {Function} messageCallback
|
||||
* @param {Function} errorCallback
|
||||
*/
|
||||
constructor(option, messageCallback = null, errorCallback = null) {
|
||||
this.childprocess = null;
|
||||
this.onceListenters = {};
|
||||
this.alawysListenters = {};
|
||||
this.cachedata = "";
|
||||
this.alwaysListenter = null;
|
||||
this.errorListenter = null;
|
||||
this.trueClose = false;
|
||||
var me = this;
|
||||
|
||||
var defaultOpt = {
|
||||
exe: 'NYSProcess.exe',
|
||||
closeCallback: function (exitcode) { },
|
||||
autoReOpen: false,
|
||||
args: []
|
||||
};
|
||||
var opt = null;
|
||||
if (typeof option == 'string') {
|
||||
defaultOpt.exe = option;
|
||||
opt = defaultOpt;
|
||||
}
|
||||
else {
|
||||
var extend = require('util')._extend;
|
||||
opt = extend(defaultOpt, option);
|
||||
}
|
||||
opt.args = ['pos'].concat(opt.args);
|
||||
function S4() {
|
||||
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
|
||||
};
|
||||
|
||||
this.guid = function () {
|
||||
return (S4() + S4() + S4() + S4() + S4() + S4() + S4() + S4());
|
||||
};
|
||||
|
||||
function endsWith(str, suffix) {
|
||||
return str.indexOf(suffix, str.length - suffix.length) !== -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取参数
|
||||
* @param {any} obj
|
||||
* @returns
|
||||
*/
|
||||
function buildParam(obj) {
|
||||
return { cguid: me.guid(), data: obj };
|
||||
}
|
||||
|
||||
// 打开程序进程
|
||||
this.open = function () {
|
||||
var exec = require("child_process").spawn;
|
||||
|
||||
me.childprocess = exec(opt.exe, opt.args);
|
||||
if (me.childprocess == null) {
|
||||
if (opt.closeCallback) {
|
||||
throw new Error('启动进程失败');
|
||||
}
|
||||
}
|
||||
// 设置标准的输入输出
|
||||
me.childprocess.stdin.setEncoding("binary");
|
||||
me.childprocess.stdout.setEncoding("binary");
|
||||
// 监听进程退出事件
|
||||
me.childprocess.on('exit', function (code) {
|
||||
if (opt.autoReOpen && code != 0 && !me.trueClose) {
|
||||
// 自动重启
|
||||
setTimeout(function () {
|
||||
me.open();
|
||||
console.log('reopen' + opt.exe, !!me.childprocess);
|
||||
}, 1000);
|
||||
}
|
||||
if (opt.closeCallback) {
|
||||
opt.closeCallback(code)
|
||||
}
|
||||
});
|
||||
// 监听程序得输出事件
|
||||
me.childprocess.stdout.on('data', function (data) {
|
||||
var result = null;
|
||||
var json = '';
|
||||
try {
|
||||
// 获取输入内容
|
||||
json = data.toString();
|
||||
// console.log('process out:', json);
|
||||
if (endsWith(json, '\r\n')) {
|
||||
json = json.substr(0, json.length - 1);
|
||||
}
|
||||
json = me.cachedata + json;
|
||||
me.cachedata = "";
|
||||
let resultdatas = json.split('@=@');
|
||||
// 解析数据对象
|
||||
for (let j in resultdatas) {
|
||||
if (resultdatas.length == 1) {
|
||||
me.cachedata += resultdatas[j];
|
||||
continue;
|
||||
}
|
||||
if (j == (resultdatas.length - 1) && resultdatas[j] != '') {
|
||||
me.cachedata += resultdatas[j];
|
||||
continue;
|
||||
}
|
||||
|
||||
let jsondata = "";
|
||||
try {
|
||||
jsondata = JSON.parse(resultdatas[j]);
|
||||
|
||||
} catch (ee) {
|
||||
me.cachedata += resultdatas[j];
|
||||
continue;
|
||||
}
|
||||
// 对数据进行回调
|
||||
if (me.onceListenters[jsondata.cguid]) {
|
||||
|
||||
// 回调
|
||||
me.onceListenters[jsondata.cguid](jsondata.Error, jsondata.data);
|
||||
// 删除回调
|
||||
delete me.onceListenters[jsondata.cguid];
|
||||
}
|
||||
|
||||
if (me.alawysListenters[jsondata.cguid]) {
|
||||
me.alawysListenters[jsondata.cguid](jsondata.Error, jsondata.data);
|
||||
}
|
||||
|
||||
if (me.alwaysListenter) {
|
||||
me.alwaysListenter(jsondata.data, jsondata.Error);
|
||||
}
|
||||
if (me.errorListenter && jsondata.Error && jsondata.Error.length > 2) {
|
||||
me.errorListenter(jsondata.Error);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
// 错误回调
|
||||
if (me.errorListenter) {
|
||||
me.errorListenter(e.message);
|
||||
} else {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 停止进程
|
||||
this.close = function (close = true) {
|
||||
me.trueClose = close;
|
||||
me.childprocess.kill();
|
||||
};
|
||||
this.exit = function () {
|
||||
me.trueClose = true;
|
||||
me.childprocess.kill();
|
||||
};
|
||||
/**
|
||||
* 发送数据,注意此方法只会响应一次
|
||||
* @param {any} data 待发送数据
|
||||
* @param {string} command 指令
|
||||
*/
|
||||
this.send = function (param, command = 'default') {
|
||||
return new Promise((resolve, reject) => {
|
||||
let error = null;
|
||||
if (!me.childprocess) {
|
||||
error = '所需进程尚未启动';
|
||||
}
|
||||
if (!me.childprocess.stdin.writable) {
|
||||
error = '无法建立通道连接';
|
||||
}
|
||||
if (error) {
|
||||
reject(new Error(error));
|
||||
} else {
|
||||
const data = buildParam({ command, param });
|
||||
// console.log('==> send data:', JSON.stringify(data))
|
||||
// 设置回调
|
||||
me.onceListenters[data.cguid] = (err, data) => {
|
||||
if (err) {
|
||||
reject(new Error(err));
|
||||
} else {
|
||||
resolve(data)
|
||||
}
|
||||
};
|
||||
// 写入数据
|
||||
me.childprocess.stdin.write(iconv.encode(JSON.stringify(data) + "\r\n", 'gbk'));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
me.alwaysListenter = messageCallback;
|
||||
me.errorListenter = errorCallback;
|
||||
me.open();
|
||||
}
|
||||
}
|
||||
module.exports = childProcess;
|
49
example.js
Normal file
49
example.js
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
const { setInterval } = require('timers');
|
||||
const Process = require('./csharp-process');
|
||||
|
||||
//正常启动一个exe
|
||||
// var exeservice=new childprocess('./exe/NodeSharpTest.exe');
|
||||
// console.log(exeservice);
|
||||
|
||||
|
||||
//高级启动
|
||||
// var defaultOpt = {
|
||||
// exe: 'NYSProcess.exe',//exe 路径
|
||||
// closeCallback: function (exitcode) { },//exe退出的回调
|
||||
// autoReOpen: false,//是否自动启动(如exe异常终止后可以自动重启)
|
||||
// args: []//给exe的启动参数
|
||||
// };
|
||||
const processOption = {
|
||||
exe: '',
|
||||
autoReOpen: true,
|
||||
args: []
|
||||
};
|
||||
const service = new Process('./exe/NodeSharpTest.exe', (result, error) => {
|
||||
// console.log('result:',result,error)
|
||||
});
|
||||
|
||||
//exe已经运行时的 通信对象,要求是必须可以格式化为json字符串,而且必须有command字段
|
||||
var onceParam = { command: 'once', data: "demo" };
|
||||
// 一次性的回调,执行后即被回收
|
||||
var onceFunction = function (err, data) { console.log(data); };
|
||||
|
||||
/***
|
||||
var alwaysparam = { command: 'always', data: { demo: "this is demo date" } };
|
||||
|
||||
// 监听性的回调,创建后可伴随exe整个生命周期
|
||||
var alwaysfun = function (err, data) {
|
||||
if (err) {return console.error(err);}console.log(data);
|
||||
};
|
||||
*/
|
||||
// service.send(onceParam, onceFunction);
|
||||
// exeservice.send(alwaysparam, function () { }, alwaysfun);
|
||||
(async () => {
|
||||
try {
|
||||
const result = await service.send({ title: '测试标题', message: "内容xxx", number: '123123' }, 'print');
|
||||
console.log('C# return result:', result)
|
||||
} catch (e) {
|
||||
console.log('C# return ', e)
|
||||
}
|
||||
service.exit();
|
||||
})();
|
16
package.json
Normal file
16
package.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "csharp-process",
|
||||
"version": "1.0.0",
|
||||
"description": "call csharp process",
|
||||
"main": "csharp-process.js",
|
||||
"dependencies": {
|
||||
"iconv-lite": "^0.4.5"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"scripts": {
|
||||
"dev": "node example.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user