本帖最后由 fly___fly 于 2010-06-22 09:07:24 编辑

解决方案 »

  1.   

    呃。。不能修改了。。再度PS:
       
      编译环境,VS2008
      运行环境,Win7
      

  2.   


    STARTUPINFO si = {sizeof(si)};
    PROCESS_INFORMATION pi = {0};

        TCHAR szApp[MAX_PATH] = _T("cmd");
        if(::CreateProcess(NULL, szApp, NULL,NULL,FALSE,NULL,NULL,NULL,&si,&pi)) 
        {
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
        }
      

  3.   

    我根据楼上的代码试了试,竟然是可行的。
    尔后,逐行试了下,发现问题发生在这里
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    不解。。不知道这里应该是如何?
    不应该是STARTF_USESHOWWINDOW 吗?
      

  4.   

    呃。。又发现是STARTF_USESTDHANDLES 这个属性的影响。
    哪位大大能解释一下。偶对进程是小白。
      

  5.   


    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE; HANDLE hInRead;
    HANDLE hOutWrite;
    HANDLE hInWrite;
    HANDLE hOutRead;
    if (!::CreatePipe(&hInRead, &hInWrite, &sa, 0))
    {
    return;
    } if (!::CreatePipe(&hOutRead, &hOutWrite, &sa, 0))
    {
    return;
    }//  ::CloseHandle(hInRead);
    //  ::CloseHandle(hOutWrite); PROCESS_INFORMATION pi;
    STARTUPINFO si; si.cb = sizeof(STARTUPINFO);
    ::GetStartupInfo(&si);
    si.hStdInput =  hOutRead;
    si.hStdError = hInWrite;
    si.hStdOutput = hInWrite;
    si.wShowWindow = SW_SHOW;
    si.dwFlags = STARTF_USESHOWWINDOW| STARTF_USESTDHANDLES; TCHAR sz[] = _T("cmd");
    if (!::CreateProcess(NULL, sz
    ,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi)) 
    {
    return;
    } if (!pi.hProcess)
    {
    return;
    }
    试试这段代码
      

  6.   

    回复楼上,不行,只有把STARTF_USESTDHANDLES去掉才行。
      

  7.   

    怎么可能,你是把我的代码复制过去的吗?我已经调试通过了,你的程序没有停下来,是因为你没有Waitif (!::CreateProcess(NULL, sz
    ,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi)) 
    {
    return;
    }
    else
    {
    WaitForSingleObject(pi.hProcess, INFINITE);
    }
      

  8.   


    void test()
    {
    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE; HANDLE hInRead;
    HANDLE hOutWrite;
    HANDLE hInWrite;
    HANDLE hOutRead;
    if (!::CreatePipe(&hInRead, &hInWrite, &sa, 0))
    {
    return;
    } if (!::CreatePipe(&hOutRead, &hOutWrite, &sa, 0))
    {
    return;
    }//  ::CloseHandle(hInRead);
    //  ::CloseHandle(hOutWrite); PROCESS_INFORMATION pi;
    STARTUPINFO si; si.cb = sizeof(STARTUPINFO);
    ::GetStartupInfo(&si);
    si.hStdInput =  hOutRead;
    si.hStdError = hInWrite;
    si.hStdOutput = hInWrite;
    si.wShowWindow = SW_SHOW;
    si.dwFlags = STARTF_USESHOWWINDOW| STARTF_USESTDHANDLES; TCHAR sz[] = _T("cmd");
    if (!::CreateProcess(NULL, sz
    ,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi)) 
    {
    return;
    }
    else
    {
    WaitForSingleObject(pi.hProcess, INFINITE);
    } if (!pi.hProcess)
    {
    return;
    }}
    这个是我的测试函数
      

  9.   

    呃。。我看错了。是可以。但是请指点一下原因。。
    输入不是应该是写的么?输出不是应该是读的么?
    为啥要反过来?si.hStdInput =  hOutRead;
        si.hStdError = hInWrite;
        si.hStdOutput = hInWrite;
      

  10.   

    hStdOutput这个Output是要告诉控制台,它的输出消息应该写到哪里,相当于一个重定向,当然是要写到你的写句柄里面
      

  11.   

    哦。。那如果我要给控制台发命令,是应该::WriteFile(hOutRead,...)
    这样么?读的话是
    ::ReadFile(hInWrite, ...)这样对么?
      

  12.   

    si.hStdInput = hOutRead;
      si.hStdError = hInWrite;
      si.hStdOutput = hInWrite;读写很简单,既然控制台从houtread读内容,你就往houtwrite里写
    控制台把内容写到了hInWrite,当然就要从hinread里读这才是管道,从一端进就从另一端出,从另一端出就要往一端放
      

  13.   

    哦。。我就是想通过传入命令可以得到cmd的执行结果,在网上查的有说应该这么做的。有问题么?
      

  14.   

    msdn里有个例子,可以参考下。#include <windows.h> 
    #include <stdio.h>
     
    VOID main(void) 

        HANDLE hStdout, hNewScreenBuffer; 
        SMALL_RECT srctReadRect; 
        SMALL_RECT srctWriteRect; 
        CHAR_INFO chiBuffer[160]; // [2][80]; 
        COORD coordBufSize; 
        COORD coordBufCoord; 
        BOOL fSuccess; 
     
        // Get a handle to the STDOUT screen buffer to copy from and 
        // create a new screen buffer to copy to. 
     
        hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
        hNewScreenBuffer = CreateConsoleScreenBuffer( 
           GENERIC_READ |           // read/write access 
           GENERIC_WRITE, 
           0,                       // not shared 
           NULL,                    // default security attributes 
           CONSOLE_TEXTMODE_BUFFER, // must be TEXTMODE 
           NULL);                   // reserved; must be NULL 
        if (hStdout == INVALID_HANDLE_VALUE || 
                hNewScreenBuffer == INVALID_HANDLE_VALUE) 
        {
            printf("CreateConsoleScreenBuffer (%d)\n", GetLastError()); 
            return;
        }
     
        // Make the new screen buffer the active screen buffer. 
     
        if (! SetConsoleActiveScreenBuffer(hNewScreenBuffer) ) 
        {
            printf("SetConsoleActiveScreenBuffer (%d)\n", GetLastError()); 
            return;
        }
     
        // Set the source rectangle. 
     
        srctReadRect.Top = 0;    // top left: row 0, col 0 
        srctReadRect.Left = 0; 
        srctReadRect.Bottom = 1; // bot. right: row 1, col 79 
        srctReadRect.Right = 79; 
     
        // The temporary buffer size is 2 rows x 80 columns. 
     
        coordBufSize.Y = 2; 
        coordBufSize.X = 80; 
     
        // The top left destination cell of the temporary buffer is 
        // row 0, col 0. 
     
        coordBufCoord.X = 0; 
        coordBufCoord.Y = 0; 
     
        // Copy the block from the screen buffer to the temp. buffer. 
     
        fSuccess = ReadConsoleOutput( 
           hStdout,        // screen buffer to read from 
           chiBuffer,      // buffer to copy into 
           coordBufSize,   // col-row size of chiBuffer 
           coordBufCoord,  // top left dest. cell in chiBuffer 
           &srctReadRect); // screen buffer source rectangle 
        if (! fSuccess) 
        {
            printf("ReadConsoleOutput (%d)\n", GetLastError()); 
            return;
        }
     
        // Set the destination rectangle. 
     
        srctWriteRect.Top = 10;    // top lt: row 10, col 0 
        srctWriteRect.Left = 0; 
        srctWriteRect.Bottom = 11; // bot. rt: row 11, col 79 
        srctWriteRect.Right = 79; 
     
        // Copy from the temporary buffer to the new screen buffer. 
     
        fSuccess = WriteConsoleOutput( 
            hNewScreenBuffer, // screen buffer to write to 
            chiBuffer,        // buffer to copy from 
            coordBufSize,     // col-row size of chiBuffer 
            coordBufCoord,    // top left src cell in chiBuffer 
            &srctWriteRect);  // dest. screen buffer rectangle 
        if (! fSuccess) 
        {
            printf("WriteConsoleOutput (%d)\n", GetLastError()); 
            return;
        }
        Sleep(10000); 
     
        // Restore the original active screen buffer. 
     
        if (! SetConsoleActiveScreenBuffer(hStdout)) 
        {
            printf("SetConsoleActiveScreenBuffer (%d)\n", GetLastError()); 
            return;
        }
    }
      

  15.   

    楼上的我看的不是很明白。这些东西以前没接触过,不过我试过GetStdHandle(STD_OUTPUT_HANDLE); 得到的是空。
    我的程序是MFC应用程序
      

  16.   

    终于搞定了。。
    CCmdProessDlg::CCmdProessDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CCmdProessDlg::IDD, pParent)
    , m_strIn(_T(""))
    , m_strOut(_T(""))
    {
    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE; HANDLE hInWrite;
    HANDLE hOutRead;
    if (!::CreatePipe(&m_hIn, &hInWrite, &sa, 0))
    {
    return;
    } if (!::CreatePipe(&hOutRead, &m_hOut, &sa, 0))
    {
    return;
    }
    //  ::CloseHandle(hInRead);
    //  ::CloseHandle(hOutWrite); PROCESS_INFORMATION pi = {0};
    STARTUPINFO si = {sizeof(STARTUPINFO)};
    ::GetStartupInfo(&si);
    si.hStdInput =  hOutRead;
    si.hStdError = hInWrite;
    si.hStdOutput = hInWrite;
    si.wShowWindow = SW_HIDE;
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; TCHAR sz[MAX_PATH] = _T("cmd");
    if (!::CreateProcess(NULL, sz
    ,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi)) 
    {
    return;
    } m_hProcess = pi.hProcess; ::CloseHandle(hOutRead);
    ::CloseHandle(hInWrite); ::CloseHandle(pi.hProcess);
    ::CloseHandle(pi.hThread);}
    CCmdProessDlg::~CCmdProessDlg()
    {
    WriteCmd(_T("exit"));
    CloseHandle(m_hIn);
    CloseHandle(m_hOut);}
    BOOL CCmdProessDlg::OnInitDialog()
    {
    CDialog::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
    BOOL bNameValid;
    CString strAboutMenu;
    bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
    ASSERT(bNameValid);
    if (!strAboutMenu.IsEmpty())
    {
    pSysMenu->AppendMenu(MF_SEPARATOR);
    pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    }
    } // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
    //  执行此操作
    SetIcon(m_hIcon, TRUE); // 设置大图标
    SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 UpdateIn(); return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
    }
    void CCmdProessDlg::OnOK()
    { WriteCmd(m_strIn); UpdateIn();
    }
    void CCmdProessDlg::UpdateIn()
    {
    UpdateData();
    Sleep(200); USES_CONVERSION;
    DWORD dwData;
    char sz[1024] = {0};
    while (PeekNamedPipe(m_hIn, sz, 1024, &dwData, NULL, 0) && dwData > 0)
    {
    ReadFile(m_hIn, sz, dwData, &dwData, NULL); m_strOut += A2T(sz);
    } dwData = GetLastError(); UpdateData(FALSE);
    }void CCmdProessDlg::WriteCmd( LPCTSTR sCmd )
    {
    USES_CONVERSION; char sz[1024] = "";
    strcpy(sz, T2A(sCmd));
    strcat(sz, "\n"); DWORD dwBytes;
    ::WriteFile(m_hOut, sz, strlen(sz), &dwBytes, NULL); Sleep(200);
    }
    万岁。。感谢各位支持。