带有 C/C++ 和 nw.js/node.js/node-native-module (C++) 的终端服务器上的 IPC?
Posted
技术标签:
【中文标题】带有 C/C++ 和 nw.js/node.js/node-native-module (C++) 的终端服务器上的 IPC?【英文标题】:IPC on Terminal Server with C/C++ an nw.js/node.js/node-native-module (C++)? 【发布时间】:2015-06-28 10:51:11 【问题描述】:我有一个 Win32-DLL (C++),它作为插件加载到另一个应用程序中。 DLL 启动一个 nw.js 实例(ShellExecuteEx 和 SEE_MASK_NOCLOSEPROCESS)并在 DLL 卸载时结束它(通过 ShellExecuteEx 的 hInstance)。我需要一种将字符串(普通 ansi)发送到 nw 进程并检索答案(也是字符串)的方法。旧的方式是一个简单的 http-request,响应在 body 中。但是在开发过程中环境发生了变化,“包”app-dll-nw由同一用户多次运行,多个用户在同一台机器(终端服务器)上运行。所以端口列表是“不可能的”(是的随机端口或单例 nw,但没有)。
我找到了不同的方法:
socket - 端口列表问题 wm_copydata/wm_... - 需要一个带有隐藏窗口的自定义 nw 插件(没有原生 nw 方式);没有请求响应系统 RPC - 端口列表问题 DDE - 没有原生 javascript 方式(找到了一个使用 .net 的模块);在我以前的 delphi 时代,DDE 不是那么简单的任务,它多次失败,没有逻辑。 共享内存 - 没有经验;期望:异步、触发?,没有原生 javascript 方式 共享文件 - 没有经验;期望:异步,触发器(文件更改的观察者)但同步问题,本机 js 方式可能 命名管道 - 没有经验;期望:win32-api 和类似聊天系统(管道内 [发送广播] 和管道外 [接收广播],或两者合二为一)?如果是,我可以对所有实例使用一个名称并使用唯一标识符并等待正确答案。什么是一种像 http 方式但没有网络的又好又简单的通信方式?
更新 1:节点模块“net”能够为命名管道创建服务器。第一次测试,将一个字符串从 dll 发送到 nw,成功了。
var server = net.createServer(function(stream)
stream.on('data', function(c)
console.log('data:', c.toString());
);
stream.on('end', function()
//server.close();
);
);
server.listen('\\\\.\\pipe\\MyAppDynamicGUID');
更新 2 - 我的解决方案
通过命名管道和https://msdn.microsoft.com/en-us/library/windows/desktop/aa365592(v=vs.85).aspx 的简化版本,我找到了一种工作方法。
nw.js 中的服务器:
var server = net.createServer(function(req)
req.on('data', function(c)
console.log(c.toString());
req.write('123|Hello World', 'ascii');
);
);
server.listen('\\\\.\\pipe\\MyAppDynamicGUID');
C++ 中的客户端(无永久连接、奇怪的字符串处理、简化的错误处理):
static std::string PipenameA = "\\\\.\\pipe\\MyAppDynamicGUID";
#define BUFSIZE 512
std::string SendPipeRequestA(std::string sRequest)
DWORD dwToWrite, dwWritten, dwRead;
BOOL bSuccess;
char chBuf[BUFSIZE];
std::vector<char> buffer;
HANDLE hPipe = CreateFileA(PipenameA.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hPipe == INVALID_HANDLE_VALUE)
return "-1|Pipe-Error 1 (connect)";
dwToWrite = (lstrlenA(sRequest.c_str())+1)*sizeof(char);
bSuccess = WriteFile(hPipe, sRequest.c_str(), dwToWrite, &dwWritten, NULL);
if (!bSuccess)
return "-1|Pipe-Error 2 (write)";
do
bSuccess = ReadFile(hPipe, chBuf, BUFSIZE*sizeof(char), &dwRead, NULL);
if (!bSuccess && GetLastError() != ERROR_MORE_DATA)
break;
buffer.insert(buffer.end(), chBuf, chBuf + dwRead);
while (!bSuccess);
std::string sResponse(&buffer[0]);
CloseHandle(hPipe);
return sResponse.c_str();
// 强尼
【问题讨论】:
【参考方案1】:您将获得的答案将基于意见,请注意这一点。
您可以将数据作为命令行参数注入到 JS 模块中
例如
start nw.js MyData
并使用process.argv
将其放入 JS 中。
现在,将数据发送回 C++ 可执行文件/DLL 有点棘手。 如果你用 shell 执行这个过程,你可以拥有它的句柄。 您可以将数据从 JS 部分打印到标准输出中,并通过从进程句柄中获取标准输出句柄在本机应用程序中读取它。
【讨论】:
问题不在于起始参数。我需要一个永久的可能性来发送消息。 stdin 和 stdout 也是一个想法,但 nw 没有原生的可能性来用 stdXY 编写。另外,我不确定对 dll 的 std 读写是否复杂,因为这部分需要一个额外的线程。 dll 等待主应用程序的调用,等待 std 阻塞整个应用程序。【参考方案2】:使用自定义 url 注册您的 nw.js 应用程序应该是一种优雅的方式。 如“github://”、“thunder://”、“twitter://”
在windows上你可以看看:
https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx
使用自定义 url,您可以在单实例模式下将简单的参数传递给 nw.js。见:
https://github.com/nwjs/nw.js/wiki/Handling-files-and-arguments#open-file-with-existing-app
如果需要更多数据,base64 可能会有所帮助,甚至可以通过 LZ-String 压缩方法提供更多数据。
【讨论】:
以上是关于带有 C/C++ 和 nw.js/node.js/node-native-module (C++) 的终端服务器上的 IPC?的主要内容,如果未能解决你的问题,请参考以下文章
无法在带有 VS2017 的 Windows 10 上安装和使用 gRPC C/C++