我想用WriteConsoleInput这类的低级别api来操纵控制台,编写shell服务器,目前实现了一个客户端,如有多个客户端连接,服务进程创建的每个子cmd进程访问标准输入会有冲突,请问如何创建另外的输入缓冲区供子进程使用,并且还能使用WriteConsoleInput这类api?已经知道CreatePipe创建的管道不可以,它只能用WriteFile写入字符内容。

解决方案 »

  1.   

    把运行情况在描述具体一些。客户端是什么意思?是cmd进程吗?
      

  2.   

    服务器创建CMD.EXE子进程,客户端通过网络连接使用,就是终端SHELL,网络通信没有问题,现在就是卡在服务端编程上,服务端只有一个进程,可能创建多个CMD.EXE系统子进程,屏幕输出可以使用CreateConsoleScreenBuffer做到各个CMD.EXE进程互不影响,可是用WriteConsoleInput会有问题,多个CMD.EXE之间会有冲突,不能单独写入指定的CMD.EXE子进程中,具体现象是这次输入被子进程A处理,则下次B会接到输入...。
    因为现在多个CMD.EXE子进程是共享父进程标准输入的,所以有这个现象。能不能通过类似CreateConsoleScreenBuffer之类的方式,创建另外的句柄传给cmd.exe子进程(也就是输入重定向但要求能使用WriteConsoleInput,或者不让子进程继承标准输入编程得到其标准输入操作),我试了CreatePipe不行,创建的句柄只能通过WriteFile写入字符流.
      

  3.   

    MSDN里面有一些文档可以看看,方法是利用CreateProcess的 LPSTARTUPINFO 参数,
    设置dwFlags为STARTF_USESTDHANDLES:
    然后自定义:
    HANDLE  hStdInput; 
    HANDLE  hStdOutput; 
    HANDLE  hStdError; 
    三个流句柄。
    这些句柄可以用CreatePipe创建的匿名管道句柄代替:
    BOOL CreatePipe(
      PHANDLE hReadPipe,                       // read handle
      PHANDLE hWritePipe,                      // write handle
      LPSECURITY_ATTRIBUTES lpPipeAttributes,  // security attributes
      DWORD nSize                              // pipe size
    );
    其中hStdOutput,hStdError传给hWritePipe,hStdInput传给hReadPipe,然后把管道的另一端的句柄保存起来。就可以用ReadFile/WriteFile从这些句柄读取/写入控制台程序的输出/输入。
    要注意的是这些句柄的继承性,调用CreateProcess时注意设置BOOL bInheritHandles = TRUE,使它可以继承主进程的句柄。调用CreatePipe要设置LPSECURITY_ATTRIBUTES lpPipeAttributes参数使Pipe的句柄能够被继承。
    此外,这样使CreatePipe创建的两个句柄都可以被继承了,所以要调用DuplicateHandle把不需要传入子进程的句柄设置为不可继承。不然子进程拥有了另一个句柄但是不会调用Closehandle减少引用记数,会导致Pipe不能被在使用完毕后被撤消。
    此外注意关闭所有使用过的内核对象句柄。