Link to home
Start Free TrialLog in
Avatar of Nemesis0815
Nemesis0815

asked on

Using a pipe to redirect output

hello,

i have the following problem:

im using this code to communicate to another program via command line interface:


char cmd[100] = "ccm set role";
char psBuffer [128];
FILE *tmp;

tmp = _popen(cmd, "rt");            // open pipe for reading in text mode and send command
 
   while( !feof( tmp ) )
   {
      if( fgets( psBuffer, 128, tmp ) != NULL )
        {
              printf( psBuffer );
        }
   }
   printf( "\nProcess returned %d\n", _pclose( tmp ) );


This returns only this:

Process returned 0



when i execute the command line stored in the cmd string with a call like this

system(cmd);

it returns the correct return value, a string like this:

developer

Now i know that the _popen command sends the correct command since the application i call by the cmd command string reacts correctly. Only thing that bothers me is that it seems i cannot get the command line return value back which i would normally get when i enter the cmd in the standard command line interpreter or by using the system() function.

Anybody knows how to get the result by using the popen directive ?
Avatar of sunnycoder
sunnycoder
Flag of India image

>>tmp = _popen(cmd, "rt");    

tmp = popen(cmd, "r");             should serve your purpose
  while( !feof( tmp ) )
  {
     if( fgets( psBuffer, 128, tmp ) != NULL )
      {
           printf( psBuffer ); ----- %s ????
      }
  }

can be changed to

   while( fgets( psBuffer, 128, tmp ) != NULL )
                 printf( "%s", psBuffer );


>>>>when i execute the command line stored in the cmd string with a call like this

system(cmd);

it returns the correct return value, a string like this:

developer

How can system return a string ? system () returns only an int and that will be the status returned

what platform are you working on ?
Avatar of Nemesis0815
Nemesis0815

ASKER

nope sorry,
exactly the same result as before - no output

it seems that this if( fgets( psBuffer, 128, tmp ) != NULL ) actually returns NULL when i debug.
sorry, with system returning something i was referring to the output in the command line interface window.
when i use popen i get no answer/result from the cmd i send in which should be printed by the printf("%s",psBuffer);
but it isnt.

im running WinNT btw.

i changed the code to this now:

   tmp = _popen(cmd, "r");            // open pipe for reading in text mode and send command
   while( !feof( tmp ) )
   {            
      if( fgets( psBuffer, 128, tmp ) == NULL )
              printf( "Error! \n");
        else
              printf("%s",psBuffer);  
   }

and it only returns me a single "Error!" in standard output.
cygwin or VC++
vc++
maybe the ccm application ( configuration management software continuus synergy )
outputs not to stdout but to stderr ?
are you creating windows application ? If yes then _popen is broken
http://lists.trolltech.com/qt-interest/1999-09/thread00289-0.html


>>maybe the ccm application ( configuration management software continuus synergy )
>>outputs not to stdout but to stderr ?

try redirecting the results to a file while executing from command line
redirecting with system( "ccm set role > tempfile.txt");
works fine

with popen and redirecting with > operator it says:

Command created: ccm query /name s_bgem_test.db /version uid08453 /type project
/f "%status" /u > tmpfile.txt

The handle could not be opened
during redirection of handle 1.
Error!

Process returned 1
add another error check

tmp = _popen(cmd, "r");          

if ( tmp == NULL )
     printf (" error opening pipe\n");
i guess this is the problem now ( popen bug with win app)

any other idea of how i could get the output of the application i call and redirect it to a variable so that i can use it in my program ? ( i want to avoid redirecting to a file )

some simple piping ? im not used to create and handle pipes in windows :)
added

if ( tmp == NULL )
    printf (" error opening pipe\n");

does not return an error
so this might be this invalid file handle problem ...
either you use fork with pipe

or

redirect to file and read from file

first is more elegant while second is slightly simpler
is there a fork in windows ?
The UNIX and Windows process models are very different, and the major difference lies in the creation of processes. UNIX uses fork to create a new copy of a running process and exec to replace a process's executable file with a new one. Windows does not have a fork function. Instead, Windows creates processes in one step by using CreateProcess. While there is no need in Win32 to execute the process after its creation (as it will already by executing the new code), the standard exec functions are still available in Win32.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnucmg/html/ucmgch09.asp

I am happy I have to work with Linux
isnt there an easier way then creating 2 pipes?

i only need to read the output that is generated by the ccm process no need to go both directions
ASKER CERTIFIED SOLUTION
Avatar of sunnycoder
sunnycoder
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
hm
any simplier example for this ? i dont quite get the msdn one.. :p
http://www.cs.cf.ac.uk/Dave/C/node23.html#SECTION002330000000000000000

its a unix example but things are pretty similar :-) once you get an idea of the concept, you will be able to code it on win
ok i did it now on my own... and thanx to alf for his help in the other thread:)



dunno why it works but it  does :)

extern int PipeThis( LPTSTR CmdLine, char * result )
{
      
      HANDLE rfd, wfd, myinput,myoutput,myerror;
      SECURITY_ATTRIBUTES attr;
      STARTUPINFO startinfo;
      PROCESS_INFORMATION myproc;
      
      char PipeBuffer[READBUFFER] ="";
      int readbytes;

      // ***************************
      // * Preparations            *
      // ***************************

      ZeroMemory( &myproc, sizeof(PROCESS_INFORMATION) );
      ZeroMemory( &startinfo, sizeof(STARTUPINFO) );

      attr.nLength = sizeof(SECURITY_ATTRIBUTES);
      attr.bInheritHandle = TRUE; // we want to be able to inherit this handle.
      attr.lpSecurityDescriptor = NULL;

      myinput = GetStdHandle(STD_INPUT_HANDLE);
      myoutput = GetStdHandle(STD_OUTPUT_HANDLE);      // save all IO handles to redirect them later on
      myerror = GetStdHandle(STD_ERROR_HANDLE);

      startinfo.cb = sizeof(STARTUPINFO);
      startinfo.dwFlags = STARTF_USESTDHANDLES;
      

      // ***************************
      // * STEP 1: Create the pipe *
      // ***************************

      if (CreatePipe(& rfd, & wfd, & attr, 0) == 0) {
            fprintf(stderr,"\nError, CreatePipe failed ! Code: %ul - exiting... \n",GetLastError());
            system("pause");
            exit(1);
      }

      startinfo.hStdError = myerror;
      startinfo.hStdInput      = myinput;
      startinfo.hStdOutput = wfd;      // set the  processe´s standard output to the write end of the pipe


      
      // ***************************
      // * STEP 2: Create a process*
      // ***************************
      
      if( CreateProcess( NULL, CmdLine, &attr, &attr, TRUE, NORMAL_PRIORITY_CLASS , NULL, NULL, &startinfo, &myproc ) == 0) {
            fprintf(stderr,"\nError, CreateProcess failed ! Code: %ul - exiting... \n",GetLastError());
            system("pause");
            exit(1);
      }


      // ***************************
      // * STEP 3: Close Handle    *
      // ***************************

      if ( CloseHandle(wfd) == 0 ){
            fprintf(stderr,"\nError, CloseHandle failed ! Code: %ul - exiting... \n",GetLastError());
            system("pause");
            exit(1);
      }


      // ***************************
      // * STEP 4: Read Pipe       *
      // ***************************

      
      if( ReadFile( rfd, PipeBuffer,READBUFFER, &readbytes, NULL) == 0){
            fprintf(stderr,"\nError, ReadFile failed ! Code: %ul - exiting... \n",GetLastError());
            system("pause");
            exit(1);
      }

      //printf("\nSuccess: \n\n%s\n",PipeBuffer);

      strcpy( result,PipeBuffer);                  // write resulting string

      // ***************************
      // * STEP 5: Closing.....    *
      // ***************************

      if ( CloseHandle(rfd) == 0 ){
            fprintf(stderr,"\nError, CloseHandle failed ! Code: %ul - exiting... \n",GetLastError());
            system("pause");
            exit(1);
      }

      if ( CloseHandle(myproc.hProcess) == 0){
            fprintf(stderr,"\nError, CloseHandle failed ! Code: %ul - exiting... \n",GetLastError());
            system("pause");
            exit(1);
      }
      
      if ( CloseHandle(myproc.hThread) == 0 ){
            fprintf(stderr,"\nError, CloseHandle failed ! Code: %ul - exiting... \n",GetLastError());
            system("pause");
            exit(1);
      }


      return 0;      // success
}

gonna give you sunnycoder the points caues you brought me on the light lane with this bug in the popen and pipes thing anyway :)