#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h> int Call(char Cmd[])
{
SECURITY_ATTRIBUTES sa;
HANDLE Hread,Hwrite;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
if (!CreatePipe(&Hread,&Hwrite,&sa,0))
{
printf("Create Pipe in error\r\n");
return 0;
} STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = Hwrite;
si.hStdOutput = Hwrite;
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
memset(&pi,0,sizeof(PROCESS_INFORMATION));
char cmdline[1024 ] = "cmd /c";
strcat(cmdline,Cmd);
if (!CreateProcessA(NULL,cmdline,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi))
{
printf("Create process error\r\n");
return 0;
} CloseHandle(Hwrite); char buff[1024] = {0};
//char cres[MAX_PATH] = {0};
DWORD bytesread;
while (true)
{
if (ReadFile(Hread,buff,1024,&bytesread,NULL) == NULL)
{
break;
} int ilen = strlen(buff);
for (int i =0;i<ilen;i++)
{
if (buff[i] == '\n' || buff[i] == '\r')
{
buff[i] = '\0';
}
}
printf(buff);
}
CloseHandle(Hread);
//sprintf() return 0;
} int _tmain(int argc, _TCHAR* argv[])
{
char* Cmd = argv[1];
Call(Cmd);
return 0;
} 使用管道CREATEPIPE,来进行进程间的相互通信,然后在进行数据的读取。 什么是管道,管道就是一种通信机制,也就是内存共享,一个进程向管道写入数据后,由另外一个管道读出。  匿名管道是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。

匿名管道由CreatePipe()函数创建,该函数在创建匿名管道的同时返回两个句柄:管道读句柄和管道写句

柄。CreatePipe()的函数原型为:
BOOL CreatePipe(
      PHANDLE hReadPipe,    // 指向读句柄的指针
   PHANDLE hWritePipe, &nb sp;  // 指向写句柄的指针
   LPSECURITY_ATTRIBUTES lpPipeAttributes,  // 指向安全属性的指针
   DWORD nSize     // 管道大小
  );   
返回值   
Long,非零表示成功,零表示失败。会设置GetLastError

在调用CreatePipe()函数时,如果管道服务器将lpPipeAttributes 指向的SECURITY_ATTRIBUTES数据结构的数据成员bInheritHandle设置为TRUE,那么CreatePipe()创建的管道读、写句柄将会被继承。
    在用WriteFile()函数向管道写入数据时,只有在向管道写完指定字节的数据后或是在有错误发生时函数才会返回。如管道缓冲已满而数据还没有写完,WriteFile()将要等到另一进程对管道中数据读取以释放出更多可用空间后才能够返回。管道服务器在调用CreatePipe()创建管道时以参数nSize对管道的缓冲大小作了设定。
  匿名管道并不支持异步读、写操作,这也就意味着不能在匿名管道中使用ReadFileEx()和WriteFileEx(),而且ReadFile()和WriteFile()中的lpOverLapped参数也将被忽略。匿名管道将在读、写句柄都被关闭后退出,也可以在进程中调用CloseHandle()函数来关闭此句柄。

程序具体实现过程:
(1) 初始化安全属性的指针 //创建匿名管道前期,就得初始化安全属性的指针。
 SECURITY_ATTRIBUTES sa;
 sa.nLength = sizeof(sa);
 sa.lpSecurityDescriptor = 0;
 sa.bInheritHandle = TRUE;

(2) 创建匿名管道 //开始创建匿名管道
 HANDLE hReadPipe1,hWritePipe1;
 CreatePipe(&hReadPipe1,&hWritePipe1,&sa,0);

(3) 创建cmd进程
BOOL CreateProcess(   
 LPCTSTR lpApplicationName,      //可执行模块的字符串 
 LPTSTR lpCommandLine,      //执行的命令行字符串
 LPSECURITY_ATTRIBUTES lpProcessAttributes, 
 LPSECURITY_ATTRIBUTES lpThreadAttributes,   
 BOOL bInheritHandles,      //新进程是否从调用进程处继承了句柄
 DWORD dwCreationFlags,      //标志
 LPVOID lpEnvironment,      //新进程的环境块
 LPCTSTR lpCurrentDirectory,     //子进程的工作路径
 LPSTARTUPINFO lpStartupInfo,     //决定新进程的主窗体如何显示
 LPPROCESS_INFORMATION lpProcessInformation  //接收新进程的识别信息
  );

在创建进程前,先初始化两个结构体:LPSTARTUPINFO 和LPPROCESS_INFORMATION

STARTUPINFO结构用于指定新进程的主窗口特性,应用程序必须将cb初始化为sizeof(STARTUPINFO)
STARTF_USESHOWWINDOW使用wShowWindow成员:wShowWindow用于设定如果子应用程序初次调用的ShowWindows将SW_SHOWDEFAULT作为nCmdShow参数传递时,该应用程序的第一个重叠窗口应该如何出现。
STARTF_USESTDHANDLES使用hstdInput、hstdOutput和hstdError成员:HANDLE hStdInput用于设定供控制台输入和输出用的缓存的句柄。按照默认设置,hstdInput 用于标识键盘缓存,hstdOutput和hstdError用于标识控制台窗口的缓存。

STARTUPINFO si;
 memset(&si,0,sizeof(si));
 GetStartupInfo(&si);  //该函数返回进程在启动时被指定的STARTUPINFO 结构
 si.cb = sizeof(si);
 si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
 si.wShowWindow = SW_HIDE;
 si.hStdOutput = si.hStdError = hWritePipe1;

PROCESS_INFORMATION pInfo;
 memset(&pInfo,0,sizeof(PROCESS_INFORMATION));

创建进程
 char szCmd[MAXLENGTH] = "cmd.exe /c";
 //接收远程传入的进程执行参数
 int dwSize = ((RatProto*)szRecvCmd)->RatLen - sizeof(RatProto);
 strncat(szCmd,szRecvCmd+sizeof(RatProto),dwSize);
 CreateProcessA(NULL,szCmd,NULL,NULL,1,0,NULL,NULL,&si,&pInfo);

(3) 通过管道通信,得到进程执行结果
 memset(szCmd,0,MAXLENGTH);
 int dwRead;
 //判断管道内是否有传入数据
 int nRet = PeekNamedPipe(hReadPipe1,szCmd,MAXLENGTH,(LPDWORD)&dwRead,NULL,NULL);
 for (int i=0;i<5&&dwRead==0;i++)
 {
  Sleep(100);
  nRet = PeekNamedPipe(hReadPipe1,szCmd,MAXLENGTH,(LPDWORD)&dwRead,NULL,NULL);
 }

if (dwRead)
 {
  nRet = ReadFile(hReadPipe1,szCmd,dwRead,(LPDWORD)&dwRead,0);
  if (!nRet)
  {
   sprintf(szCmd,"%s","CMD COMMAND EXCUTE ERROR!");
  }  
 }

(4) 将执行结果传给客户端
 .......

VC 模拟CMD 匿名管道的更多相关文章

  1. 匿名管道读取CMD回显信息

    之前用了很坑爹的做法去读取了cmd命令的回显信息,现在发现了用匿名管道的实现方法,由于楼主没有学过Windows核心编程,找了一个代码来凑数 存下来以后研究 #include <windows. ...

  2. 通过匿名管道获取CMD运行结果

    #include <iostream> #include <string> #include <Windows.h> using namespace std; /* ...

  3. Windows下 C++ 实现匿名管道的读写操作

    由于刚弄C++没多久,部分还不熟练,最近又由于开发需求要求实现与其他程序进行通信,瞬间就感觉想到了匿名通信.于是自己查阅了一下资料,实现了一个可读可写的匿名管道: 源代码大部分都有注释: Pipe.h ...

  4. 使用匿名管道在进程间通信 (System.IO.Pipes使用)(转)

    原文地址:http://www.cnblogs.com/yukaizhao/archive/2011/08/04/system-io-pipes.html 管道的用途是在同一台机器上的进程之间通信,也 ...

  5. C语言通过匿名管道实现反弹式CMDShell

    #pragma comment(lib,"ws2_32.lib") #ifdef _MSC_VER #pragma comment( linker, "/subsyste ...

  6. Windows进程通信之一看就懂的匿名管道通信

    目录 进程通信之一看就懂的匿名管道通信 一丶匿名管道 1.1何为匿名管道 1.2创建匿名管道需要注意的事项 1.3 创建匿名管道需要的步骤 1.4代码例子 1.5代码运行截图 进程通信之一看就懂的匿名 ...

  7. 进程通信类型 管道是Linux支持的最初Unix IPC形式之一 命名管道 匿名管道

    管道 Linux环境进程间通信(一) https://www.ibm.com/developerworks/cn/linux/l-ipc/part1/index.html 管道及有名管道 郑彦兴200 ...

  8. Linux学习笔记(12)-进程间通信|匿名管道

    Linux的进程间通信有几种方式,包括,管道,信号,信号灯,共享内存,消息队列和套接字等-- 现在一个个的开始学习! ----------------------------------------- ...

  9. Linux进程间通信(三):匿名管道 popen()、pclose()、pipe()、close()、dup()、dup2()

    在前面,介绍了一种进程间的通信方式:使用信号,我们创建通知事件,并通过它引起响应,但传递的信息只是一个信号值.这里将介绍另一种进程间通信的方式——匿名管道,通过它进程间可以交换更多有用的数据. 一.什 ...

随机推荐

  1. hoj 2715 (费用流 拆点)

    http://acm.hit.edu.cn/hoj/problem/view?id=2715 将每个格子 i 拆成两个点 i’, i’’并加边(i’, i’’, 1, -Vi), (i’, i’’, ...

  2. LibSvm添加到Matlab

    1.下载libSVM工具包 http://pan.baidu.com/s/1bnGNTBT或者下载最新版的到http://www.csie.ntu.edu.tw/~cjlin/libsvm/ 2.解压 ...

  3. javascript基础(整理自手册网)

    变量 person=null; //清空变量 carname="Volvo"; //赋值给未声明的变量, 它将会变成全局变量, 即使在函数内部 window.carnam; //所 ...

  4. python系列六:Python3元组tuple

    '''元组与列表类似,不同之处在于元组的元素不能修改.元组使用小括号,列表使用方括号.''''''uple元素不可变有一种特殊情况,当元素是可变对象时.对象内部属性是可以修改的!tuple的不可变限制 ...

  5. Arcgis server服务启动后停止

    ---恢复内容开始--- 重新按装server10.1,10sp1和10.2 易出现服务无法启动.在管理中手动启动服务,出现如图1所示的错误. 图1 错误信息 本人多次遇到用户反馈这问题,最初以为是因 ...

  6. 如何生成动态库 .dll 的符号 .lib 文件?

    在知道拥有动态库和头文件的情况下,但没有动态库符号文件的情况下,如何静态链接动态库? 1.使用 Microsoft Visual Studio Tools 命令行命令生成 xxx.def 文件,进而使 ...

  7. Java基础—数据类型

    Java的两大数据类型 基本数据类型 引用类型 Java程序中,new出来的对象存储在堆中(引用类型),但当使用new创建一个小的.简单的对象时,往往不是很有效,所以对于这些类型,Java不用new来 ...

  8. Python常见序列详解

    一.Python中序列的分类 常见序列类型包括字符串(普通字符串和unicode字符串),列表和元组.所谓序列,即成员有序排列,可通过下标访问. 二.Python序列通用操作 下面我们将分别以字符串. ...

  9. Autonomous System

        自治系统(Autonomous System).在互联网中,一个自治系统(AS)是一个有权自主地决定在本系统中应采用何种路由协 议的小型单位.这个网络单位可以是一个简单的网络也可以是一个由一个 ...

  10. bootstrap-select 使用笔记 设置选中值及手动刷新

    直接笔记: 1.页面刚加载完填充select选项数据时,需要手动刷新一下组件,否则没有选项值.(组件初始化时,li 与 option 分离的,需要刷新一下(据说)) $.post('/cpms/tod ...