Javascript 带C/C+的终端服务器上的IPC+;一个nw.js/node.js/node-native-module(C+;+;)?

Javascript 带C/C+的终端服务器上的IPC+;一个nw.js/node.js/node-native-module(C+;+;)?,javascript,c++,node.js,ipc,nw.js,Javascript,C++,Node.js,Ipc,Nw.js,我有一个Win32 DLL(C++),它作为插件加载到另一个应用程序中。DLL启动一个nw.js实例(ShellExecuteEx和SEE_MASK_NOCLOSEPROCESS)并在DLL卸载时结束(通过ShellExecuteEx的hInstance)。我需要一种向nw进程发送字符串(普通ansi)并检索答案(也是字符串)的方法。旧方法是一个简单的http请求,其响应在主体中。但在开发过程中环境发生了变化,“包”应用程序dll nw由同一用户多次运行,多个用户在同一台机器(终端服务器)上运行

我有一个Win32 DLL(C++),它作为插件加载到另一个应用程序中。DLL启动一个nw.js实例(ShellExecuteEx和SEE_MASK_NOCLOSEPROCESS)并在DLL卸载时结束(通过ShellExecuteEx的hInstance)。我需要一种向nw进程发送字符串(普通ansi)并检索答案(也是字符串)的方法。旧方法是一个简单的http请求,其响应在主体中。但在开发过程中环境发生了变化,“包”应用程序dll nw由同一用户多次运行,多个用户在同一台机器(终端服务器)上运行。所以端口列表是“不可能的”(是随机端口或单例nw,但不是)

我找到了不同的方法:

  • 套接字端口列表问题
  • wm_copydata/wm_…-需要一个带有隐藏窗口的自定义nw插件(无本地nw方式);无请求-响应系统
  • RPC-端口列表问题
  • DDE—没有本地javascript方式(找到一个使用.net的模块);在我以前的delphi时代,DDE不是一个简单的任务,它失败了很多次,没有逻辑
  • 共享记忆-没有经验;期望值:异步、触发器?,无本机javascript方式
  • 共享文件-没有经验;期望值:异步、触发器(文件更改时的观察者),但存在同步问题,可能是原生js方式
  • 命名管道-无经验;期望值:win32 api和类似于聊天系统(管道内[send broadcast]和管道外[receive broadcast],或两者合一)?如果是,我可以对所有实例使用一个名称,使用唯一标识符并等待正确答案
什么是一种好的、简单的通信方式,像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-我的解决方案

通过命名管道和简化版本的,我找到了一个工作方法

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”;
#定义BUFSIZE 512
std::string SendPipeRequestA(std::string sRequest){
DWORD dwToWrite、DWWRITED、dwRead;
成功;
char chBuf[BUFSIZE];
向量缓冲区;
HANDLE hPipe=CreateFileA(PipenameA.c_str(),GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
if(hPipe==无效的句柄值)
返回“-1 |管道错误1(连接)”;
dwToWrite=(lstrlenA(sRequest.c_str())+1)*sizeof(char);
bSuccess=WriteFile(hPipe,sRequest.c_str(),dwToWrite,&dwwrited,NULL);
如果(!b成功)
返回“-1 |管道错误2(写入)”;
做{
bSuccess=ReadFile(hPipe,chBuf,BUFSIZE*sizeof(char),&dwRead,NULL);
如果(!bSuccess&&GetLastError()!=错误\u更多\u数据)
打破
insert(buffer.end(),chBuf,chBuf+dwRead);
}而(!b成功);
std::字符串响应(&buffer[0]);
闭柄(hPipe);
返回sResponse.c_str();
}

//Jonny

你会得到基于意见的答案,请注意这一点

您可以将数据作为命令行参数注入JS模块 例如
start nw.js MyData
并使用
process.argv
在JS中获取它

现在,将数据返回到C++可执行文件/DLL有点棘手。 如果您shell执行该进程,您就可以拥有该进程的句柄。


您可以从JS部件将数据打印到标准输出中,并通过从进程句柄获取标准输出句柄在本机应用程序中读取数据

使用自定义url注册你的nw.js应用程序应该是一种优雅的方式。 例如“github://”、“thunder://”、“twitter://”

在windows上,您可以查看:

使用自定义url,您可以在单实例模式下向nw.js提供简单的参数。见:


如果需要更多数据,base64可能会有所帮助,甚至可以通过LZ字符串压缩方法提供更多数据。

问题不在于开始参数。我需要一个永久的可能性发送消息。stdin和stdout也是一个想法,但nw本身不可能用stdXY编写。另外,我不确定对std的读写对于dll来说是否太复杂,因为这部分需要一个额外的线程。dll等待主应用程序的调用,std上的等待会阻塞整个应用程序。
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();
}