简体   繁体   English

如何轻松地将非常长的字符串传递给Windows下的工作进程?

[英]How to easily pass a very long string to a worker process under Windows?

My native C++ Win32 program spawns a worker process and needs to pass a huge configuration string to it. 我的本机C ++ Win32程序产生一个工作进程,需要向它传递一个巨大的配置字符串。 Currently it just passes the string as a command line to CreateProcess() . 目前它只是将字符串作为命令行传递给CreateProcess() The problem is the string is getting longer and now it doesn't fit into the 32K characters limitation imposed by Windows. 问题是字符串越来越长,现在它不适合Windows强加的32K字符限制。

Of course I could do something like complicating the worker process start - I use the RPC server in it anyway and I could introduce an RPC request for passing the configuration string, but this will require a lot of changes and make the solution not so reliable. 当然我可以做一些事情,比如复杂的工作进程启动 - 无论如何我在其中使用RPC服务器,我可以引入一个RPC请求来传递配置字符串,但这需要进行大量更改并使解决方案不那么可靠。 Saving the data into a file for passing is also not very elegant - the file could be left on the filesystem and become garbage. 将数据保存到文件中以便传递也不是很优雅 - 文件可能会留在文件系统上并变成垃圾。

What other simple ways are there for passing long strings to a worker process started by my program on Windows? 还有哪些简单的方法可以将长字符串传递给我在Windows上的程序启动的工作进程?

One possible strategy is to create a named Pipe and pass the handle ( or pipe name) to the other process. 一种可能的策略是创建一个命名管道并将句柄(或管道名称)传递给另一个进程。 Then use normal Read\\Write operations on Pipe to extract the data. 然后在Pipe上使用正常的Read / Write操作来提取数据。

There are several good answers already, but the easiest way is to save it in a file, and pass the filename in the command line. 已有几个好的答案,但最简单的方法是将其保存在文件中,并在命令行中传递文件名。

As well as being simple, an advantage of this approach is that the apps will be very loosely coupled (you'll potentially be able to use the child application stand-alone in other ways, rather than always having to launch it from a program that knows how to pipe data into it via a specialised interface) 除了简单之外,这种方法的一个优点是应用程序将非常松散地耦合(您可能能够以其他方式独立使用子应用程序,而不是总是必须从一个程序启动它知道如何通过专门的接口将数据传输到它

If you want to be sure that the file is cleaned up after processing, mark it for deletion on the next reboot. 如果要确保在处理后清除文件,请在下次重新引导时将其标记为删除。 THen if anybody forgets to clean it up, the OS will deal with it for you on the next reboot. 如果有人忘记清理它,操作系统将在下次重启时为您处理。

I would prefer Boost's message queue. 我更喜欢Boost的消息队列。 It's extremely simple yet sophisticated. 它非常简单而复杂。 Here's example: 这是一个例子:


#include <boost/interprocess/ipc/message_queue.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/shared_ptr.hpp>

using namespace boost::interprocess;

// ------------------------------------------------------------------------------
// Your worker:
// ------------------------------------------------------------------------------

try {
        message_queue::remove("NAME_OF_YOUR_QUEUE");

        boost::shared_ptr<message_queue> mq(new message_queue(create_only, "NAME_OF_YOUR_QUEUE", 65535, 32));

        char message[1024];
        std::size_t size_received;
        unsigned int priority;

        if (mq->timed_receive(&message, sizeof(message), size_received, priority, boost::posix_time::ptime(boost::posix_time::second_clock::universal_time()) + boost::posix_time::seconds(1))) {
                std::string s(message); // s now contains the message.
        }
} catch (std::exception &) {
        // ...
}

// ------------------------------------------------------------------------------
// And the sender:
// ------------------------------------------------------------------------------

try {
        boost::shared_ptr<message_queue> mq(new message_queue(create_only, "NAME_OF_YOUR_QUEUE", 1024, 1024));
        std::stringstream message;

        message << "the very very very long message you wish to send over";

        while (!mq.try_send(message.str().c_str(), message.str().length(), 0))
                ::Sleep(33);
} catch (std::exception &) {
        // ...
}

Use shared memory. 使用共享内存。 Pass to a worker process name of shared memory object. 传递给共享内存对象的工作进程名称。 Another solution is to use WM_COPYDATA message. 另一种解决方案是使用WM_COPYDATA消息。

How about reading it from stdin :) It seems to work for the Unix folks. 如何从stdin读取它:)它似乎适用于Unix人。

Guaranteed a lot easier than passing pipe names/handles around! 保证比传递管道名称/句柄更容易!

Here is some official code from MSDN for creating child processes with I/O pipes. 以下是MSDN中用于使用I / O管道创建子进程的一些官方代码

Is it a possibility to set up a named shared memory segment? 是否可以设置命名的共享内存段?

http://msdn.microsoft.com/en-us/library/aa366551(VS.85).aspx http://msdn.microsoft.com/en-us/library/aa366551(VS.85).aspx

You could use an inheritable handle to a section object. 您可以使用可继承的句柄来处理节对象。 In your parent process create a section object (CreateFileMapping) and specify that its handle is to be inherited by the child process; 在父进程中创建一个section对象(CreateFileMapping)并指定它的句柄将由子进程继承; then pass the handle value to the child process on the command line. 然后将句柄值传递给命令行上的子进程。 The child process can then open the section object (OpenFileMapping). 然后,子进程可以打开section对象(OpenFileMapping)。 Though I would prefer a named section object as the semantics of using it are easier to understand. 虽然我更喜欢命名的section对象,因为使用它的语义更容易理解。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM