使用BCB将Telnet集成到自己的一个程序界面里,请教大家
近期接手一个东东。
大致思路是:
我在自己的输入界面输入一条指令,将该指令传递给CMD,调用Telnet,Telnet成功后将数据截获,将数据反馈到自己的界面。参考了贵论坛许多这种重定向的帖子。
目前实现了大概功能。方法是建立两个管道,分别用来读写。创建一个执行进程,执行cmd命令,输出输入的端口设置为两个管道的相关端口。
目前测试了下。可以执行基本的cmd功能,如cd,dir,ping .并且能够达到实时的交互。但输入Telnet指令后,就没反映了。
大家能否帮我看看代码里出了什么问题。
并且我搜索了下,BCB有个TIdTelnet控件,但我自己的BCB4.0好像没这个控件。大家有没有什么思路可以更简单的实现这个telnet集成功能?谢谢
//这个是按钮响应函数,有两个Memo,Memo1用来显示CMD的输出数据,Memo2用来输入用户键入的指令
Button1Click(Tobject *Sender)
{
char buffer[4095]={0};
unsigned long dwBytes=0;
AnsiString a=Memo2->Text;
int x= WriteFile(hWriteInput,a.c_str(),a.Length(),&dwBytes,NULL);
if(x==0)
return;
WriteFile(hWriteInput,a.c_str(),"\n\r",1,&dwBytes,NULL);
FlushFileBuffers(hWriteInput);
int y= ReadFile(hReadOutput,buffer,4095,&dwBytes,NULL);
if(y==0)
return;
buffer[dwBytes]=0;
Memo1->Text=buffer;
}
//窗体建立时的函数,用来建立进程执行CMD命令
FormCreate(Tobject *Sender)
{
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor =NULL;
sa.bInheritHandle=true;
CreatePipe(&hReadOutput,&hWriteOutput,&sa,0);
CreatePipe(&hReadInput,&hWriteInput,&sa,0);
char szCmd[100];
PROCESS_INFORMATION m_ProcessInfo;
STARTUPINFO m_StartInfo;
GetStartupInfo(&m_StartInfo);
m_StartInfo.dwFlags=STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
m_StartInfo.hStdInput=hReadInput;
m_StartInfo.hStdOutput=hWriteOutput;
m_StartInfo.hStdError=hWriteOutput;
m_StartInfo.wShowWindow=SW_HIDE;
GetSystemDirectory(szCmd,100);
strcat(szCmd,"\\cmd.exe");
int ret = CreateProcess(
NULL,szCmd,NULL,NULL,true,0,NULL,NULL,&m_StartInfo,&m_ProcessInfo
);
if(ret==0)
return;
}
[解决办法]
BCB6.0以上都带了indy的Telnet控件,可以用。
[解决办法]
Button1Click(Tobject *Sender)
{
char buffer[4095]={0};
unsigned long dwBytes=0;
AnsiString a=Memo2->Text;
int x= WriteFile(hWriteInput,a.c_str(),a.Length(),&dwBytes,NULL);
if(x==0)
return;
WriteFile(hWriteInput,a.c_str(),"\n\r",1,&dwBytes,NULL);
Sleep();//加上一个数字,可能是telnet返回比较慢
FlushFileBuffers(hWriteInput);
int y= ReadFile(hReadOutput,buffer,4095,&dwBytes,NULL);
if(y==0)
return;
buffer[dwBytes]=0;
Memo1->Text=buffer;
}
[解决办法]
我试了下正常,是你系统安装不太完整吧?
[解决办法]
>>>Connected is not a member of TidTelnet
可能和你的indy版本有关系.
[解决办法]
用管道的确可以和cmd地行复杂的交互,但是不能做telnet,因为telnet是cmd又另外调用的一个程序(用dos的话说,你只能和dos外壳下的内部命令打交道,但不能控制外部命令)。
楼主若使用TIdTelnet组件的话,我可以提供一个自己写的封装了TIdTelnet的类,用了大半年了,还没出过问题。可以参考一下。
头文件:
/****************************************************************************描述: 本类用于提供Telnet自动脚本操作的功能。作者: 孙冬最后一次修改: 2009年6月1日(儿童节礼物)使用环境: C++ Builder 2009(Update 3)示例: TStringList* Bat = new TStringList; Bat->Add("foxconn"); Bat->Add("en"); Bat->Add("cisco"); Bat->Add("session slot 8 processor 1"); Bat->Add("cisco"); Bat->Add("en"); Bat->Add(""); TTelnetControl TC(2000); TC.Open("172.20.0.18"); TC.Start(Bat); TC.WaitFor(); TC.Close(); ShowMessage(kk.Result->Text); delete Bat;****************************************************************************///---------------------------------------#ifndef TTelnetH#define TTelnetH#include "IdTelnet.hpp"#include <ExtCtrls.hpp>//---------------------------------------class TTelnetControl{public: TTelnetControl(int WaitTime); //(参数WaitCount:最大等待时间(毫秒)) ~TTelnetControl(void); void Open(String HostIP); //连接Telnet主机 void Close(void); //断开Telnet主机 void Start(TStringList* Bat); //开始执行脚本 void SendCommand(AnsiString CMD); void WaitFor(void); //等待脚本执行结束public: TStringList* Result; //返回的数据private: TIdTelnet* _Telnet; TStringList* _Bat; TTimer* _CmdEngine; const int WaitTime; int _Counter; int _CmdPointer; bool _IsBusy;private: void __fastcall TelnetDataAvailable(TIdTelnet *Sender, const String Buffer); void __fastcall OnPulse(TObject *Sender);};#endif//---------------------------------------