CreatePipe、CreateProcess函数

CreatePipe、CreateProcess函数0x01.CreatePipe函数管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另一进程就可以从管道的另一端将其读取出来。匿名管道(AnonymousPipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。先详细介绍一下管道,这里以匿名管道为

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

0x01.CreatePipe函数

管 道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另 一进程就可以从管道的另一端将其读取出来。匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。

先详细介绍一下管道,这里以匿名管道为例:
第一:匿名管道只能实现本地进程之间的通信,不能实现跨网络之间的进程间的通信。
第二:匿名管道只能实现父进程和子进程之间的通信,而不能实现任意两个本地进程之间的通信。

创建管道函数原型:

BOOL WINAPI CreatePipe(
  _Out_    PHANDLE               hReadPipe,
  _Out_    PHANDLE               hWritePipe,
  _In_opt_ LPSECURITY_ATTRIBUTES lpPipeAttributes,
  _In_     DWORD                 nSize
);

返回值

如果函数成功,返回值不为零。
如果函数失败,返回值为零。要获取扩展错误信息,请调用GetLastError。

备注

CreatePipe创建管道,将指定的管道大小分配给存储缓冲区。 CreatePipe还会在随后的ReadFileWriteFile函数调用中创建该进程用于读取和写入缓冲区的句柄。
要从管道读取,一个进程在调用ReadFile函数时使用读取句柄。当以下任一条件为真时,ReadFile返回:写操作在管道的写入端完成,请求的字节数已被读取或发生错误。
当一个进程使用WriteFile写入匿名管道时,写操作在所有字节都被写入之前不会完成。如果在写入所有字节之前管道缓冲区已满,则WriteFile不会返回,直到另一个进程或线程使用ReadFile来创建更多的缓冲区空间。
使用具有唯一名称的命名管道实现匿名管道。因此,您经常可以将匿名管道的句柄传递给需要命名管道句柄的函数。
如果CreatePipe失败,输出参数的内容是不确定的。在这个事件中,不应该假设他们的内容。
要释放管道使用的资源,应用程序应该不再需要关闭句柄,这可以通过调用CloseHandle函数或与实例句柄关联的进程结束。请注意,管道的一个实例可能有多个与之关联的句柄。当命名管道的实例的最后一个句柄关闭时,管道的实例总是被删除。

0x02、CreateProcess

创建一个新进程及其主要线程。新进程在调用进程的安全上下文中运行。

BOOL WINAPI CreateProcess(
  _In_opt_    LPCTSTR               lpApplicationName,
  _Inout_opt_ LPTSTR                lpCommandLine,
  _In_opt_    LPSECURITY_ATTRIBUTES lpProcessAttributes,
  _In_opt_    LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_        BOOL                  bInheritHandles,
  _In_        DWORD                 dwCreationFlags,
  _In_opt_    LPVOID                lpEnvironment,
  _In_opt_    LPCTSTR               lpCurrentDirectory,
  _In_        LPSTARTUPINFO         lpStartupInfo,
  _Out_       LPPROCESS_INFORMATION lpProcessInformation
);

0x03.example

#include <iostream>
#include <windows.h>
#include <Shlwapi.h>

using namespace std;

#define BUFSIZE 4096

int main()
{
    BOOL bRet = FALSE;
    DWORD dwRead = 0;
    DWORD dwAvail = 0;
    char cbBuf[4096] = { 0 };
    HANDLE hReadPipe = NULL;
    HANDLE hWritePipe = NULL;
    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;
    char *pCommandLine = new TCHAR[0x200];//
    char szPath[] = "C:\\Windows\\System32\\calc.exe";
    CreatePipe(&hReadPipe, &hWritePipe, &sa, 0);
    STARTUPINFO si = { 0 };
    si.cb = sizeof(STARTUPINFO);
    GetStartupInfo(&si);
    si.wShowWindow = SW_HIDE;
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    si.hStdError = hWritePipe;
    si.hStdOutput = hWritePipe;
    PROCESS_INFORMATION   pi = { 0 };

    memset(pCommandLine, 0, sizeof(szPath));
    lstrcpy(pCommandLine, szPath);

    if (!CreateProcess(NULL, pCommandLine, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi))//创建子进程
    {
        if (pCommandLine)
            delete pCommandLine;

        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        CloseHandle(hReadPipe);
        CloseHandle(hWritePipe);

        return 1;
    }
    std::string strResult;
    do
    {
        cout << "test.." << endl;
        if (!PeekNamedPipe(hReadPipe, NULL, NULL, &dwRead, &dwAvail, NULL) || dwAvail <= 0)//PeekNamePipe用来预览一个管道中的数据,用来判断管道中是否为空
        {
             break;
         }
        if (ReadFile(hReadPipe, cbBuf, BUFSIZE, &dwRead, NULL))//这里是读管道,即便已经没有数据,仍然会等待接收数据,因为,子进程会认为父进程仍有数据要发送,只是暂时没法送,
        {                                                        //所以,会“卡”在这里。所以才需要PeekNamePipe
            if (dwRead == 0)
                break;
            cout << dwRead << endl;
            cout << cbBuf << endl;
        }
    } while (TRUE);

    if (pCommandLine)
        delete pCommandLine;
    cout << "delete" << endl;
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    CloseHandle(hReadPipe);
    CloseHandle(hWritePipe);

    return 0;
}

例二:

直接程序放入主程序:

    HANDLE hRead,hWrite;
    SECURITY_ATTRIBUTES sa;    
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);    
    sa.lpSecurityDescriptor = NULL; //使用系统默认的安全描述符 
    sa.bInheritHandle = TRUE; //创建的进程继承句柄

    if (!CreatePipe(&hRead,&hWrite,&sa,0)) //创建匿名管道
    {        
        MessageBox("CreatePipe Failed!","提示",MB_OK | MB_ICONWARNING);        
        return;
    }

    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;


    char cmdline[200]; 
    CString tmp,stredit2;
    GetDlgItemText(IDC_EDIT2,stredit2); //获取编辑框中输入的命令行
    tmp.Format("cmd /C %s",stredit2);
    sprintf(cmdline,"%s",tmp);

    if (!CreateProcess(NULL,cmdline,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi)) //创建子进程
    {
        MessageBox("CreateProcess Failed!","提示",MB_OK | MB_ICONWARNING);        
        return;
    }
    CloseHandle(hWrite); //关闭管道句柄

    char buffer[4096] = {
  
  0};
    CString strOutput;
    DWORD bytesRead;

    while (true) 
    {
        if (ReadFile(hRead,buffer,4095,&bytesRead,NULL) == NULL) //读取管道
            break;

        strOutput += buffer;
        SetDlgItemText(IDC_EDIT1,strOutput); //显示输出信息到编辑框,并刷新窗口
        UpdateWindow();
        Sleep(100);
    }
    CloseHandle(hRead);
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/159395.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • typora 免费版, 最后一个beta版本下载[通俗易懂]

    typora 免费版, 最后一个beta版本下载[通俗易懂]连接为官方下载链接,直接复制MD5可迅雷下载亲测可用,和付费版使用体验无差别.1.Windows64bithttps://download.typora.io/windows/typora-setup-x64-0.11.18.exeMD5:12F96372BEE2951ACF5627EA28F8A389**2.Window32bit**https://download.typora.io/windows/typora-setup-ia32-0.11.18.exeMD5:F5036

    2022年10月12日
    4
  • idea配置springboot热部署终极解决办法,解决热部署失效问题

    idea配置springboot热部署终极解决办法,解决热部署失效问题idea配置springboot热部署终极解决办法,解决热部署失效问题1.添加maven依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</a…

    2022年5月21日
    106
  • Android Studio 简单生成so文件并调用「建议收藏」

    Android Studio 简单生成so文件并调用「建议收藏」平台:windowsIDE:AndroidStudio下载好ndk:下载地址https://developer.android.com/ndk/downloads/index.html第1步:新建一个AndroidStudio工程JniHelloWorld。新建一个MyJni.java文件。MyJni.javapublicclassMyJni

    2022年9月19日
    2
  • SMO算法最通俗易懂的解释

    SMO算法最通俗易懂的解释我的机器学习教程「美团」算法工程师带你入门机器学习已经开始更新了,欢迎大家订阅~任何关于算法、编程、AI行业知识或博客内容的问题,可以随时扫码关注公众号「图灵的猫」,加入”学习小组“,沙雕博主在线答疑~此外,公众号内还有更多AI、算法、编程和大数据知识分享,以及免费的SSR节点和学习资料。其他平台(知乎/B站)也是同名「图灵的猫」,不要迷路哦~SVM通常用对偶问题来求解,这…

    2022年6月30日
    25
  • 功能测试数据测试之因果图分析方法[通俗易懂]

    功能测试数据测试之因果图分析方法[通俗易懂]定义是一种利用图解法分析输入的各种组合情况,从而设计测试用例的方法,它适合于检查程序输入条件的各种组合情况。因果图法产生的背景等价类划分法和边界值分析方法都是着重考虑输入条件,但没有考虑输入条件的各种组合、输入条件之间的相互制约关系。这样虽然各种输入条件可能出错的情况已经测试到了,但多个输入条件组合起来可能出错的情况却被忽视了。如果在测试时必须考虑输入条件的各种组合,则可能的组合数目将是天文数字,因此必须考虑采用一种适合于描述多种条件的组合、相应产生多个动作的形式来进行测试用例的设计,这就需要利用

    2022年8月14日
    5
  • webstorm安装使用教程

    webstorm安装使用教程webstorm 安装教程

    2025年9月19日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号