Solved

How to use _popen in an MFC App

Posted on 1998-07-14
9
1,270 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
Independent Software Vendors: 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

Enroll in June's Course of the Month

June's Course of the Month is now available! Every 10 seconds, a consumer gets hit with ransomware. Refresh your knowledge of ransomware best practices by enrolling in this month's complimentary course for Premium Members, Team Accounts, and Qualified Experts.

Question has a verified solution.

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

Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
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.
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…

734 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