Link to home
Start Free TrialLog in
Avatar of zeek_ja
zeek_ja

asked on

executing a console program from within a DLL and reading the output

I'm trying to get a DLL i wrote to run a console program (i.e. "PKZIP c:\temp\afile.txt" ) and read the output to a CString var... the DLL runs on a web server with an application server as the DLL caller

Here's how i do it on my sun box (solaris);
----- start code ------

FILE *ptr;
char buf[BUFSIZ];
char stdErr[BUFSIZ];
char cmdStr[256];

strcpy( cmdStr, "/bin/gzip /tmp/afile.txt" ); // just an example

// open a pipe and execute command string / read stderr for command outputs
if ((ptr = popen(cmdStr, "r")) != NULL)
{
      strcpy( stdErr, "" );

      while ( fgets( buf, BUFSIZ, ptr ) != NULL )
      {
            strcat( stdErr, "<br>" );
            strcat( stdErr, buf );
      }
}
else
{
      char Err[1024];
      sprintf( Err, "Can't create pipe (popen failed)" );
      exit(1);
}
pclose( ptr );

----- end code ------

I deperately need an equivalent to work in a Windows environment MFC DLL... oh and i use CSting in Windows as opposed to
char whatever[123]; if that is relavent at all

i know i may not be very clear here but this is as close to explaining it as i can get atm. Any help at this point would be greatly appreciated.

zeek
Avatar of Kyle Abrahams, PMP
Kyle Abrahams, PMP
Flag of United States of America image

what do you need help with, creating the pipe or executing the command?
SOLUTION
Avatar of mnashadka
mnashadka

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
ASKER CERTIFIED SOLUTION
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
Avatar of zeek_ja
zeek_ja

ASKER

i know that it should work in windows.... but i keep getting the error... here is the code in windows:

---- start win code ----
FILE *ptr;
char buf[BUFSIZ];
char pipeOut[256];

if( ( ptr = _popen( ( cmdString ), "r" ) ) != NULL )
{
      while (  fgets( buf, BUFSIZ, ptr ) != NULL )
      {
            strcat( pipeOut, "<br>" );
            strcat( pipeOut, buf );
      }
}
else
{
      strError = "Can't create pipe (_popen failed)";

      if ( pRequest->AttributeExists( "THROWEXCEPTION" ) )
      {
            pRequest->ThrowException( TAG_ERROR_HEADER, strError ) ;
            exit(1);
      }
}

_pclose( ptr );

---- end win code ----

it seems like i can;t create a pipe... so i tried system( cmdString ); and nothing.. there is no result

I'm stumped here... perhaps a pure win32 approach would be better...

can someone give me the above pasted code in win32 format with CreateProcess or WinExec.... not sure if this is the way to go because the code looks fine to me...

zeek
Avatar of zeek_ja

ASKER

i've tried a different approach... but it only works when the command line does not contain a pipe symbol and i don't get all the output... can anyone add to or give me a better solution... here's what i got so far:

--- start new code ---
CString ExecAndGetOutput( LPCSTR szCommand )
{
    CString sRet= "";
    SECURITY_ATTRIBUTES rSA;
    rSA.nLength=              sizeof(SECURITY_ATTRIBUTES);
    rSA.bInheritHandle=       TRUE;
    rSA.lpSecurityDescriptor= 0;

    HANDLE hReadPipe, hWritePipe;
    CreatePipe( &hReadPipe, &hWritePipe, &rSA, 250000 );
   
   PROCESS_INFORMATION rPI;
    STARTUPINFO rSI;
   memset( &rSI, 0, sizeof(STARTUPINFO));
   rSI.cb=          sizeof(STARTUPINFO);
    rSI.dwFlags=     STARTF_USESHOWWINDOW |STARTF_USESTDHANDLES;
    rSI.wShowWindow= SW_HIDE; //SW_MINIMIZE;
    rSI.hStdOutput=  hWritePipe;
    rSI.hStdError=   hWritePipe;

    CString sCmd; sCmd.Format( "%s", (LPCSTR)szCommand );

    BOOL fRet=CreateProcess(NULL,(LPSTR)(LPCSTR)sCmd, NULL,NULL,TRUE,0,0,0, &rSI, &rPI );
    if ( !fRet ) {
         return( "" );
    }
    //------------------------- wait for the program to end
    WaitForSingleObject( rPI.hProcess, INFINITE);

    //------------------------- read the pipe
    char dest[1000];
    while ( ReadFromPipeNoWait( hReadPipe, dest, sizeof(dest) ) > 0 ) {
         sRet += dest;
    }

    CloseHandle( hReadPipe  );
    CloseHandle( hWritePipe );
    CloseHandle( rPI.hThread);
    CloseHandle( rPI.hProcess);
   
      return( sRet );
}
int ReadFromPipeNoWait( HANDLE hPipe, char* pDest, int nMax )
{
    DWORD nBytesRead= 0;
    DWORD nAvailBytes;
    char cTmp;
    memset( pDest, 0, nMax );

    PeekNamedPipe( hPipe, &cTmp, 1, NULL, &nAvailBytes, NULL );
    if ( nAvailBytes == 0 ) {
         return( nBytesRead );
    }
    BOOL fNoErr= ReadFile( hPipe, pDest, nMax-1, &nBytesRead, NULL);

    if ( !fNoErr ) {  // error
         nBytesRead= 0;
         strError = "Error reading pipe";
    }
    return( nBytesRead );
}

---- end new code ----

so if i use something like

CString cmdLine = "c:\\temp\\pkzip.exe -t -v c:\\temp\afile.txt"; // this is just an example... don't take pkzip literally
ExecAndGetOutput( cmdLine ); it'll work

but if i try something like:

CString cmdLine = "type someFile.txt | c:\\temp\\pkzip.exe -t -v c:\\temp\afile.txt"; // this is just an example... don't take pkzip literally
ExecAndGetOutput( cmdLine ); // it doesn't work


any ideas ???


zeek
SOLUTION
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
Avatar of zeek_ja

ASKER

i also need to be able to read all outputs and error outputs... in the code above the cmd.exe /c did do the trick,,thx... but the question also touches on the outputs.. this is critical

any thoughts?

zeek
:o)
CString cmdLine = "cmd.exe /c  echo << type someFile.txt | c:\\temp\\pkzip.exe -t -v c:\\temp\afile.txt 1>&2" ;
Avatar of zeek_ja

ASKER

when i run cmd.exe /c  echo << type someFile.txt | c:\\temp\\pkzip.exe -t -v c:\\temp\afile.txt 1>&2 i get

<< was unexpected at this time

is this going to give me "all" outputs that would normally be sent to a command window? i.e stdout and stderr ?

zeek
Avatar of zeek_ja

ASKER

fixed it... cmd.exe /c  echo | type someFile.txt | c:\\temp\\pkzip.exe -t -v c:\\temp\afile.txt 1>&2 works perfectly

thanks for the point in the right direction jkr though i had this working great in unix and could have gotten the first method i posted.. i wanted the "bells and whistles"... more info is certainly better than not enough

cheers

zeek