荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Dreamer (我爱萤火虫), 信区: SoftDev
标  题: 【BCB】使用管道
发信站: 荔园晨风BBS站 (Sat May  8 14:20:13 2004), 站内信件

毕设需要用到的技术,贴出来大家分享 :)

http://expert.csdn.net/Expert/topic/3032/3032649.xml?temp=.1442682

主  题:  50分找帮手,可加分!!管道问题?
作  者:  fengxia0078 (风侠)
等  级:
信 誉 值:  100
所属论坛:  C++ Builder 基础类
问题点数:  50
回复次数:  2
发表时间:  2004-05-04 22:39:51



用ShellExecute(NULL,"open","gamv.exe","GV_data.par",NULL,SW_SHOWNORMAL)
运行之后,dos窗口几乎只显示了一秒。在dos窗口里gamv.exe输出了很多信息,我在Form1
上加了一个Memo1,设置为黑底白字......
请高手们帮助,希望能写完整的代码和说明。谢谢!!
明天早上就给分!



 回复人: lzf20lzf(一阵风-我真贱(2004-4-27)) ( ) 信誉:100  2004-05-04 23:32:00
 得分:0


  http://www.chinabcb.com/bbs/viewtopic.php?t=5113&highlight=%B9%DC%B5%C0
★使用管道技术实例
代码:
bool __fastcall TForm1::RunCmd(AnsiString cmd,TStringList *stringlist)
{
    TMemoryStream *memstream=new TMemoryStream();
    AnsiString rn="\\r\\n";
    PROCESS_INFORMATION proc;
    STARTUPINFO start;
    SECURITY_ATTRIBUTES sa;
    long ret;
    unsigned long lngBytesread;
    HANDLE hReadPipe,hWritePipe;
    char *strBuff=(char *)malloc(256);
    if(strBuff==NULL)
    {
        return false;
    }
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle=true;
    sa.lpSecurityDescriptor=NULL;
    ret=CreatePipe(&hReadPipe,&hWritePipe,&sa,0);
    if(ret==0)
    {
        //创建管道失败
        return false;
    }
    memset(&start,0x00,sizeof(STARTUPINFO));
    start.cb=sizeof(STARTUPINFO);
    start.dwFlags=STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    start.hStdOutput=hWritePipe;
    start.hStdError=hWritePipe;
    bool retc=CreateProcess(NULL,cmd.c_str(),NULL,NULL,true, 0, 0, NULL, &start,
 &proc);
    if(!retc)
    {
        return false;
    }
    CloseHandle(hWritePipe);
    unsigned long len;
    memstream->Position=0;
    while(true)
    {
        memset(strBuff,0x00,256);
        GetFileSize(hReadPipe,&len);
        ret = ReadFile(hReadPipe, strBuff, 256, &lngBytesread,NULL);
        if(ret==0)
        {
            break;
        }
        else
        {
            memstream->Write(strBuff,lngBytesread);
        }
    }
    CloseHandle(proc.hProcess);
    CloseHandle(proc.hThread);
    CloseHandle(hReadPipe);
    memstream->Position=0;
    free(strBuff);
    stringlist->LoadFromStream(memstream);
    memstream->Clear();
    delete memstream;
    return true;
}


以上为一个使用管道获取命令行模式的程序的运行结果的函数。

使用代码

TStringList *StrList=new TStringList;
AnsiString strcmd;

RunCmd(strcmd,StrList);

结果保留再StrList中。
试了试,发现上述代码运行时不能显示中间过程,要等到程序完全运行结束才能看到结果,
不太方便(特别是运行比较耗时的命令)。并且会多出一些不必要的空行,和dos窗口下看
到的结果不一样(例如运行ping的命令)。

下面是我改进的代码,把运行的情况直接显示在Memo1中。其实我觉得没有太大的必要使用
TMemoryStream,直接用AnsiString就可以了。
代码:

//---------------------------------------------------------------------------
String __fastcall TForm1::ExecuteApp(String sCmdline)
{
    PROCESS_INFORMATION proc = {0};
    long ret,k=1;
    bool bret;
    STARTUPINFO start = {0};
    SECURITY_ATTRIBUTES sa = {0};
    HANDLE hReadPipe ;
    HANDLE hWritePipe;
    String sOutput;
    String sBuffer;
    unsigned long lngBytesRead;
    char cBuffer[257];
    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor=0;
    sa.bInheritHandle = TRUE;
    bret =::CreatePipe(&hReadPipe, &hWritePipe,&sa, 0);
    if (!bret)
    {
        sOutput="CreatePipe failed. Error: " + String(GetLastError());
        Memo1->Lines->Add(sOutput);
        return sOutput;
    }
    start.cb = sizeof(STARTUPINFOA);
    start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    start.hStdOutput = hWritePipe;
    start.hStdError = hWritePipe;
    start.wShowWindow = SW_HIDE;
    sBuffer = sCmdline;
    ret =::CreateProcess(0, sBuffer.c_str(), &sa, &sa, TRUE,
NORMAL_PRIORITY_CLASS, 0, 0, &start, &proc);
    if (ret == 0)
    {
        sOutput="Bad command or filename";
        Memo1->Lines->Add(sOutput);
        return sOutput;
    }
    ::CloseHandle(hWritePipe);
    do
    {
        memset(cBuffer,'\0',sizeof(cBuffer));
        ret = ::ReadFile(hReadPipe, &cBuffer, 256, &lngBytesRead, 0);
        sBuffer=StrPas(cBuffer);
        sOutput = sOutput + sBuffer;
        Memo1->Text=Memo1->Text+sBuffer;
        Application->ProcessMessages();

    } while (ret != 0 );
    ::CloseHandle(proc.hProcess);
    ::CloseHandle(proc.hThread);
    ::CloseHandle(hReadPipe);
    return sOutput;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    ExecuteApp("Ping www.chinabcb.com");
}
//---------------------------------------------------------------------------








Top

 回复人: lzf20lzf(一阵风-我真贱(2004-4-27)) ( ) 信誉:100  2004-05-04 23:32:00
 得分:0


  下面是运行结果:

引用:
Pinging www.chinabcb.com [218.22.205.4] with 32 bytes of data:

Reply from 218.22.205.4: bytes=32 time=60ms TTL=115
Reply from 218.22.205.4: bytes=32 time=50ms TTL=115
Reply from 218.22.205.4: bytes=32 time=140ms TTL=115
Reply from 218.22.205.4: bytes=32 time=81ms TTL=115

Ping statistics for 218.22.205.4:

Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 50ms, Maximum = 140ms, Average = 82ms

以上程序没有使用线程,耗时长的程序界面反应缓慢。

★请问如何将标准输出或错误输出重定向到TMemo或TRichEdit中去?

我的意思是,在一个IDE程序中,调用system函
数时,可以把屏幕的输出在一个TMemo或TRichEdit中显示,
可不可以把cout<<和ceer<<也显示到里面?
可否告诉我那本书或文章有相关的介绍?

这里有源代码(例子):
http://www.chinabcb.com/bbs/viewtopic.php?t=5113&highlight=%B9%DC%B5%C0

BCB的WINTOOLS范例

        // Create the Pipe and get r/w handles
        HANDLE hReadPipe;
        HANDLE hWritePipe;
        assert(CreatePipe(&hReadPipe,
                                          &hWritePipe,
                          lpsa,
                          2500000));
        // initialize STARTUPINFO struct
        STARTUPINFO si;
        memset(&si, 0, sizeof(STARTUPINFO));
        si.cb = sizeof(STARTUPINFO);
        si.dwFlags = STARTF_USESHOWWINDOW |STARTF_USESTDHANDLES;
        si.wShowWindow = SW_HIDE;
        si.hStdOutput = hWritePipe;
        si.hStdError = hWritePipe;
        PROCESS_INFORMATION pi;
        assert(hWritePipe);
        // Run the cmdLine tool
        ResultsRE->Lines->Add("Working.....");
        Application->ProcessMessages();

      if(  CreateProcess(NULL,
                             CmdStrRE->Text.c_str(),
                             NULL,//security
                             NULL,// security
                             TRUE,//inherits handles
                             0,
                             0,
                             0,
                             &si,
                             &pi)

         ){
        CloseHandle(pi.hThread);

// read from the pipe and put in richedit
        assert(hReadPipe);
        DWORD BytesRead; //unsigned long
        char dest[4000];
        bool RdLoopDone = false;
        ResultsRE->Lines->Clear();
        FBreak = 1;
        if (ExitCode) Screen->Cursor = crDefault;
        while (!RdLoopDone) {
                memset(dest, 0, 4000);
            assert(ReadFile(hReadPipe, &dest, sizeof(dest), &BytesRead, NULL));
            ResultsRE->Lines->Add(String(dest));
            if (BytesRead < 4000) RdLoopDone = true;
            if (FBreak > 150) RdLoopDone = true;
            FBreak++;
        }
        ResultsRE->Lines->Add("FINISHED!");

http://expert.csdn.net/Expert/topic/2887/2887041.xml?temp=.8849298
★SECURITY_ATTRIBUTES saPipe;

    // 管道忏属性
    saPipe.nLength              = sizeof (SECURITY_ATTRIBUTES);
    saPipe.lpSecurityDescriptor = NULL;
    saPipe.bInheritHandle       = TRUE;

    if (!CreatePipe(&m_hReadPipe, &m_hWriteFile, &saPipe, 0)    // 创建输入管道
        ||!CreatePipe(&m_hReadFile, &m_hWritePipe, &saPipe, 0)   // 创建输出管道
    )
    {
        throw Exception("can't create shell pipe");
    }


    //
    // 连接管道
    //
    char szCmd[MAX_PATH];

    GetStartupInfo(&m_StartInfo);

    m_StartInfo.dwFlags       = STARTF_USESHOWWINDOW  // 不忽略 wShowWindow 成员
                            | STARTF_USESTDHANDLES; // 不忽略 Std 输入输出错误
    m_StartInfo.hStdInput     = m_hReadPipe;  // 连接输入, 可通过 m_hWriteFile

    m_StartInfo.hStdOutput    = m_hWritePipe; // 连接输出, 可通过 m_hReadFile 读
    m_StartInfo.hStdError     = m_hWritePipe; // 连接输出, 可通过 m_hReadFile 读
    m_StartInfo.wShowWindow   = SW_HIDE;      // 隐藏控制台窗体

    GetSystemDirectory(szCmd, MAX_PATH);
    strcat(szCmd, "\\cmd.exe");

    // 创建 cmd.exe 进程, 已将输入输出错误指向我们的程序
    CreateProcess(
            NULL,
            szCmd,
            NULL,
            NULL,
            TRUE,
            0,
            NULL,
            NULL,
            &m_StartInfo,
            &m_ProcessInfo
            );


    // 向管道里写入, cmd.exe 执行此命令
    if (Key == VK_RETURN)
    {
        WriteFile(m_hWriteFile, Edit1->Text.c_str(), Edit1->Text.Length(),
                &dwBytes, NULL);
        WriteFile(m_hWriteFile, "\n\r", 1, &dwBytes, NULL);
    }

// 从管道里读取数据
        ReadFile(Form1->hReadFile, lpBuff, 0x1000, &dwBytes, NULL);
        lpBuff[dwBytes] = 0;

        m_pCSMemo->Acquire();
        AddPipeInfo(lpBuff);
        m_pCSMemo->Release();

http://expert.csdn.net/Expert/topic/2021/2021806.xml?temp=.388241





--
如果你真的爱萤火虫,你就不应该将她困在瓶子里;
如果你真的爱萤火虫,你应该放开她,让她在天空中自由自在地飞!
虽然你会不舍得她,但是最终你就会明白这样你才真正拥有了她!

※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 210.21.224.234]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店