Solved

Using CreateProcess() to call a C++ program and communicating back and forth with it from MFC GUI interface.

Posted on 2004-04-29
6
2,834 Views
Last Modified: 2013-12-03
Hi all,
I have a Win32 (MFC) application that serves as an interface to time-consuming scientific computation. Currently I have the main interface thread start the scientific computation in a separate worker-thread (using AfxBeginThread()). I also pass a pointer to a relatively large parameter structure/object to the scientific worker-thread function. The structure contains a number of control parameters and input/output file names. One of the parameters is a Boolean variable, which gives main thread power to terminate the worker-thread function in the middle of its computation, if necessary. The worker thread also communicates back with the main thread (using windows messages) to update the Progress Bar, status, etc.
My employer now wants me to separate the main interface thread and the time-intensive worker thread into separate processes. The idea is to give users the ability to look at and modify the scientific code, but not the interface code. That’s where I am at right now. I realize I can use CreateProcess() and ShellExecuteEx()/ShellExecute() functions to start the scientific worker-process from the main interface-process. The user would have to enter (in the main interface-process) the path name to the executable they obtained after recompiling the scientific worker-program. I can also probably stuff all of the parameters: about 15 numbers and 20 long input/output file names into the parameter character string. However, how do I terminate such process in mid-run at will from the main interface? Also, how can the scientific worker-process communicate with the main interface-process to update its status information, progress bar, etc.? Would 2-way communication be possible with such setup? If not, could anyone suggest an alternative setup?  
I would appreciate any help/advice/code you could offer me.
Thank you in advance.
0
Comment
Question by:abuly80
  • 3
  • 2
6 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 10955169
>>However, how do I terminate such process in mid-run at will from the main
>>interface?

As for this part of your question, see http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/Q178/8/93.ASP&NoWebContent=1 ("HOWTO: Terminate an Application "Cleanly" in Win32")

>>Also, how can the scientific worker-process communicate with the main
>>interface-process to update its status information, progress bar, etc.?

There's the bad news: If that process is not providing any notifications about the progress (most likely to be documented in the manufacturer's manual), you are out of luck.
0
 

Author Comment

by:abuly80
ID: 10955380
I am sorry if I was not clear enough. The process I will need to terminate is a windowless program, which I currently use as a worker-thread in my application. The article you referred me to states: "In a perfect world, your process could ask another process, through some form of inter-process communication, to shut down. However, if you do not have source-level control of the application that you wish to shut down, then you may not have this option." My question is: how do I design "some form of inter-process communication" mechanism to make this possible, because I do have "source-level control" over the application I need to shut down.

The same goes for the second point you made. In fact, I can legislate the worker-process to provide all the notifications of progress I require.

I just do not know how to make a leap from thread-based to process-based multitasking. For example, I used to start the worker thread with code similar to below:
typedef struct
{

HWND hCommunicationWnd;
BOOL bContinue;
} params_t;

params_t params;
params.bContinue = TRUE;
params.hCommunicationWnd = this.m_hWnd;
AfxBeginThread(ScientificCalculation,&params);

To terminate such worker thread I would program it to terminate on params.bContinue being FALSE. To inform the main thread of the worker-thread’s progress, I would program the worker thread to send update messages to hCommunicationWnd.

Now, when I go from using different threads within the same process to using different processes/programs, how do I cleanly terminate the worker-process from the main interface process? Also, how do I send messages from one process to another? Can I pass the window handle or a pointer to a boolean continue-or-stop variable from one process to another?

Hope this clears things up a bit. Thanks again.
0
 
LVL 3

Accepted Solution

by:
MikProg earned 415 total points
ID: 10957823
Windows API brings you many abylities for interporcess communication and data exchange.
First: Events.
  CreateEvent
  SetEvent
  ResetEvent
 This one intend to notify about 'events'. Process that want to notify another process sets event to signaled state and process to be notifyed reads event and reset it to nonsignaled state.
Second: Shared memory.
This implemented throught Memory Mapped Files. Thise files may have underlying phisical file but may have not. It is standart mechanism for interprocess data exchange
Follows text from Win32 API help files

The first process calls the CreateFileMapping function to create a file-mapping object and give it the name MyFileMappingObject. By using the PAGE_READWRITE flag, the processes will have read/write permission to the memory through any file views that are created.

HANDLE hMapFile;
 
hMapFile = CreateFileMapping(hFile,    // Current file handle.
    NULL,                              // Default security.
    PAGE_READWRITE,                    // Read/write permission.
    0,                                 // Max. object size.
    0,                                 // Size of hFile.
    "MyFileMappingObject");            // Name of mapping object.
 
if (hMapFile == NULL) {
    ErrorHandler("Could not create file-mapping object.");

}
 

The process then uses the file-mapping object handle returned by CreateFileMapping in the call to MapViewOfFile to create a view of the file in the process's address space. The MapViewOfFile function returns a pointer to the file view.

LPVOID lpMapAddress;
lpMapAddress = MapViewOfFile(hMapFile, // Handle to mapping object.  
    FILE_MAP_ALL_ACCESS,               // Read/write permission
    0,                                 // Max. object size.
    0,                                 // Size of hFile.
    0);                                // Map entire file.
 
if (lpMapAddress == NULL) {
    ErrorHandler("Could not map view of file.");
}
 

The second process calls the OpenFileMapping function with the name MyFileMappingObject to use the same file-mapping object as the first process. Like the first process, the second process uses the MapViewOfFile function to obtain a pointer to the file view.

HANDLE hMapFile;
LPVOID lpMapAddress;
 
hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, // Read/write permission.
    FALSE,                             // Do not inherit the name
    "MyFileMappingObject");            // of the mapping object.
 
if (hMapFile == NULL) {
    ErrorHandler("Could not open file-mapping object.");
}
 
lpMapAddress = MapViewOfFile(hMapFile, // Handle to mapping object.
    FILE_MAP_ALL_ACCESS,               // Read/write permission.

    0,                                 // Max. object size.
    0,                                 // Size of hFile.
    0);                                // Map entire file.
 
if (lpMapAddress == NULL) {
    ErrorHandler("Could not map view of file.");
}
 
After creating file mappings tasks do its work eventually change data pointed by lpMapAddress and rise Event to signaled state.

You frontend process periodically perform Event state check in loop. If Event rised than it need to read changed data from File Mapping and update visuals. You can use WaitForSingleObject, WaitForMultipleObject functions to detect Event state.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:abuly80
ID: 10961680
MikProg:

First of all, thank you for your detailed comment. However, I am still not clear on a number of things. I think I understand how the events work. They can only pass signals from one process to another, but not data. For data passing, you suggest that I use some sort of file reading/writing mechanism. That’s where I am still a bit confused.
 
1) How is mapped-file reading and writing performed? Is it done via regular ReadFile()/WriteFile() functions? In that case, the front-end process has the file handle (“hFile”), but the back-end process does not. How would back-end process read and write data? In other words, how do processes change data pointed to by “lpMapAddress” and read data from “lpMapAddress”?

2) What is the difference between using these File Mapping Functions and regular (maybe hidden) binary file reading/writing? The name of the shared binary file could be passed from the front-end to back-end process via the parameter list of CreateProcess(), could it not? The same event mechanism could then be used to signal reading and writing.

3) You referred to the File Mapping Functions mechanism as a “Shared memory” mechanism. Is there a way for the front-end process to pass pointer(s)/window handle(s) to the back-end process using some sort of shared memory block structure without using disk?

Thanks again.
0
 

Author Comment

by:abuly80
ID: 10973784
I think I have figured out all other things I was not clear on with respect to the File Mapping Functions. Thanks!
0
 
LVL 3

Expert Comment

by:MikProg
ID: 10992922
Sorry about silence. It was a looong weekend. ;)
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

This article describes how to programmatically preset the "Pages per Sheet" option that's available with most printer drivers.   This setting lets you do "n-Up" printing, where two, four, or more pages are printed on each sheet of paper. If your …
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now