Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. Currently it just passes the string as a command line to CreateProcess(). The problem is the string is getting longer and now it doesn't fit into the 32K characters limitation imposed by Windows.

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. 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?

like image 392
sharptooth Avatar asked Apr 05 '10 07:04

sharptooth


4 Answers

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.

like image 163
aJ. Avatar answered Nov 02 '22 23:11

aJ.


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.

like image 43
Jason Williams Avatar answered Nov 03 '22 00:11

Jason Williams


I would prefer Boost's message queue. 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 &) {
        // ...
}
like image 31
nhaa123 Avatar answered Nov 03 '22 00:11

nhaa123


Use shared memory. Pass to a worker process name of shared memory object. Another solution is to use WM_COPYDATA message.

like image 36
Kirill V. Lyadvinsky Avatar answered Nov 02 '22 22:11

Kirill V. Lyadvinsky