简体   繁体   English

在 Windows 中是否有一种明确的方式来通信两个程序?

[英]Is there a clear way of communicate two programs in windows?

My goal is just the following:我的目标只是以下几点:

Send a JSON stringified (from my program) to another program (external program) and wait for a string response, also a JSON stringified.将字符串化的 JSON(从我的程序)发送到另一个程序(外部程序)并等待字符串响应,也是字符串化的 JSON。 This is no matter of JSON programming.这与 JSON 编程无关。 The code (both program really are c++ programs) that I use is:我使用的代码(两个程序实际上都是 C++ 程序)是:

void initializePipeCommunication(){

//HANDLE que representa la salida estandar de este programa (DLL). Se conectara con la entrada estandar del otro programa
HANDLE this_write;

//HANDLE que representa la entrada estandar de este programa (DLL).
HANDLE this_read;

//informacion del proceso asociado al programa externo, es necesaria esta variable para cerrar la comunicacion
PROCESS_INFORMATION externalProcessInformation;

//HANDLE que representa la entrada estandar del otro programa.
HANDLE child_input_read;

//HANDLE que representa la salida estandar del otro programa.
HANDLE child_output_write;

STARTUPINFO startup_info;
SECURITY_ATTRIBUTES security_attributes;

// Set the security attributes for the pipe handles created
security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
security_attributes.bInheritHandle = TRUE;
security_attributes.lpSecurityDescriptor = NULL;

CreatePipe(&this_read, &child_output_write, &security_attributes, 0);
CreatePipe(&child_input_read, &this_write, &security_attributes, 0);

ZeroMemory(&externalProcessInformation, sizeof(PROCESS_INFORMATION));
ZeroMemory(&startup_info, sizeof(STARTUPINFO));

startup_info.cb = sizeof(STARTUPINFO);
startup_info.hStdInput = child_input_read;
startup_info.hStdOutput = child_output_write;
//startup_info.hStdError = child_output_write;
startup_info.dwFlags |= STARTF_USESTDHANDLES;
startup_info.dwFlags |= STARTF_USESHOWWINDOW;


TCHAR* szCommandLine = loadExecutablePathFromRegistryWide();
lstrcatW(szCommandLine, L" UsePipeMode");

//Creando el programa externo
if (!CreateProcess(NULL, szCommandLine, NULL, NULL,
    TRUE, 0/*CREATE_NEW_CONSOLE*/, NULL, NULL, &startup_info, &externalProcessInformation)){
    DWORD dwStatus = GetLastError();

    if (dwStatus == ERROR_CANCELLED || dwStatus == ERROR_ELEVATION_REQUIRED) {          
        Errors::report(Errors::BAD_EXTERNAL_PROGRAM_PRIVILEGES);
    }
    else if (dwStatus == ERROR_FILE_NOT_FOUND) {
        // The file defined by lpFile was not found and an error message popped up. 
        Errors::report(Errors::BAD_EXTERNAL_PROGRAM_PATH);
    }
    PluginHelper::log("error # ");
    PluginHelper::logn(std::to_string(dwStatus).c_str());
}}

void write(std::string msg){
    unsigned long dwWritten, toWrite = msg.length();
    WriteFile(this_write, msg.c_str(), toWrite, &dwWritten, NULL);
}



std::string read(){
    unsigned long dwRead, dwWritten;
    static char* chBuf = (char*)malloc(266240);
    ReadFile(this_read, chBuf, 266240, &dwRead, NULL);
    chBuf[dwRead] = 0;
    std::string g(chBuf);           
    return (g.substr(0, g.length()));
}

That is using pipes, in fact, anonymous pipes in both sides.那就是使用管道,实际上是双方的匿名管道。 I don´t care about asynchronous communication.我不关心异步通信。

The problem is that the string I send is around 266KB and sometimes the response from the external program came with a bad JSON format, again, in the external program the stringified JSON is well constructed and sent to my program (the logs confirm that).问题是我发送的字符串大约为 266KB,有时来自外部程序的响应带有错误的 JSON 格式,同样,在外部程序中,字符串化的 JSON 构造良好并发送到我的程序(日志证实了这一点)。 Summarizing, the anonymous pipes in both sides are the same, and in the external program the string emitted to my program is well, besides that, in my program the response is another that I expect (plus inconsistent errors, like exceptions text concatenated to the JSON with no sense).总而言之,双方的匿名管道是相同的,在外部程序中,发送到我的程序的字符串很好,除此之外,在我的程序中,响应是我期望的另一个(加上不一致的错误,如连接到没有意义的 JSON)。

Some ask:有人问:

• Is well or at least error proof the above code? • 上面的代码是否很好或至少是防错的?

• Is there an Input/output way, ie cin/cout way of communication without the need of hard tricking? • 是否有输入/输出方式,即cin/cout 通信方式而无需硬欺骗? (Like Google Chrome Native Messaging Interface does) (就像 Google Chrome 本机消息界面那样)

I've been doing Win32 coding for 20+ years and written servers, apps, you name it.我从事 Win32 编码已有 20 多年,并编写过服务器、应用程序,应有尽有。 I think the only reason I'd use pipes is for easy (but limited utility) ACL'ing of the endpoint, or to be able to impersonate the client .我认为我使用管道的唯一原因是为了方便(但有限的效用)端点的 ACL,或者能够模拟客户端 Otherwise, it's just proprietary and not terribly performant.否则,它只是专有的,性能不是很好。

As for the corruption you report, my guess would be it's truncation because you're assuming that all the data is read at once, which is neither guaranteed by the OS nor even likely given the size of your data.至于您报告的损坏,我的猜测是截断,因为您假设所有数据都被一次读取,操作系统既不能保证,也不可能考虑到数据的大小。 I'd suggest modifying your protocol to always send a DWORD dwBytesSent first, read that, then loop until you've read that many bytes off the pipe.我建议修改您的协议以始终首先发送 DWORD dwBytesSent,读取它,然后循环直到您从管道中读取了那么多字节。

If I were you, since this data sounds like it gets large, I'd probably just write it to a file.如果我是你,因为这些数据听起来好像变大了,我可能会把它写到一个文件中。 You can use GetTempFileName() to figure out where to write it.您可以使用GetTempFileName()找出写入位置。 You can have a simple prefix unique to your application to cleanup orphan files, eg more than a day old.您可以使用应用程序独有的简单前缀来清理孤立文件,例如超过一天的文件。 And then just simple (and generally at least as fast) APIs to read/write data.然后只是简单的(通常至少是同样快的)API 来读/写数据。

IF you want more performance (and complexity) you can do shared memory or sockets.如果您想要更高的性能(和复杂性),您可以使用共享内存或套接字。 Sockets are nice for portability, but have some extra overhead (loopback adapter isn't super fast) and you'll want to turn off Nagling: setsockopt(TCP_NODELAY) .套接字对于可移植性很好,但有一些额外的开销(环回适配器不是超快),您需要关闭 Nagling: setsockopt(TCP_NODELAY) Shared memory is no harder than the APIs you're using for pipes, but is more performant, but you'll need to invent a protocol within it (eg first DWORD is status, second DWORD is length, rest is data).共享内存并不比您用于管道的 API 难,但性能更高,但您需要在其中发明一个协议(例如,第一个 DWORD 是状态,第二个 DWORD 是长度,其余的是数据)。 Microsoft has a nice tutorial article .微软有一篇很好的教程文章

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C++ 如何让两个程序通信? - C++ How to make two programs communicate? 如何在Windows中的两个程序之间快速交换 - How to quick swap between two programs in windows 在Windows上编写脚本或创建程序的快速方法? - quick way to scripting or creating programs on Windows? 在Windows中运行/调试python程序最干净的方法 - Cleanest way to run/debug python programs in windows 在Windows中对程序进行基准测试的最佳方法是什么? - What's the best way to benchmark programs in Windows? 与Windows应用程序之间进行通信的最佳方式是什么? - What is the best way to communicate between to windows application? “正确”的方式与本地Windows服务进行通信 - “Correct” way to communicate with a local Windows Service Windows 凭据提供程序 - 有没有办法与 Windows Hello API 进行通信或干扰? - Windows Credential Provider - Is there a way to communicate or interfere with windows Hello API? python瓶可以在WINDOWS上的相同地址和端口上运行两个程序 - python bottle can run two programs on the same address and port on WINDOWS 用Python获取所有已安装的Windows程序的'正确'和可靠的方法? - 'proper' & reliable way to get all installed windows programs in Python?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM