Solved

How to use _popen in an MFC App

Posted on 1998-07-14
9
1,259 Views
Last Modified: 2013-11-20
Hi,

Is it possible to use _popen() in an MFC app, it always seems to fail for me!

The _popen() implementation seems to fail when it tries to do stuff (remap?) with stdin, stdout.

Is there any way to give an MFC app valid stdin and stdout without having a nasty console??

I tried _freopen()but _popen() still did not work.

Thanks

Kevin
0
Comment
Question by:KevinG
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
9 Comments
 
LVL 8

Expert Comment

by:trestan
ID: 1319130
Can you use fstream instead? I have used it without any problem.
0
 
LVL 2

Expert Comment

by:graber
ID: 1319131
_popen is compatable with 95 and NT.  Your outbut will have to
be redirected to some sort out device such as a dialog.

/* POPEN.C: This program uses _popen and _pclose to receive a
 * stream of text from a system process.
 */

#include <stdio.h>
#include <stdlib.h>

void main( void )
{

   char   psBuffer[128];
   FILE   *chkdsk;

        /* Run DIR so that it writes its output to a pipe. Open this
    * pipe with read text attribute so that we can read it
         * like a text file.
    */
   if( (chkdsk = _popen( "dir *.c /on /p", "rt" )) == NULL )
      exit( 1 );

   /* Read pipe until end of file. End of file indicates that
    * CHKDSK closed its standard out (probably meaning it
         * terminated).
    */
   while( !feof( chkdsk ) )
   {
      if( fgets( psBuffer, 128, chkdsk ) != NULL )
         printf( psBuffer );
   }

   /* Close pipe and print return value of CHKDSK. */
   printf( "\nProcess returned %d\n", _pclose( chkdsk ) );
}
Output
Volume in drive C is CDRIVE
 Volume Serial Number is 0E17-1702

 Directory of C:\dolphin\crt\code\pcode

05/02/94  01:05a                   805 perror.c
05/02/94  01:05a                 2,149 pipe.c
05/02/94  01:05a                   882 popen.c
05/02/94  01:05a                   206 pow.c
05/02/94  01:05a                 1,514 printf.c
05/02/94  01:05a                   454 putc.c
05/02/94  01:05a                   162 puts.c
05/02/94  01:05a                   654 putw.c
               8 File(s)          6,826 bytes
                             86,597,632 bytes free

Process returned 0
0
 
LVL 8

Expert Comment

by:trestan
ID: 1319132
Sorry for my carelessness.
The _popen() does not work under Windows application. I debug into the POPEN.C, found that the non-inheritable copy of stdhdl can not be saved, so that NULL is always returned. I do not know why. But I think there are some alternative methods to achieve your purpose. Actually the procedure will be like the POPEN do, create a console program using CreateProcess(), redirect the output from stdio to other streams. There are some functions can perform this task.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Accepted Solution

by:
racter earned 300 total points
ID: 1319133
Using popen is the wrong appoach for Windows programming...

You want to use CreateProcess, which allows you to supply
the pipes it should take in and output data to, and also
lets you set the display style for the console window that will be created for the process, in  your case you probably want it to be SW_HIDE, I'll show you below how to set this all up, basicly once you do the code below, you simply need to read the
output from the output pipe.

--------------

STARTUPINFO         sinf = {0};
PROCESS_INFORMATION pinf = {0};
SECURITY_ATTRIBUTES sa = {0};
HANDLE hPipeORead  = NULL;
HANDLE hPipeOWrite = NULL;
HANDLE hPipeIRead  = NULL;
HANDLE hPipeIWrite = NULL;

sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;

CreatePipe(&hPipeORead, &hPipeOWrite, &sa, 0);
CreatePipe(&hPipeIRead, &hPipeIWrite, &sa, 0);

sinf.cb = sizeof(sinf);
sinf.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
sinf.wShowWindow = SW_HIDE;
sinf.hStdInput = hPipeIRead;
sinf.hStdOutput = hPipeOWrite;
sinf.hStdError = hPipeOWrite;

CreateProcess(NULL, "myprogram.exe", NULL, NULL, TRUE,     NORMAL_PRIORITY_CLASS, NULL, NULL, &sinf, &pinf);


0
 
LVL 8

Expert Comment

by:trestan
ID: 1319134
I have tried the code listed in the proposed answer. There are many problems to use them and finally, nothing can be read from the pipe. I am still trying to find a way to do that.
racter: I don't think you have tried to compile that codes by yourself.  
0
 

Expert Comment

by:racter
ID: 1319135
Its ment to be a code fragment, and  yes, it works, I used it to launch the MSVC compiler on the command line and then read the error messages in so I can make a pretty list of the errors.

if you want my to write every line of the code for you, thats a different problem.

Simple code to read a pipe....

DWORD total, bRead;
char byte;

PeekNamedPipe(hPipeORead, NULL, 0, NULL, &total, NULL);

if (total == 0)
   return false;

while (total--) {
    if (ReadFile(hPipeORead, &byte, 1, &bRead, NULL) == NULL)
        break;

// Do soemthing with the byte from the pipe (perhaps build a line buffer)
}
0
 

Expert Comment

by:racter
ID: 1319136
Its ment to be a code fragment, and  yes, it works, I used it to launch the MSVC compiler on the command line and then read the error messages in so I can make a pretty list of the errors.

if you want my to write every line of the code for you, thats a different problem.

Simple code to read a pipe....

DWORD total, bRead;
char byte;

PeekNamedPipe(hPipeORead, NULL, 0, NULL, &total, NULL);

if (total == 0)
   return false;

while (total--) {
    if (ReadFile(hPipeORead, &byte, 1, &bRead, NULL) == NULL)
        break;

// Do soemthing with the byte from the pipe (perhaps build a line buffer)
}
0
 
LVL 23

Expert Comment

by:chensu
ID: 1319137
These KB articles may be helpful.

How to Spawn a Console App and Redirect Standard Handles
http://support.microsoft.com/support/kb/articles/q126/6/28.asp

Redirection Issues on Windows 95 MS-DOS Apps and Batch Files
http://support.microsoft.com/support/kb/articles/q150/9/56.asp
0
 

Author Comment

by:KevinG
ID: 1319138
Hi,

I wanted to use popen() as I am under a dark cloud of UNIX Legacy source (found some K&R C in it Yesterday!) and even though I knew it wasn't the correct windows way to go I tried to be lazy and save some time, Well that back-fired!

I now intercept calls to popen() and use CreateProcess() etc., it took me a bit of time to figure out SW_HIDE though!

Kevin.
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seve…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.

749 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