Thread: Pipe the console from a DLL

  1. #1
    Registered User
    Join Date
    Oct 2001
    Posts
    104

    Pipe the console from a DLL

    Hi!

    I've got this code that pipes the console output into a string. The problem is that when I use it in a DLL file, and use this DLL file from VB, the console's output is not in the string, as it should be. It executes but does not store the output into the string.
    Any ideas?
    Here is my code:


    Code:
    std::string ConsoleInfo(LPSTR Command) 
    { 
     std::string result; 
      
     HANDLE hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup, hSaveStdout; 
     SECURITY_ATTRIBUTES saAttr; 
     BOOL fSuccess; 
    
     // Set the bInheritHandle flag so pipe handles are inherited. 
     saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
     saAttr.bInheritHandle = TRUE; 
     saAttr.lpSecurityDescriptor = NULL; 
    
     // Save the handle to the current STDOUT. 
     hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
      
     // Create a pipe for the child process's STDOUT. 
     if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) 
      return result; 
    
     // Set a write handle to the pipe to be STDOUT. 
     if (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr)) 
      return result; 
      
     // Create noninheritable read handle and close the inheritable read handle. 
        fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, 
            GetCurrentProcess(), &hChildStdoutRdDup , 0, 
            FALSE, 
            DUPLICATE_SAME_ACCESS); 
        if( !fSuccess ) 
      return result; 
        CloseHandle(hChildStdoutRd); 
    
     // Now create the child process. 
     PROCESS_INFORMATION piProcInfo; 
     STARTUPINFO siStartInfo; 
    
     // Set up members of the PROCESS_INFORMATION structure. 
      ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); 
      
     // Set up members of the STARTUPINFO structure. 
     ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); 
     siStartInfo.cb = sizeof(STARTUPINFO); 
    
     // Create the child process. 
      fSuccess = CreateProcess(NULL, 
      Command,       // command line 
      NULL,          // process security attributes 
      NULL,          // primary thread security attributes 
      TRUE,          // handles are inherited 
      0,             // creation flags 
      NULL,          // use parent's environment 
      NULL,          // use parent's current directory 
      &siStartInfo,  // STARTUPINFO pointer 
      &piProcInfo);  // receives PROCESS_INFORMATION 
      
     if (! fSuccess) 
      return result; 
      
     // After process creation, restore the saved STDIN and STDOUT. 
      if (! SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)) 
      return result; 
      
     // Read from pipe that is the standard output for child process. 
     DWORD dwRead; 
     CHAR chBuf[4096]; 
     HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
    
     // Close the write end of the pipe before reading from the 
     // read end of the pipe. 
      if (!CloseHandle(hChildStdoutWr)) 
      return result; 
      
     // Read output from the child process, and write to parent's STDOUT. 
     for (;;) 
     { 
      if( !ReadFile(hChildStdoutRdDup, chBuf, 4096, &dwRead, NULL) || dwRead == 0) 
       break; 
      result += chBuf; 
     } 
      
     return result; 
    }
    Thanks!
    Ilia Yordanov,
    http://www.cpp-home.com ; C++ Resources

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    It executes but...
    How do you know that it executes? Which "return" statement does it execute?

    gg

  3. #3
    Registered User
    Join Date
    Oct 2001
    Posts
    104
    Hi!

    In VB (where I use the DLL) when I make a call to the function, it executes what I called, but it just doesn't store it's console output into the string.
    And I know that it executes because it opens the console itself and I see it it's working... but it just doens't get the output.

    Any ideas?
    Ilia Yordanov,
    http://www.cpp-home.com ; C++ Resources

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    That only proves that your are getting as far as the CreateProcess() call. How do you know what happens after that?

    Use a debugger or put some MessageBox() calls with all the return statements.

    gg

  5. #5
    Registered User
    Join Date
    Oct 2001
    Posts
    104
    Hi there!

    But the CreateProcess does execute in my mind... I think so, because if it didn't the console wouldn't open! And it opens!
    Ilia Yordanov,
    http://www.cpp-home.com ; C++ Resources

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    That's what I said...

  7. #7
    Registered User
    Join Date
    Oct 2001
    Posts
    104
    Will MessageBox work in DLL imported in VB?

    Also, what exactly is your idea? To see WHERE it returns?
    Ilia Yordanov,
    http://www.cpp-home.com ; C++ Resources

  8. #8
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    MessageBox() should work.
    To see WHERE it returns?
    Yes. Got to know where it stopped working if you want to know why it stopped working.

    gg

  9. #9
    Registered User
    Join Date
    Oct 2001
    Posts
    104
    Thanks a lot!
    I will give it a try right away and will publish what happened.

    Thanks!
    Ilia Yordanov,
    http://www.cpp-home.com ; C++ Resources

  10. #10
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    You also need this:
    Code:
        chBuf[dwRead] = '\0';
        result += chBuf;
    gg

  11. #11
    Registered User
    Join Date
    Oct 2001
    Posts
    104
    Hi!

    Thanks, I added this.

    One dumb question though (as I haven't used Win32 much)- what parameters should I pass to the MessageBox function? I see the list of the parameters, but I don't know what values to pass...especially for the handles?

    Any advice on this one?
    Ilia Yordanov,
    http://www.cpp-home.com ; C++ Resources

  12. #12
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Something like this...
    Code:
    #include <sstream> //for VC++ 6.0
    #include <strstream>
      ....
        if (!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)) 
        {
            std::ostringstream msg;
    
            msg << "SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout) Failed" << endl
                << "GetLastError() = " << GetLastError();
    
            MessageBox(NULL, 
                       msg.str().c_str(),
                       "Debug", 
                       MB_OK | MB_ICONSTOP);
    
            return result; 
        }
    For all the return spots after CreateProcess() call.

    gg

  13. #13
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Returning a std::string to Visual Basic is unlikely to work. You can search the web for ways to pass a string back to VB from a dll.
    --> Search: visual basic return string dll

    or you can use this method:

    Code:
    BSTR WINAPI ConsoleInfo(LPSTR Command) 
    
    ...
    
    return SysAllocStringByteLen(result.c_str(), strlen(result.c_str()));
    This assumes that you are declaring the function as returning a string in VB.

    This will also leak the returned string. If this bothers you(ie. you are running the function multiple times in your program) then post back and we can try and figure out a better solution.

    As to the MessageBox method of debugging remember to start with one just before the function is meant to return and work backwards up the function if it doesn't show.

    Your function is also leaking handles. You at least need:
    Code:
    CloseHandle(piProcInfo.hThread);
    CloseHandle(piProcInfo.hProcess);

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. non-MFC DLL with MFC app question.
    By Kempelen in forum Windows Programming
    Replies: 10
    Last Post: 08-20-2008, 07:11 AM
  2. Help with simple console to dll code
    By crazybucky in forum C++ Programming
    Replies: 29
    Last Post: 02-06-2008, 02:08 AM
  3. Replies: 7
    Last Post: 01-14-2008, 10:25 AM
  4. dll communicating between each other
    By cloudy in forum C++ Programming
    Replies: 5
    Last Post: 06-17-2005, 02:20 AM
  5. DLL and std::string woes!
    By Magos in forum C++ Programming
    Replies: 7
    Last Post: 09-08-2004, 12:34 PM