Click here to Skip to main content
15,888,461 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
how can i redirect cmd box output into a textbox or grab it somehow in native C++, like what we see in Visual Studio itself while compiling with cl.exe?
i need not to wait until the command gets executed completely and then show the output.
i need to open the textbox and whenever something is to be copied into standard output by the command line program (or stderr which i want to be able to select), the output be redirected to the textbox automatically.
Posted

Not a complete solution, just pointers, but:
-Create named pipe(s) with CreateNamedPipe[^]
-run the console application with CreateProcess[^], specifying your named pipe(s) in the STARTUPINFO[^] structure for hStdOutput and hStdError
-Use ReadFile[^] to read anything that gets delivered to the named pipe in a thread or in a timer or somesuch and feed it to the text box

Read the MSDN links for more info on the methods. Feel free to ask if there's a question. Good luck.
 
Share this answer
 
Comments
Hawkfuture 5-Aug-12 23:00pm    
i remember "freopen" can redirect the stderr or stdout, not for sure.
Code-o-mat 6-Aug-12 3:35am    
Wouldn't that work only "inside the process" whose outputs you want to redirect? I presume the command line program isn't written by him and he does not have the sources so he can't insert reopen in it.
Hawkfuture 9-Aug-12 3:31am    
oh, sorry. i read the question not carefully enough.
Code-o-mat 9-Aug-12 4:09am    
No problem, it appebs.
Little example to demonstrate capturing of console input.
To update your edit: put the capture functionallity into a class object and use a timer in your application window for cyclic update to the edit control.

Best regards.

C++
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>
#include <malloc.h>

#pragma comment(lib,"user32.lib")
#pragma comment(lib,"gdi32.lib")

WNDPROC __wndsuper = 0;
LRESULT FAR PASCAL __wndproc(HWND h,unsigned int m,WPARAM w,LPARAM l)
{
  switch(m)
  {
    case WM_CLOSE  : DestroyWindow(h); break;
    case WM_DESTROY: PostQuitMessage(0); break;
  }
  return CallWindowProc(__wndsuper,h,m,w,l);
}

HGLOBAL  CatchConsole(const TCHAR* exe,const TCHAR* param=0);

int FAR PASCAL _tWinMain(HINSTANCE h,HINSTANCE p,LPTSTR c,int sw)
{
  HWND    hwnd;
  HGLOBAL  hmem;
  MSG      msg;

  hmem = c && *c ? CatchConsole(c): CatchConsole(__TEXT("cmd.exe"),__TEXT("/c dir /s C:\\*.*"));
  if(!hmem) return 1;

  hwnd = CreateWindowEx(0,__TEXT("EDIT"),__TEXT("CatchConsole"),
    WS_OVERLAPPEDWINDOW|WS_HSCROLL|WS_VSCROLL|ES_MULTILINE|ES_AUTOVSCROLL|ES_AUTOHSCROLL|ES_WANTRETURN,
    CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,0,0,h,0);

  if(IsWindow(hwnd))
  {
    #if _WIN64
    __wndsuper = (WNDPROC)SetWindowLongPtr(hwnd,GWLP_WNDPROC,(LONG_PTR)__wndproc);
    #else
    __wndsuper = (WNDPROC)SetWindowLong(hwnd,GWL_WNDPROC,(LONG)__wndproc);
    #endif
    GlobalFree((HGLOBAL)SendMessage(hwnd,EM_GETHANDLE,0,0));
    SendMessage(hwnd,EM_SETHANDLE,(WPARAM)hmem,0);
    SendMessage(hwnd,WM_SETFONT,(WPARAM)GetStockObject(ANSI_FIXED_FONT),0);
    SendMessage(hwnd,WM_SETICON,ICON_BIG,(LPARAM)LoadIcon(0,IDI_ASTERISK));
    ShowWindow(hwnd,sw);
    while(GetMessage(&msg,0,0,0))
    {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }
  return 0;
}

class CMemWrite // helper class
{
public:
  CMemWrite(){ _hmem=0;_seek=_size=0; }
  ~CMemWrite(){ if(_hmem) GlobalFree(_hmem); }
  
  HGLOBAL  Detach()
  {
    HGLOBAL h; return h=_hmem,_hmem=0,h;
  }

  void  Write(const char* lp,const unsigned int cb)
  {
    if(Grow((1+cb)*sizeof(TCHAR)))
    {
      TCHAR*        lpto = (TCHAR*)GlobalLock(_hmem);
      unsigned int  size;
      lpto += _seek / sizeof(TCHAR);
      size = (_size - _seek) / sizeof(TCHAR);
      if(sizeof(TCHAR)==sizeof(short))
        MultiByteToWideChar(CP_OEMCP,0,lp,cb,lpto,size);
      else
        memcpy(lpto,lp,cb);
      lpto[cb] = 0;
      _seek += cb*sizeof(TCHAR);
      GlobalUnlock(_hmem);
    }
  }

protected:
  int    Grow(const unsigned int add)
  {
    if(_size>=(_seek+add)) return 1;
    _size = 256 + ((_seek + add)<<1);
    _hmem = _hmem ? GlobalReAlloc(_hmem,_size,GMEM_MOVEABLE) : GlobalAlloc(GMEM_MOVEABLE,_size);
    return _hmem?1:0;
  }

private:
  HGLOBAL        _hmem;
  unsigned int  _size;
  unsigned int  _seek;
};

HGLOBAL  CatchConsole(const TCHAR* exe,const TCHAR* param)
{
  CMemWrite                write;
  STARTUPINFO              stari;
  PROCESS_INFORMATION      proci;
  int                      ok;
  TCHAR*                  command;
  size_t                  le,lp;
  SECURITY_ATTRIBUTES      sa;
  HANDLE                  hproc;
  HANDLE                  hRead,
                          hWrite;
  unsigned long            avail;
  unsigned long            read;
  char                    out[0x400];

  if(!exe) return 0;

  memset(&proci,0,sizeof(proci));
  memset(&stari,0,sizeof(stari));

  stari.cb              = sizeof(stari);
  stari.lpTitle         = __TEXT("---");
  stari.dwXCountChars   = 128;
  stari.dwYCountChars   = 300;
  stari.dwFlags         = STARTF_USESHOWWINDOW|STARTF_USECOUNTCHARS;
  stari.wShowWindow     = SW_HIDE;
  stari.hStdInput       = 0;
  stari.hStdOutput      = 0;
  stari.hStdError       = 0;

  hRead  = hWrite = 0;

  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  sa.lpSecurityDescriptor = 0;
  sa.bInheritHandle = 1;

  do
  {
    hproc = ::GetCurrentProcess();

    if(!::CreatePipe(&hRead, &stari.hStdOutput, &sa, 0)) break;
    if(!::DuplicateHandle(hproc,stari.hStdOutput,hproc,&stari.hStdError,0,1,DUPLICATE_SAME_ACCESS)) break;
    if(!::CreatePipe(&stari.hStdInput, &hWrite, &sa, 0)) break;

    stari.dwFlags |= STARTF_USESTDHANDLES;

    le = _tcslen(exe);
    lp = param?_tcslen(param):0;
    command = (TCHAR*)malloc(sizeof(TCHAR)*(le+lp+32)); if(!command) break;
    _tcscpy_s(command,le+lp+32,exe);
    if(0<lp)
    {
      _tcscpy_s(command+le,lp+32,__TEXT(" "));
      _tcscpy_s(command+le+1,lp+32-1,param);
    }

    ok = CreateProcess(0,command,0,0,1,IDLE_PRIORITY_CLASS,0,0,&stari,&proci);
    free(command);

    while(ok)
    {
      ok = WAIT_TIMEOUT==WaitForSingleObject(proci.hProcess,10);
      for(avail=0;PeekNamedPipe(hRead,0,0,0,&avail,0) && avail;avail=0)
      {
        if(ReadFile(hRead,out,min(sizeof(out),avail),&read,0) && read)
        {
          write.Write(out,read);
        }
      }
    }

  } while(0);

  if(stari.hStdOutput) CloseHandle(stari.hStdOutput);
  if(stari.hStdInput ) CloseHandle(stari.hStdInput);
  if(stari.hStdError ) CloseHandle(stari.hStdError);
  if(hRead ) CloseHandle(hRead);
  if(hWrite) CloseHandle(hWrite);

  return write.Detach();
}
 
Share this answer
 
Comments
Wyler Martin 31-Oct-12 5:45am    
I tried to use the code above. Unfortunately I do not have enough experience with Windows programming. The Problem is that CatchConsole comes back always with NULL:
hmem = c && *c ? CatchConsole( c ): CatchConsole(__TEXT("MyApp.exe"),c);
You may have me an example of how I have to apply this code in a application? I am running Win7 and msvc2005. Thanks a lot in advance. Regards
mbue 31-Oct-12 13:08pm    
If the CatchConsole function returns NULL there is possibly nothing written to output. Have you tried the example as it is (with: "cmd.exe dir *.*")? This should work. Example for MyApp.exe (this should be a console application): #pragma once #include <tchar.h>#include <iostream>int _tmain(int argc, _TCHAR* argv[]) { std::cout << "Hello world"; return 0; } The program should finally show an edit window displaying "Hello world". If you run in a debugger the call CreateProcess must return true. Writes your "MyApp.exe" any text to stdout the output is written to a memory file (CMemWrite). The memory handle is detached from the file and attached for displaying to an edit control. Best regards and good luck.
PS: sorry its really heavy to place preformatted code here :(
two ways
1 (bad way)
output the result from cmd to txt and then your programe read it
2 (good way)
pipe(see above)
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900