注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

AlexYoung

做好大家都必须要做的事,发展自己感兴趣的事,结束圣人所不齿的事...

 
 
 

日志

 
 

【转载】编写自己的IDE(续)@VC++  

2013-09-11 16:49:37|  分类: VC ++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

补充:相反方向的信息传递

上面这篇文章在网上发布后,引起了一些反响。很多网友来信询问这样一个问题:上文中演示的是图形界面程序实时捕获控制台程序的输出;但有不少控制台程序是交互式运行的(如ftp客户端程序),需要人们在控制界面输入特定的指令才能完成相应的功能——能不能用类似的办法,让图形界面程序向控制台程序输入特定的命令行指令呢?

如果我们想输入到控制台程序的指令序列是固定的,那完全可以使用更简单的办法:把命令序列存储在一个文本文件中,然后使用下面这样的重定向指令运行控制台程序:

foo.exe < commands.txt

但如果想输入到控制台的指令序列是由用户在操作图形界面程序时决定的,或是根据控制台程序的输出来决定的,我们就需要使用与上面文章中类似的管道法解决问题了。这一思路基本上和上文相同,只不过信息的传递方向颠倒了过来:图形界面程序在需要时将指令序列作为字符串传递给中介程序,中介程序将该字符串写入控制台程序的标准输入。

实现这种相反功能的中介程序proxy的代码如下:

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <string>

#include <windows.h>

 

using namespace std;

 

void exit_friendly(void)

{

    puts("请不要单独运行proxy.");

    exit(0);

}

 

int main( int argc, char *argv[] )

{

    HANDLE  hRead = NULL;

    DWORD   dwReaded;

    int     i = 0, ret = 0, len = 0;

    const int BUFFER_LEN = 256;

    char    psBuffer[BUFFER_LEN];

    FILE*   child_input;

    string  command_line = "";

 

    // 检查命令行,如存在管道句柄,则将其转换为HANDLE类型

    if (argc < 2)

        exit_friendly();

    if (!stricmp(argv[1], "-h"))

    {

        if (argc < 4)

            exit_friendly();

        hRead = (HANDLE)atoi(argv[2]);

        i = 3;

    }

    else

        i = 1;

 

    // 提取要执行的命令

    for (; i < argc; i++)

    {

        command_line += argv[i];

        command_line += " ";

    }

 

    // 使用_popen创建子进程并重定向其标准输入

    if( (child_input = _popen( command_line.c_str(), "wt" )) == NULL )

        exit( 1 );

 

    if (hRead)

    {

        while(1)

        {

            memset(psBuffer, 0, BUFFER_LEN);

            if (ReadFile(hRead, psBuffer, BUFFER_LEN, &dwReaded, NULL)

                    && dwReaded > 0)

            {

                fputs(psBuffer, child_input);

                fflush(child_input);

 

                psBuffer[4] = 0;

                if (!stricmp(psBuffer, "quit"))

                    break;

            }

        }

    }

    return _pclose( child_input );

}


 

图形界面程序中,创建管道并启动中介程序的示例代码如下:

    HANDLE hRead, hWrite;

    HANDLE hProcess;

 

    PROCESS_INFORMATION pi;

    STARTUPINFO siStartInfo;

    SECURITY_ATTRIBUTES saAttr;

    CString Output, tmp;

    char command_line[200];

 

    // 创建与proxy.exe通讯的可继承的匿名管道

    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);

    saAttr.bInheritHandle = TRUE;

    saAttr.lpSecurityDescriptor = NULL;

    if (!CreatePipe(&hRead, &hWrite, &saAttr, 0))

    {

        AfxMessageBox("创建管道失败");

        EndDialog(IDCANCEL);

        return FALSE;

    }

 

    // 准备proxy.exe的命令行,在命令行给出写管道句柄和要proxy.exe执行的命令

    memset(&pi, 0, sizeof(pi));

    sprintf(command_line, "proxy -h %d ftp ...", (unsigned int)hRead);

 

    ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );

    //siStartInfo.cb = sizeof(STARTUPINFO);

    //siStartInfo.wShowWindow = SW_HIDE;

    //siStartInfo.dwFlags = STARTF_USESHOWWINDOW;

    if (!CreateProcess( NULL, command_line, NULL, NULL, TRUE,

                        0, NULL, NULL, &siStartInfo, &pi))

    {

        AfxMessageBox("调用proxy.exe时失败");

        EndDialog(IDCANCEL);

        return FALSE;

    }

    hProcess = pi.hProcess;

 

图形界面程序中,向控制台程序发送某特定命令的示例代码如下:

    char command = "help";

    DWORD dwWritten;

    WriteFile(hWrite, command, strlen(command), &dwWritten, NULL);

 

显然,利用这两种方向的管道,我们很容易为一个纯控制台界面的程序加上一层图形用户界面的漂亮外壳。

王咏刚

200312

  评论这张
 
阅读(134)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017