Hey guys, quick question:

I have been experementing with the _popen() function to get the stdout from programs. I'm trying to wrap it in a function for quick reuse, but the prog crashes every time!

Here is the function (as well as the quick test main() function):

// crt_popen.c
/* This program uses _popen and _pclose to receive a 
 * stream of text from a system process.
 */

#include "StdAfx.h"
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string>
#include <iostream>

char getStdOut(char*);

int main( void )
{
	std::cout << getStdOut("ls");
   _getch();
}

char getStdOut(char *cmd)
{
   char psBuffer[128];
   char ps[1024];
   FILE *pPipe;

   if( (pPipe = _popen(cmd, "rt" )) == NULL )
      exit( 1 );

   /* Read pipe until end of file, or an error occurs. */

   while(fgets(psBuffer, 128, pPipe))
   {
	  strcat(ps,psBuffer);
	  memset(psBuffer, 0, sizeof(psBuffer) );
   }
   /* Close pipe and print return value of pPipe. */
   if (!feof( pPipe))
   {
     printf( "Error: Failed to read the pipe to the end.\n");
   }
   return *ps;
}

In VS2010, it keeps running into an Access Violation.
Unhandled exception at 0x77df158e in PipesTest.exe: 0xC0000005: Access violation.

Thanks guys!

Recommended Answers

All 19 Replies

You are using VC++ 2010 on MS-Windows but attempting to run a *nix ls command???? On MS-Windows the equivalent of ls is dir.

>>strcat(ps,psBuffer);
You will have to initialize ps to 0 before that line. Do it when it is declared, char ps[1024] = {0}; I think it would be better to use a linked list because the results of dir can be very very huge. In c++ just use vector<string> filelist;

>>You are using VC++ 2010 on MS-Windows but attempting to run a *nix ls command???? On MS-Windows the equivalent of ls is dir.

Yes, ls works too. And i like my unix commands ^.^ but I can change it, it dosent matter too much to me.

>>You will have to initialize ps to 0 before that line. Do it when it is declared, char ps[1024] = {0};
Thanks, That makes sure it dosent crash :D but the proggie only prints the first char of the stdout. I modded the loop for atting the buffer to the final string:

while(fgets(psBuffer, 128, pPipe))
   {
	  strcat(ps,psBuffer);
          printf("%s\n------------\n",ps); 
	  memset(psBuffer, 0, sizeof(psBuffer) );
   }

and that prints the correct output (or at least the last itteration of it)
:

PipesTest.exe

------------
PipesTest.exe
PipesTest.ilk

------------
PipesTest.exe
PipesTest.ilk
PipesTest.pdb

------------
P

Hmm... is it because I am only returning a char? How would I allow the function to return an array of chars?

>>but I can change it, it dosent matter too much to me.


Well it will matter to the operating system :)

>>How would I allow the function to return an array of chars? char* getStdOut(char *cmd) Now you will want to make that string getStdout(char* cmd) because a function can not return a character array that is declared on the stack as ps is declared in that function. You could change ps to a pointer and use malloc() to allocate memory for it, but using std::string in a c++ program would be a better and easier solution.

Yea.... I sorta figured I would have to use strings! Code updated and working :p ....

As for the OS caring, ls works exactly the same as dir, but without adding all of the timestamps and sized and such things like drive size, volume serials, labels. Works better for cross platform-ness, as well as just getting the list of files in the dir your in :)

Thanks for you help, Ancient Dragon!

Heres the code, if anyone can use it to learn from or for an example or whatever:

// PipesTest.c
/* 
open a pipe, run the command in the param,  then read the stdout and return it as a cstring
*/

#include "StdAfx.h"
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string>
#include <iostream>

//Proto functions
std::string getStdOut(char*);

//Main function
int main( void )
{
	std::cout << getStdOut("ls");
   _getch();
}
//for getting the stdout of programs
std::string getStdOut(char *cmd)
{
   char psBuffer[128]={0};
   char ps[1024]={0};
   FILE *pPipe;

   if((pPipe = _popen(cmd, "rt" )) == NULL )
      exit(1);

   while(fgets(psBuffer, 128, pPipe))
   {
	  strcat(ps,psBuffer);
	  memset(psBuffer, 0, sizeof(psBuffer) );
   }
   if (!feof( pPipe))
   {
     printf( "Error: Failed to read the pipe to the end.\n");
   }
   return ps;
}

ls doesn't work on Windows 7

Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.

C:\Users\Ancient Dragon>ls
'ls' is not recognized as an internal or external command,
operable program or batch file.

C:\Users\Ancient Dragon>

If you want the filenames then use /b option

C:\Users\Ancient Dragon>dir /b
Contacts
Desktop
Documents
Downloads
Favorites
Links
Music
Pictures
Saved Games
Searches
Videos
workspace

C:\Users\Ancient Dragon>

>>orly? 0.0

Huh??? The ls command you have in your link is probably from one of the gnu libraries, not standard MS-Windows command. You will not be able to run that program on other computers with MS-Windows unless you also install that ls.exe program.

Haha, yea, your probably right. At one point, I had cygwin installed, so that might have installed ls?

Well, I'll stick to the M$ stock commands from now on :p

If you are concerned about security in your programs then don't use pipes to execute M$ stock command. Most, if not all, those commands have win32 api equivalent functions. For dir you can call FindFirstFile() and FindNextFile() to do the same thing.

Huh, I have dabbled in the win32 api, but not much. Usually because the GUI progging in C++ is so difficult (or for me right now, that is). I'll be sure to look over @ MSDN, and try some more GUI and win32 coding.

Those functions can be used in either console or GUI programs. There are a lot of win32 api functions that can be called from console programs.

FindFirstFile() and FindNextFile() are very similar in concept to opendir() and readdir() for *nix. All you have to do is include <windows.h> then use google to get the full descriptions of those functions from MSDN. I have even posted code examples using those functions.

>> I have even posted code examples using those functions.
So that's how you use a vector! lol I've seen it a lot of places... So its like a stack of variables of the same type? Like, vector<string> holds a stack of strings, vector<int> holds a stack of ints?

Cool code, I like the simplicity of it, and how it all works together with itself (the recursion and calling itself)

Its not copy-paste-able in VC++2010, but I get the idea. Cool prog!

>>Its not copy-paste-able in VC++2010,

Funny -- I didn't have any trouble doing that. Just copy/paste into an existing console project.

vectors are c++ implementation of arays, not stacks. There is another class called stack. You might want to read up on STL containers.

memset(psBuffer, 0, sizeof(psBuffer) );

This line is not necessary.After the string concatration the strcat function will
add the null character end of it.

And if your thread is sloved then please so mark this thread as sloved.

And unless there are linux operating systems like BusyBox the comands like
"ls","cat","cp" are not part of the operating system itself.There are things like
cigwin/mingw which are emulating the Unix POSIX system under the windows.So check
your PATH environment variable.Here I'm also using the windows 7 but did not noticed
it.Here using ultimate so every componments in the windows 7 should be here.Probablly
this should be something that comming from a cigwin/mingw like thing.

Heres the build log...

1>------ Build started: Project: DirTraverser, Configuration: Debug Win32 ------
1>Build started 10/19/2010 8:17:23 PM.
1>InitializeBuildStatus:
1>  Touching "Debug\DirTraverser.unsuccessfulbuild".
1>ClCompile:
1>  All outputs are up-to-date.
1>  DirTraverser.cpp
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(2): warning C4627: '#include <io.h>': skipped when looking for precompiled header use
1>          Add directive to 'StdAfx.h' or rebuild precompiled header
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(3): warning C4627: '#include <string>': skipped when looking for precompiled header use
1>          Add directive to 'StdAfx.h' or rebuild precompiled header
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(4): warning C4627: '#include <vector>': skipped when looking for precompiled header use
1>          Add directive to 'StdAfx.h' or rebuild precompiled header
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(5): warning C4627: '#include <list>': skipped when looking for precompiled header use
1>          Add directive to 'StdAfx.h' or rebuild precompiled header
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(6): warning C4627: '#include <iostream>': skipped when looking for precompiled header use
1>          Add directive to 'StdAfx.h' or rebuild precompiled header
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(79): fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "StdAfx.h"' to your source?
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:00.56
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

after adding the stdafx.h:

1>------ Build started: Project: DirTraverser, Configuration: Debug Win32 ------
1>Build started 10/19/2010 8:18:25 PM.
1>InitializeBuildStatus:
1>  Touching "Debug\DirTraverser.unsuccessfulbuild".
1>ClCompile:
1>  All outputs are up-to-date.
1>  DirTraverser.cpp
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(2): warning C4627: '#include <io.h>': skipped when looking for precompiled header use
1>          Add directive to 'StdAfx.h' or rebuild precompiled header
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(3): warning C4627: '#include <string>': skipped when looking for precompiled header use
1>          Add directive to 'StdAfx.h' or rebuild precompiled header
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(4): warning C4627: '#include <vector>': skipped when looking for precompiled header use
1>          Add directive to 'StdAfx.h' or rebuild precompiled header
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(5): warning C4627: '#include <list>': skipped when looking for precompiled header use
1>          Add directive to 'StdAfx.h' or rebuild precompiled header
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(6): warning C4627: '#include <iostream>': skipped when looking for precompiled header use
1>          Add directive to 'StdAfx.h' or rebuild precompiled header
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(14): error C2146: syntax error : missing ';' before identifier 'path'
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(14): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(14): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(15): error C2143: syntax error : missing ';' before '<'
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(15): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(15): error C2238: unexpected token(s) preceding ';'
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(19): error C2065: 'string' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(19): error C2146: syntax error : missing ')' before identifier 'path'
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(19): error C2182: 'TransverseDirectory' : illegal use of type 'void'
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(19): error C2059: syntax error : ')'
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(20): error C2143: syntax error : missing ';' before '{'
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(20): error C2447: '{' : missing function header (old-style formal list?)
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(62): error C2065: 'list' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(62): error C2275: 'FILELIST' : illegal use of this type as an expression
1>          c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(13) : see declaration of 'FILELIST'
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(62): error C2065: 'MyList' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(63): error C2065: 'string' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(63): error C2146: syntax error : missing ';' before identifier 'path'
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(63): error C2065: 'path' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(64): error C2065: 'cout' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(65): error C2065: 'cin' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(65): error C2065: 'path' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(65): error C3861: 'getline': identifier not found
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(66): error C2065: 'path' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(66): error C2065: 'MyList' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(67): error C2065: 'list' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(67): error C2275: 'FILELIST' : illegal use of this type as an expression
1>          c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(13) : see declaration of 'FILELIST'
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(67): error C2039: 'iterator' : is not a member of '`global namespace''
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(67): error C2065: 'iterator' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(67): error C2146: syntax error : missing ';' before identifier 'it'
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(67): error C2065: 'it' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(68): error C2065: 'it' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(68): error C2065: 'MyList' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(68): error C2228: left of '.begin' must have class/struct/union
1>          type is ''unknown-type''
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(68): error C2065: 'it' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(68): error C2065: 'MyList' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(68): error C2228: left of '.end' must have class/struct/union
1>          type is ''unknown-type''
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(68): error C2065: 'it' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(70): error C2065: 'vector' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(70): error C2065: 'string' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(70): error C2039: 'iterator' : is not a member of '`global namespace''
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(70): error C2065: 'iterator' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(70): error C2146: syntax error : missing ';' before identifier 'its'
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(70): error C2065: 'its' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(71): error C2065: 'its' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(71): error C2065: 'it' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(71): error C2228: left of '.theList' must have class/struct/union
1>          type is ''unknown-type''
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(71): error C2228: left of '.begin' must have class/struct/union
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(71): error C2065: 'its' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(71): error C2065: 'it' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(71): error C2228: left of '.theList' must have class/struct/union
1>          type is ''unknown-type''
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(71): error C2228: left of '.end' must have class/struct/union
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(71): error C2065: 'its' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(73): error C2065: 'cout' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(73): error C2065: 'it' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(73): error C2228: left of '.path' must have class/struct/union
1>          type is ''unknown-type''
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(73): error C2065: 'its' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(73): error C2065: 'endl' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(77): error C2065: 'cin' : undeclared identifier
1>c:\users\dylan\visstudioprojects\dirtraverser\dirtraverser\dirtraverser.cpp(77): error C2228: left of '.ignore' must have class/struct/union
1>          type is ''unknown-type''
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:00.32
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

>>Heres the build log...
For what?

Disable precompiled headers for that project. Or add #include "stdafx.h" at the top of each *.cpp file in the project.

And make sure its in a *.cpp file, not *.c. C programs can not use precompiled headers or STL containers such as vector

>>For what?
For your directory program. Dont worry about it, just thought i'd share, after you said it could be pasted in. IDK if its helpfull or not, haha.

yes follow the Acient dragons instruction first.
If it won't work, try right click that stdeafx.h thing in the project
explore and click compile.They try build.that trick works for me in VC++6.0.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.