从利用匿名管道实现可交互式远程超级终端cmd.exe说起

为了实现一个可交互式的远程cmd,我选用了匿名管道来实现cmd的重定向,通过把cmd.exe进程的输入输出重定位到管道的输入输出可以实现主进程与cmd.exe的交互。具体实现重定位的技术是利用与创建进程的函数CreateProcess的一个参数STARTUPINFO来进行设置,这个参数可以用于设置进程的输入输出,默认的情况是系统的标准输入输出,修改后可以重定位到管道的输入输出。

因为匿名管道是单向的,为了实现主进程与子进程之间的交互,创建两个管道。

        if (!CreatePipe(&hReadStdin, &hWriteStdin, &sa, 0))
        {
            return -1;
        }

        if (!CreatePipe(&hReadStdout, &hWriteStdout, &sa, 0))
        {
            return -1;
        }

创建两个管道后再进行重定位操作:

// 关联cmd和管道
        si.hStdError = hWriteStdin;
        si.hStdOutput = hWriteStdin;
        si.hStdInput = hReadStdout;
        si.wShowWindow = SW_HIDE;
        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;

可以看到通过重定位,把cmd.exe进程的输出以及错误的输出都定位到了Pipe1的写句柄hWriteStdin上,那么只要是cmd的输出都会直接写入到Pipe1中;而cmd的输入就定位到了Pipe2上的hReadStdout句柄上,这样,管道Pipe2中的数据会被cmd进程当做输入。这样的话,我们对管道的另一端进行写入和读取的话,就相当于直接对cmd进程进行传递命令和获取命令反馈的消息了。那么这样就实现了远程交互的cmd。


那么现在,重点就来了,有很多细节需要进行处理了。

我们如何知道管道中有数据可以进行读取?

在使用ReadFile读取管道数据的时候会出现阻塞的情况,这就是ReadFile这个函数的缺陷,在管道中没有数据的话那么它也一直处于阻塞状态并不会返回。要解决这个问题,网上很多前辈都说在读取之前关闭管道的写句柄,那么在ReadFile的时候就不会因为管道中没有数据而不返回,因为关闭写句柄后就相当于告诉系统管道在读取完最后的数据后就会关闭,那么Readfile后就不会阻塞了。但是这样的话就实现不了一个交互的cmd,因为没有保存写句柄,这样的话下次就不知往哪里写了。

找到的一种解决方法就是通过使用函数PeekNamedPipe来进行判断管道中的数据情况,这个函数可以返回管道中数据的字节数,进行的操作是拷贝管道中的数据,而不是Readfile这个函数的拷贝后清除的操作。

通过返回的数目,判断是否为0,为0就退出此次的接收。

// 从管道中取出数据
    while (true)
    {
        // 获取管道中数据的大小
        PeekNamedPipe(hReadStdin, szTmp, 1024, &dwRead, NULL, NULL);
        if (0 == dwRead)
        {
            break;
        }
        ReadFile(hReadStdin, szTmp, 1024, &dwRead, NULL);
        memcpy( szRecvPipeBuffer + dwSum  , szTmp , dwRead ) ;
        dwSum += dwRead ;
        memset( szTmp , 0 , sizeof( szTmp ) ) ;
    }


在实际的过程中又出现了一个问题,通过调试发现,在往管道中写入数据后,从管道中并没有取出数据,但是调试的结果是对的,运行确错误,我我就发现往管道写数据后使用Sleep(500)就就可以解决问题,这是因为,给cmd发送命令后假如不等待的话,cmd进程也没有准备好数据,而我们就直接从管道中去取数据,这样肯定是去取不出数据的。现在的疑问使用Sleep函数感觉有些不当。是不是还可以用其他的方式来解决呢?


还需要注意的问题就是:

(1)发送的命令需要加行‘"\r\n"这个,毕竟在cmd输入命令后是需要按enter的。

(2)最后cmd结束的时候如何CloseHandle这几个句柄呢?


最后列出帮我解决问题的几个重要链接:

http://www.cnblogs.com/boyxiao/archive/2011/01/02/1924188.html


http://www.myexception.cn/vc-mfc/850686.html


http://www.cnblogs.com/thankgoodness/articles/1762596.html


http://msdn.microsoft.com/en-us/library/windows/desktop/aa365779%28v=vs.85%29.aspx

猜你喜欢

转载自blog.csdn.net/bobopeng/article/details/40395109
今日推荐