进程利用管道通讯的问题? ( 积分: 200 )

  • 主题发起人 主题发起人 迈克老狼
  • 开始时间 开始时间

迈克老狼

Unregistered / Unconfirmed
GUEST, unregistred user!
这是两个程序利用标准输入、输出重定向的问题,主程序启动后,点击界面上的读取按钮,
没有问题,把客户端程序的字符都读出来了,但是第二次点的时候,即客户程序没有发送字符的时候,则出现死机现象,调试一下,是死在 if (!ReadFile(hChildStdoutRdDup, chBuf,4096, &dwRead, NULL) || dwRead == 0) return;
这一句,就是客户程序没有数据时边死在此,希望有经验的朋友指点一下,谢谢。。。
主程序启动客户程序,主程序中的project2.exe,就是客户程序的名字,客户程序是一个控制台程序代码如下:
int main(int argc, char* argv[])
{
for (int i=0;i<100;i++)
{
printf("123");
fflush(stdout);
}
getchar();
}
主程序如下:
头文件:
//---------------------------------------------------------------------------

#ifndef MainFrmH
#define MainFrmH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TfrmMain : public TForm
{
__published: // IDE-managed Components
TPageControl *pgcMain;
TTabSheet *tshMain;
TMemo *moMsg;
TButton *btnRead;
void __fastcall FormCreate(TObject *Sender);
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
void __fastcall btnReadClick(TObject *Sender);
private:
HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,
hSaveStdin, hSaveStdout;
DWORD dwProcessId;

BOOL CreateChildProcess(DWORD& dwProcessId);
bool CreateConsoleRedirect();
void WriteToPipe( LPCTSTR line );
public: // User declarations
__fastcall TfrmMain(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TfrmMain *frmMain;
//---------------------------------------------------------------------------
#endif
Cpp文件:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "MainFrm.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TfrmMain *frmMain;
//---------------------------------------------------------------------------
bool TfrmMain::CreateConsoleRedirect()
{
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;
// Öض¨Ïò×Ó½ø³ÌµÄ±ê×¼Êä³ö...
// ±£´æµ±Ç°±ê×¼Êä³öµÄ¾ä±ú
hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if( !CreatePipe( &hChildStdoutRd, &hChildStdoutWr, &saAttr, 0) )
{
ShowMessage("Stdout pipe creation failed");
return FALSE;
}
// ÉèÖÃÒ»¸öд¾ä±úµ½¹ÜµÀ£¬Ê¹Ö®³ÉΪ±ê×¼Êä³ö
if( !SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr) )
{
ShowMessage("Redirecting STDOUT failed");
return FALSE;
}
// ´´½¨²»¿É¼Ì³ÐµÄ¶Á¾ä±ú²¢¹Ø±Õ¿É¼Ì³ÐµÄ¶Á¾ä±ú
fSuccess = DuplicateHandle( GetCurrentProcess(), hChildStdoutRd,
GetCurrentProcess(), &hChildStdoutRdDup ,
0, FALSE,
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
ShowMessage("DuplicateHandle failed");
return FALSE;
}
CloseHandle( hChildStdoutRd );
// Öض¨Ïò×Ó½ø³ÌµÄ±ê×¼ÊäÈë...
// ±£´æµ±Ç°±ê×¼ÊäÈëµÄ¾ä±ú
hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);

//Ϊ×Ó½ø³ÌµÄ±ê×¼ÊäÈë´´½¨Ò»¸ö¹ÜµÀ
if( !CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0) )
{
ShowMessage("Stdin pipe creation failed");
return FALSE;
}
// ÉèÖÃÒ»¸öд¾ä±úµ½¹ÜµÀ£¬Ê¹Ö®³ÉΪ±ê×¼ÊäÈë
if( !SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd) )
{
ShowMessage("Redirecting Stdin failed");
return FALSE;
}
// ¸´ÖÆд¾ä±úµ½¹ÜµÀ£¬ÕâÑùËü¾Í²»¿É¼Ì³Ð
// Duplicate the write handle to the pipe so it is not inherited.
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
GetCurrentProcess(), &hChildStdinWrDup,
0, FALSE, // not inherited
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
ShowMessage("DuplicateHandle failed");
return FALSE;
}
CloseHandle(hChildStdinWr);
// ´´½¨×Ó½ø³Ì
if( !CreateChildProcess(dwProcessId))
{
ShowMessage("CreateChildProcess failed");
return FALSE;
}
// ×Ó½ø³Ì´´½¨Íê±Ï£¬ÖØÖÃϵͳ±ê×¼ÊäÈëÊä³ö
if( !SetStdHandle(STD_INPUT_HANDLE, hSaveStdin) )
{
ShowMessage("Re-redirecting Stdin failed");
return FALSE;
}
if( !SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout) )
{
ShowMessage("Re-redirecting Stdout failed");
return FALSE;
}

return true;
}
BOOL TfrmMain::CreateChildProcess(DWORD& dwProcessId)
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;

// Set up members of STARTUPINFO structure.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);

siStartInfo.dwFlags = STARTF_USESTDHANDLES;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdError = hChildStdoutWr;

TCHAR shellCmd[_MAX_PATH];

strcpy(shellCmd,"project2.exe");
// Create the child process.
BOOL ret = CreateProcess( NULL,
shellCmd, // applicatin name
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
DETACHED_PROCESS, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if( ret )
dwProcessId = piProcInfo.dwProcessId;
return ret;
}
void TfrmMain::WriteToPipe( LPCTSTR line )
{
DWORD dwWritten;
if (!WriteFile( hChildStdinWrDup, line, strlen(line)*sizeof(TCHAR),
&dwWritten, NULL ))
{
ShowMessage("дÈëʧ°Ü");
}
}
__fastcall TfrmMain::TfrmMain(TComponent* Owner)
: TForm(Owner)
{

}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::FormCreate(TObject *Sender)
{
CreateConsoleRedirect();
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::FormClose(TObject *Sender, TCloseAction &Action)
{
CloseHandle( hChildStdinRd);
CloseHandle( hChildStdoutWr);
CloseHandle( hChildStdinWrDup );
CloseHandle( hChildStdoutRdDup );

}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnReadClick(TObject *Sender)
{
char chBuf[4096];
AnsiString TempStr;
DWORD dwRead;
if (!ReadFile(hChildStdoutRdDup, chBuf,4096, &dwRead, NULL) || dwRead == 0) return;
TempStr=Trim(AnsiString(chBuf));
moMsg->Lines->Add(TempStr);
}
//---------------------------------------------------------------------------
 
这是两个程序利用标准输入、输出重定向的问题,主程序启动后,点击界面上的读取按钮,
没有问题,把客户端程序的字符都读出来了,但是第二次点的时候,即客户程序没有发送字符的时候,则出现死机现象,调试一下,是死在 if (!ReadFile(hChildStdoutRdDup, chBuf,4096, &dwRead, NULL) || dwRead == 0) return;
这一句,就是客户程序没有数据时边死在此,希望有经验的朋友指点一下,谢谢。。。
主程序启动客户程序,主程序中的project2.exe,就是客户程序的名字,客户程序是一个控制台程序代码如下:
int main(int argc, char* argv[])
{
for (int i=0;i<100;i++)
{
printf("123");
fflush(stdout);
}
getchar();
}
主程序如下:
头文件:
//---------------------------------------------------------------------------

#ifndef MainFrmH
#define MainFrmH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TfrmMain : public TForm
{
__published: // IDE-managed Components
TPageControl *pgcMain;
TTabSheet *tshMain;
TMemo *moMsg;
TButton *btnRead;
void __fastcall FormCreate(TObject *Sender);
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
void __fastcall btnReadClick(TObject *Sender);
private:
HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,
hSaveStdin, hSaveStdout;
DWORD dwProcessId;

BOOL CreateChildProcess(DWORD& dwProcessId);
bool CreateConsoleRedirect();
void WriteToPipe( LPCTSTR line );
public: // User declarations
__fastcall TfrmMain(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TfrmMain *frmMain;
//---------------------------------------------------------------------------
#endif
Cpp文件:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "MainFrm.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TfrmMain *frmMain;
//---------------------------------------------------------------------------
bool TfrmMain::CreateConsoleRedirect()
{
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;
// Öض¨Ïò×Ó½ø³ÌµÄ±ê×¼Êä³ö...
// ±£´æµ±Ç°±ê×¼Êä³öµÄ¾ä±ú
hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if( !CreatePipe( &hChildStdoutRd, &hChildStdoutWr, &saAttr, 0) )
{
ShowMessage("Stdout pipe creation failed");
return FALSE;
}
// ÉèÖÃÒ»¸öд¾ä±úµ½¹ÜµÀ£¬Ê¹Ö®³ÉΪ±ê×¼Êä³ö
if( !SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr) )
{
ShowMessage("Redirecting STDOUT failed");
return FALSE;
}
// ´´½¨²»¿É¼Ì³ÐµÄ¶Á¾ä±ú²¢¹Ø±Õ¿É¼Ì³ÐµÄ¶Á¾ä±ú
fSuccess = DuplicateHandle( GetCurrentProcess(), hChildStdoutRd,
GetCurrentProcess(), &hChildStdoutRdDup ,
0, FALSE,
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
ShowMessage("DuplicateHandle failed");
return FALSE;
}
CloseHandle( hChildStdoutRd );
// Öض¨Ïò×Ó½ø³ÌµÄ±ê×¼ÊäÈë...
// ±£´æµ±Ç°±ê×¼ÊäÈëµÄ¾ä±ú
hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);

//Ϊ×Ó½ø³ÌµÄ±ê×¼ÊäÈë´´½¨Ò»¸ö¹ÜµÀ
if( !CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0) )
{
ShowMessage("Stdin pipe creation failed");
return FALSE;
}
// ÉèÖÃÒ»¸öд¾ä±úµ½¹ÜµÀ£¬Ê¹Ö®³ÉΪ±ê×¼ÊäÈë
if( !SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd) )
{
ShowMessage("Redirecting Stdin failed");
return FALSE;
}
// ¸´ÖÆд¾ä±úµ½¹ÜµÀ£¬ÕâÑùËü¾Í²»¿É¼Ì³Ð
// Duplicate the write handle to the pipe so it is not inherited.
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
GetCurrentProcess(), &hChildStdinWrDup,
0, FALSE, // not inherited
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
ShowMessage("DuplicateHandle failed");
return FALSE;
}
CloseHandle(hChildStdinWr);
// ´´½¨×Ó½ø³Ì
if( !CreateChildProcess(dwProcessId))
{
ShowMessage("CreateChildProcess failed");
return FALSE;
}
// ×Ó½ø³Ì´´½¨Íê±Ï£¬ÖØÖÃϵͳ±ê×¼ÊäÈëÊä³ö
if( !SetStdHandle(STD_INPUT_HANDLE, hSaveStdin) )
{
ShowMessage("Re-redirecting Stdin failed");
return FALSE;
}
if( !SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout) )
{
ShowMessage("Re-redirecting Stdout failed");
return FALSE;
}

return true;
}
BOOL TfrmMain::CreateChildProcess(DWORD& dwProcessId)
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;

// Set up members of STARTUPINFO structure.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);

siStartInfo.dwFlags = STARTF_USESTDHANDLES;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdError = hChildStdoutWr;

TCHAR shellCmd[_MAX_PATH];

strcpy(shellCmd,"project2.exe");
// Create the child process.
BOOL ret = CreateProcess( NULL,
shellCmd, // applicatin name
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
DETACHED_PROCESS, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if( ret )
dwProcessId = piProcInfo.dwProcessId;
return ret;
}
void TfrmMain::WriteToPipe( LPCTSTR line )
{
DWORD dwWritten;
if (!WriteFile( hChildStdinWrDup, line, strlen(line)*sizeof(TCHAR),
&dwWritten, NULL ))
{
ShowMessage("дÈëʧ°Ü");
}
}
__fastcall TfrmMain::TfrmMain(TComponent* Owner)
: TForm(Owner)
{

}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::FormCreate(TObject *Sender)
{
CreateConsoleRedirect();
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::FormClose(TObject *Sender, TCloseAction &Action)
{
CloseHandle( hChildStdinRd);
CloseHandle( hChildStdoutWr);
CloseHandle( hChildStdinWrDup );
CloseHandle( hChildStdoutRdDup );

}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnReadClick(TObject *Sender)
{
char chBuf[4096];
AnsiString TempStr;
DWORD dwRead;
if (!ReadFile(hChildStdoutRdDup, chBuf,4096, &dwRead, NULL) || dwRead == 0) return;
TempStr=Trim(AnsiString(chBuf));
moMsg->Lines->Add(TempStr);
}
//---------------------------------------------------------------------------
 
匿名管道不支持异步读写,要避免读写时阻塞,最好使用线程
 
to: tseug
加了个线程,好像还有相同情况,请大侠分析一下,难道是线程用的不对?...
线程的代码:
头文件
//---------------------------------------------------------------------------

#ifndef ReadPipeThreadH
#define ReadPipeThreadH
//---------------------------------------------------------------------------
#include <Classes.hpp>
//---------------------------------------------------------------------------
class TReadPipe : public TThread
{
private:
TMemo* ShowMemo;
void __fastcall ReadAndShow();
protected:
void __fastcall Execute();
public:
__fastcall TReadPipe(bool CreateSuspended,TMemo* MyMemo);
};
//---------------------------------------------------------------------------
#endif
cpp文件
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "ReadPipeThread.h"
#include "MainFrm.h"
#pragma package(smart_init)
extern HANDLE hChildStdoutRdDup;

__fastcall TReadPipe::TReadPipe(bool CreateSuspended,TMemo* MyMemo)
: TThread(CreateSuspended)
{
FreeOnTerminate = true;
ShowMemo = MyMemo;
}
void __fastcall TReadPipe::ReadAndShow()
{

char chBuf[4096];
AnsiString TempStr;
DWORD dwRead;
for (;;)
{
ReadFile(hChildStdoutRdDup, chBuf,4096, &dwRead, NULL);
if (dwRead>0)
{
TempStr=Trim(AnsiString(chBuf));
ShowMemo->Lines->Add(TempStr);
}
}
}
//---------------------------------------------------------------------------
void __fastcall TReadPipe::Execute()
{
while (!Terminated) Synchronize(ReadAndShow);
}
//---------------------------------
修改后的主程序代码
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "MainFrm.h"
#include "ReadPipeThread.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TfrmMain *frmMain;
HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,
hSaveStdin, hSaveStdout;
DWORD dwProcessId;
TReadPipe* ReadMsgThread;
//---------------------------------------------------------------------------
bool TfrmMain::CreateConsoleRedirect()
{
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;
// Öض¨Ïò×Ó½ø³ÌµÄ±ê×¼Êä³ö...
// ±£´æµ±Ç°±ê×¼Êä³öµÄ¾ä±ú
hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if( !CreatePipe( &hChildStdoutRd, &hChildStdoutWr, &saAttr, 0) )
{
ShowMessage("Stdout pipe creation failed");
return FALSE;
}
// ÉèÖÃÒ»¸öд¾ä±úµ½¹ÜµÀ£¬Ê¹Ö®³ÉΪ±ê×¼Êä³ö
if( !SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr) )
{
ShowMessage("Redirecting STDOUT failed");
return FALSE;
}
// ´´½¨²»¿É¼Ì³ÐµÄ¶Á¾ä±ú²¢¹Ø±Õ¿É¼Ì³ÐµÄ¶Á¾ä±ú
fSuccess = DuplicateHandle( GetCurrentProcess(), hChildStdoutRd,
GetCurrentProcess(), &hChildStdoutRdDup ,
0, FALSE,
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
ShowMessage("DuplicateHandle failed");
return FALSE;
}
CloseHandle( hChildStdoutRd );
// Öض¨Ïò×Ó½ø³ÌµÄ±ê×¼ÊäÈë...
// ±£´æµ±Ç°±ê×¼ÊäÈëµÄ¾ä±ú
hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);

//Ϊ×Ó½ø³ÌµÄ±ê×¼ÊäÈë´´½¨Ò»¸ö¹ÜµÀ
if( !CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0) )
{
ShowMessage("Stdin pipe creation failed");
return FALSE;
}
// ÉèÖÃÒ»¸öд¾ä±úµ½¹ÜµÀ£¬Ê¹Ö®³ÉΪ±ê×¼ÊäÈë
if( !SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd) )
{
ShowMessage("Redirecting Stdin failed");
return FALSE;
}
// ¸´ÖÆд¾ä±úµ½¹ÜµÀ£¬ÕâÑùËü¾Í²»¿É¼Ì³Ð
// Duplicate the write handle to the pipe so it is not inherited.
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
GetCurrentProcess(), &hChildStdinWrDup,
0, FALSE, // not inherited
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
ShowMessage("DuplicateHandle failed");
return FALSE;
}
CloseHandle(hChildStdinWr);
// ´´½¨×Ó½ø³Ì
if( !CreateChildProcess(dwProcessId))
{
ShowMessage("CreateChildProcess failed");
return FALSE;
}
// ×Ó½ø³Ì´´½¨Íê±Ï£¬ÖØÖÃϵͳ±ê×¼ÊäÈëÊä³ö
if( !SetStdHandle(STD_INPUT_HANDLE, hSaveStdin) )
{
ShowMessage("Re-redirecting Stdin failed");
return FALSE;
}
if( !SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout) )
{
ShowMessage("Re-redirecting Stdout failed");
return FALSE;
}

return true;
}
BOOL TfrmMain::CreateChildProcess(DWORD& dwProcessId)
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;

// Set up members of STARTUPINFO structure.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);

siStartInfo.dwFlags = STARTF_USESTDHANDLES;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdError = hChildStdoutWr;

TCHAR shellCmd[_MAX_PATH];

strcpy(shellCmd,"project2.exe");
// Create the child process.
BOOL ret = CreateProcess( NULL,
shellCmd, // applicatin name
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
DETACHED_PROCESS, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if( ret )
dwProcessId = piProcInfo.dwProcessId;
return ret;
}
void TfrmMain::WriteToPipe( LPCTSTR line )
{
DWORD dwWritten;
if (!WriteFile( hChildStdinWrDup, line, strlen(line)*sizeof(TCHAR),
&dwWritten, NULL ))
{
ShowMessage("дÈëʧ°Ü");
}
}
__fastcall TfrmMain::TfrmMain(TComponent* Owner)
: TForm(Owner)
{

}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::FormCreate(TObject *Sender)
{
CreateConsoleRedirect();
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::FormClose(TObject *Sender, TCloseAction &Action)
{
CloseHandle( hChildStdinRd);
CloseHandle( hChildStdoutWr);
CloseHandle( hChildStdinWrDup );
CloseHandle( hChildStdoutRdDup );

}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnReadClick(TObject *Sender)
{
char chBuf[4096];
AnsiString TempStr;
DWORD dwRead;
if (!ReadFile(hChildStdoutRdDup, chBuf,4096, &dwRead, NULL) || dwRead == 0) return;
TempStr=Trim(AnsiString(chBuf));
moMsg->Lines->Add(TempStr);
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnStartClick(TObject *Sender)
{
if (ReadMsgThread!=NULL)
{
ReadMsgThread->Resume();
ReadMsgThread->Terminate();
}

ReadMsgThread=new TReadPipe(false,moMsg);

}
//---------------------------------------------------------------------------

void __fastcall TfrmMain::btnTerminateClick(TObject *Sender)
{
ReadMsgThread->Resume();
ReadMsgThread->Terminate();

}
//---------------------------------------------------------------------------

void __fastcall TfrmMain::btnResumeClick(TObject *Sender)
{
if (btnResume->Caption=="Suspend")
{
ReadMsgThread->Suspend();
btnResume->Caption = "Resume";
return;
}
if (btnResume->Caption=="Resume")
{
ReadMsgThread->Resume();
btnResume->Caption = "Suspend";
return;
}
}
//---------------------------------------------------------------------------
 
同样的程序,vc6下面没有问题
/ ConsoleView.cpp : implementation file
//

#include "stdafx.h"
//#include "gurueditor.h"
#include "ConsoleView.h"

#include "Console.h"
#include "ConsoleDoc.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CConsoleView

IMPLEMENT_DYNCREATE(CConsoleView, CEditView)

CConsoleView::CConsoleView()
{
dwProcessId = DWORD(-1);//³õʼ»¯½ø³ÌID
m_pReadThread = NULL;

// Initialize LOGFONT structure
memset(&m_lf, 0, sizeof(m_lf));
m_lf.lfWeight = FW_NORMAL;
m_lf.lfCharSet = GB2312_CHARSET;//ANSI_CHARSET;
m_lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
m_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
m_lf.lfQuality = DEFAULT_QUALITY;
m_lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
lstrcpy(m_lf.lfFaceName, _T("FixedSys"));
}

CConsoleView::~CConsoleView()
{
}

BEGIN_MESSAGE_MAP(CConsoleView, CEditView)
//{{AFX_MSG_MAP(CConsoleView)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_CHAR()
ON_WM_KEYDOWN()
ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CConsoleView drawing

void CConsoleView::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
// TODO: add draw code here
}

/////////////////////////////////////////////////////////////////////////////
// CConsoleView diagnostics

#ifdef _DEBUG
void CConsoleView::AssertValid() const
{
CEditView::AssertValid();
}

void CConsoleView::Dump(CDumpContext& dc) const
{
CEditView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CConsoleView message handlers

int CConsoleView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CEditView::OnCreate(lpCreateStruct) == -1)
return -1;

// GetEditCtrl().SetReadOnly( TRUE );
DWORD dwStyle = GetWindowLong( GetEditCtrl().GetSafeHwnd(),GWL_STYLE );
if( dwStyle )
{
dwStyle |= DS_LOCALEDIT;
SetWindowLong( GetEditCtrl().GetSafeHwnd(),GWL_STYLE,dwStyle );
}

if( m_defFont.CreateFontIndirect( &m_lf ) )
GetEditCtrl().SetFont( &m_defFont );
if( !CreateConsoleRedirect() )
return -1;

return 0;
}

#define BUFSIZE 4096

BOOL CConsoleView::CreateConsoleRedirect()
{
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;

// Öض¨Ïò×Ó½ø³ÌµÄ±ê×¼Êä³ö...
// ±£´æµ±Ç°±ê×¼Êä³öµÄ¾ä±ú
hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
//Ϊ×Ó½ø³ÌµÄ±ê×¼Êä³ö´´½¨Ò»¸ö¹ÜµÀ
if( !CreatePipe( &hChildStdoutRd, &hChildStdoutWr, &saAttr, 0) )
{
TRACE0( _T("Stdout pipe creation failed/n") );
return FALSE;
}
// ÉèÖÃÒ»¸öд¾ä±úµ½¹ÜµÀ£¬Ê¹Ö®³ÉΪ±ê×¼Êä³ö
if( !SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr) )
{
TRACE0( _T("Redirecting STDOUT failed/n") );
return FALSE;
}
// ´´½¨²»¿É¼Ì³ÐµÄ¶Á¾ä±ú²¢¹Ø±Õ¿É¼Ì³ÐµÄ¶Á¾ä±ú
fSuccess = DuplicateHandle( GetCurrentProcess(), hChildStdoutRd,
GetCurrentProcess(), &hChildStdoutRdDup ,
0, FALSE,
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
TRACE0( _T("DuplicateHandle failed/n") );
return FALSE;
}
CloseHandle( hChildStdoutRd );

// Öض¨Ïò×Ó½ø³ÌµÄ±ê×¼ÊäÈë...
// ±£´æµ±Ç°±ê×¼ÊäÈëµÄ¾ä±ú
hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);

//Ϊ×Ó½ø³ÌµÄ±ê×¼ÊäÈë´´½¨Ò»¸ö¹ÜµÀ
if( !CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0) )
{
TRACE0( _T("Stdin pipe creation failed/n") );
return FALSE;
}
// ÉèÖÃÒ»¸öд¾ä±úµ½¹ÜµÀ£¬Ê¹Ö®³ÉΪ±ê×¼ÊäÈë
if( !SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd) )
{
TRACE0( _T("Redirecting Stdin failed/n") );
return FALSE;
}
// ¸´ÖÆд¾ä±úµ½¹ÜµÀ£¬ÕâÑùËü¾Í²»¿É¼Ì³Ð
// Duplicate the write handle to the pipe so it is not inherited.
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
GetCurrentProcess(), &hChildStdinWrDup,
0, FALSE, // not inherited
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
TRACE0( _T("DuplicateHandle failed/n") );
return FALSE;
}
CloseHandle(hChildStdinWr);
// ´´½¨×Ó½ø³Ì
if( !CreateChildProcess(dwProcessId) )
{
TRACE0( _T("CreateChildProcess failed/n") );
return FALSE;
}
// ×Ó½ø³Ì´´½¨Íê±Ï£¬ÖØÖÃϵͳ±ê×¼ÊäÈëÊä³ö
if( !SetStdHandle(STD_INPUT_HANDLE, hSaveStdin) )
{
TRACE0( _T("Re-redirecting Stdin failed/n") );
return FALSE;
}
if( !SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout) )
{
TRACE0( _T("Re-redirecting Stdout failed/n") );
return FALSE;
}
m_pReadThread = AfxBeginThread( (AFX_THREADPROC)ReadPipeThreadProc,(LPVOID)this );
if( !m_pReadThread )
{
TRACE0( _T("Cannot start read-redirect thread!/n") );
return FALSE;
}
WriteToPipe("ucci");
return TRUE;
}

BOOL CConsoleView::CreateChildProcess(DWORD& dwProcessId)
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;

// Set up members of STARTUPINFO structure.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);

siStartInfo.dwFlags = STARTF_USESTDHANDLES;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdError = hChildStdoutWr;

TCHAR shellCmd[_MAX_PATH];

// if( !GetEnvironmentVariable(_T("ComSpec"), shellCmd, _MAX_PATH) )
// return FALSE;
// strcpy(shellCmd,"eleeye09.exe");
// strcpy(shellCmd,"keplugin.exe");
strcpy(shellCmd,"Project2.exe");
#ifdef _UNICODE
_tcscat( shellCmd, _T(" /U") );
#else
_tcscat( shellCmd, _T(" /A") );
#endif
// Create the child process.
BOOL ret = CreateProcess( NULL,
shellCmd, // applicatin name
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
DETACHED_PROCESS, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if( ret )
dwProcessId = piProcInfo.dwProcessId;
return ret;
}

void CConsoleView::WriteToPipe( LPCTSTR line )
{
DWORD dwWritten;
if (!WriteFile( hChildStdinWrDup, line, _tcslen(line)*sizeof(TCHAR),
&dwWritten, NULL ))
{
TRACE0( _T("дÈëʧ°Ü!/n") );
}
}

UINT CConsoleView::ReadPipeThreadProc( LPVOID pParam )
{
DWORD dwRead;
TCHAR chBuf[BUFSIZE];
CConsoleView* pView = (CConsoleView*)pParam;

TRACE0( _T("ReadPipe Thread begin run/n") );
for( ;; )
{
if( !ReadFile( pView->hChildStdoutRdDup, chBuf,
BUFSIZE, &dwRead, NULL) || dwRead == 0)
break;
chBuf[dwRead/sizeof(TCHAR)] = _T('/0');
pView->AddTexts( chBuf );
pView->m_nLength = pView->GetEditCtrl().SendMessage( WM_GETTEXTLENGTH );
}
CloseHandle( pView ->hChildStdinRd);
CloseHandle( pView ->hChildStdoutWr);
CloseHandle( pView ->hChildStdinWrDup );
CloseHandle( pView ->hChildStdoutRdDup );
pView->m_pReadThread = NULL;
pView->dwProcessId = DWORD(-1);
pView->PostMessage( WM_CLOSE );
return 1;
}


void CConsoleView::OnDestroy()
{
if( dwProcessId!=DWORD(-1) )
{
HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessId );
if( hProcess )
{
TerminateProcess( hProcess,0 );
CloseHandle( hProcess );
}
}
if( m_pReadThread )
{
TerminateThread( m_pReadThread->m_hThread,0 );
delete m_pReadThread;
}
CEditView::OnDestroy();
}

void CConsoleView::AddTexts(LPCTSTR string)
{
MoveToEnd();
GetEditCtrl().ReplaceSel( string );
}

void CConsoleView::AddTexts(TCHAR ch)
{
TCHAR string[2];
string[0] = ch;
string[1] = _T('/0');
AddTexts( (LPCTSTR)string );
}

void CConsoleView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
/*int nPos = GetCurrentPosition();
if( nChar==8 && nPos<=m_nLength )
return;
if( nPos<m_nLength )
MoveToEnd();*/
CEditView::OnChar(nChar, nRepCnt, nFlags);
WriteToPipe("level");
if( nChar==13 )
{
CString input;
CString strtmp;
strtmp="exit";
strtmp+="/r/n";
GetUserInput(input);
WriteToPipe(input);
if(input==strtmp)
exit(1);
strtmp="cls";
strtmp+="/r/n";
if(input==strtmp)
GetEditCtrl().SetWindowText("");

}
}

void CConsoleView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
static CString strhold;
CString str;
if( nChar==VK_DELETE )
{
if( GetCurrentPosition()<m_nLength )
return;
}
//if( nChar==VK_CONTROL)//x
{
//GetAsyncKeyState(88);
//GetEditCtrl().GetWindowText(str);
//if(strhold.GetLength()>str.GetLength())
{
//GetEditCtrl().SetWindowText(strhold);
//AfxMessageBox(str+"|"+strhold);
}
//if(GetAsyncKeyState(88))

}

GetEditCtrl().GetWindowText(strhold);

return;
CEditView::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CConsoleView::MoveToEnd()
{
int nLen = GetEditCtrl().SendMessage( WM_GETTEXTLENGTH );
GetEditCtrl().SetSel( nLen,nLen );
}

int CConsoleView::GetCurrentPosition()
{
GetEditCtrl().SetSel(-1,-1);
int nstart,nstop;
GetEditCtrl().GetSel(nstart,nstop);
return nstart;
}

void CConsoleView::GetUserInput(CString &input)
{
int where = GetCurrentPosition();
HLOCAL hBuffer = GetEditCtrl().GetHandle();
if( hBuffer )
{
LPCTSTR szBuffer = (LPCTSTR)LocalLock(hBuffer);
if( szBuffer )
{
input = CString( szBuffer+m_nLength,(where-m_nLength) );
LocalUnlock( hBuffer );
}
}
}

int CConsoleView::GetSelLength()
{
int nstart,nstop;
GetEditCtrl().GetSel(nstart,nstop);
return (nstart-nstop);
}

BOOL CConsoleView::PreCreateWindow(CREATESTRUCT& cs)
{
return CEditView::PreCreateWindow(cs);
}

void CConsoleView::ClearWindow()
{
if( dwProcessId!=DWORD(-1) )
{
HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessId );
if( hProcess )
{
TerminateProcess( hProcess,0 );
CloseHandle( hProcess );
}
}
if( m_pReadThread )
{
TerminateThread( m_pReadThread->m_hThread,0 );
delete m_pReadThread;
}
GetEditCtrl().SetWindowText("");
}
void CConsoleView::OnChange()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CEditView::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.

// TODO: Add your control notification handler code here

}
 
接受答案了.
 
后退
顶部