日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

MFC匿名管道原理详解、函数总结、调用实例(用MFC的匿名管道读取CMD输出内容)(C++语言)

發布時間:2023/12/18 c/c++ 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MFC匿名管道原理详解、函数总结、调用实例(用MFC的匿名管道读取CMD输出内容)(C++语言) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本博客主要總結MFC中匿名管道的原理和具體調用實例,以及調用匿名管道三個核心函數各個參數用法詳解,具體的如下所述。

博主在做項目時,遇到一個問題。用程序調用一個進程,然后讀取進程輸出信息。但是,博主用Qt的QProcess無法讀取標準輸出,所以只能考慮管道技術。

由于博主的開發環境是Windows10 64位,Qt的QProcess并沒有找到類似的功能(可能博主對Qt研究不夠深入,希望知道的大神告知一下),所以打算用MFC的匿名管道。

經過資料的查找和驗證,博主發現,MFC的匿名管道技術可以實現讀取CMD進程輸出的內容,所以特定將MFC匿名管道用法記錄下來,學習和總結。

?

匿名管道概念解釋:

匿名管道主要用于進程間通信,進程的關系為父進程和子進程。具體原理如下圖所示:

父進程和子進程都有讀端口和寫端口。通信方式可以從父進程寫數據,子進程讀數據?;蛘咦舆M程寫數據,父進程讀數據。

其中,本文下面的例子是用圖二的從子進程寫數據,從父進程讀取數據。即子進程通過cmd命令執行程序,然后程序輸入的內容通過寫句柄hWritePipe,寫入內核(直接調用CrateProcess()函數,設置對應參數就可以寫數據到內核。而不用調用WriteFile()函數)。父進程根據子進程管道的讀句柄hReadPipe,調用ReadFile()函數讀取內核數據。

?

一、MFC創建管道主要步驟

用MFC編寫匿名管道的核心函數有三個,分別是CreatePipe(),CreateProcess(),ReadFile()三個核心函數。其中,函數CreatePipe()主要功能是創建一個管道通信,函數CreateProcess()主要功能是創建一個進程,函數ReadFile()讀取進程輸出的內容。下面是對創建管道通信步驟的總結:

?

1.1先創建調用函數CreatePipe()創建一個管道通信。關鍵代碼為:

CreatePipe(&hReadPipe, &hWritePipe, &safety, 0);
?

1.2調用函數CreateProcess()創建一個進程,該進程輸出的內容作為管道的寫端口,向管道寫數據。關鍵代碼為:(其中寫的句柄hWritePipe在結構體startInfo里的參數設置)

CreateProcess(NULL, cmdStr, NULL, NULL, TRUE, NULL, NULL, NULL, &startupInfo, &pinfo);
?

1.3調用函數ReadFile()作為管道的讀端口,讀取進程寫入管道的內容。關鍵代碼為:(其中讀取內存存在緩沖區buffer)

ReadFile(hReadPipe, buffer, 4095, &byteRead, NULL);
?

1.4下面是博主封裝的一個函數。該函數的功能是輸入cmd命令,返回cmd輸出內容。

具體代碼如下所示:

CString executeCmd(CString command)
{
?? ?//創建匿名管道
?? ?HANDLE hReadPipe, hWritePipe;
?? ?SECURITY_ATTRIBUTES safety;?? ??? ??? ??? ??? ??? ?//安全屬性?? ?
?? ?safety.nLength = sizeof(SECURITY_ATTRIBUTES);?? ?//結構體大小
?? ?safety.lpSecurityDescriptor = NULL;?? ??? ??? ??? ?//安全描述符,NULL;使用默認的
?? ?safety.bInheritHandle = TRUE;?? ??? ??? ??? ??? ?//安全描述符的對象能否被子進程繼承
?? ?if (!CreatePipe(&hReadPipe, &hWritePipe, &safety, 0))
?? ?{
?? ??? ?//創建管道錯誤
?? ??? ?return _T("創建管道錯誤!");
?? ?}

?? ?//創建進程
?? ?TCHAR *cmdStr = StringToChar(command);
?? ?STARTUPINFO startupInfo = { sizeof(startupInfo) };?? ??? ??? ??? ??? ?//進程信息?? ?
?? ?startupInfo.hStdError = hWritePipe;?? ??? ??? ??? ??? ??? ??? ??? ??? ?//標志控制臺窗口緩存
?? ?startupInfo.hStdOutput = hWritePipe;?? ??? ??? ??? ??? ??? ??? ??? ?//標志控制臺窗口緩存
?? ?startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;?? ?//使用wSHOWWIndows成員
?? ?startupInfo.wShowWindow = SW_HIDE;
?? ?PROCESS_INFORMATION pinfo;
?? ?if (!CreateProcess(NULL, cmdStr, NULL, NULL, TRUE, NULL, NULL, NULL, &startupInfo, &pinfo))
?? ?{
?? ??? ?//創建進程錯誤
?? ??? ?return _T("創建進程錯誤!");
?? ?}
?? ?CloseHandle(hWritePipe);

?? ?//獲取管道信息
?? ?char buffer[4096];?? ?
?? ?DWORD byteRead;
?? ?CString output;?? ??? ??? ??? ??? ??? ??? ??? ??? ?//返回值
?? ?while (true)
?? ?{
? ? ? ? memset(buffer, 0, 4096); ? ? ? ? ? ? ? ? ? ?//要放在循環里面,否則接收數據錯亂
? ? ? ? if (ReadFile(hReadPipe, buffer, 4095, &byteRead, NULL) == NULL)
?? ??? ?{
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?output += buffer;
?? ?}
?? ?CloseHandle(hReadPipe);

?? ?return output;
}
TCHAR* StringToChar(CString& str)
{
?? ?int len = str.GetLength();
?? ?TCHAR* tr = str.GetBuffer(len);
?? ?str.ReleaseBuffer();
?? ?return tr;
}
?

1.5函數調用的一個實例

? ? CString cmdString = _T("ipconfig.exe /?");
? ? CString output = executeCmd(cmdString);

? ? AfxMessageBox(output);
?

1.6運行結果如下圖所示:

二、關鍵函數參數講解

2.1函數CreatePipe()各個參數如下所示:

BOOL CreatePipe(
?? ?_Out_ PHANDLE hReadPipe,?? ?//管道讀端口句柄
?? ?_Out_ PHANDLE hWritePipe,?? ?//管道寫端口句柄
?? ?_In_opt_ LPSECURITY_ATTRIBUTES lpPipeAttributes,?? ?//安全描述符,通過設置參數,可以設置能否被支線程繼承
?? ?_In_ DWORD nSize ? ?//0表示管道緩沖設置為系統默認值
?? ?);
?

2.2函數CreateProcess()各個參數如下所示:

BOOL CreateProcess(
_In_opt_ LPCWSTR lpApplicationName,?? ??? ??? ??? ??? ?//指向要調用的程序路徑
_Inout_opt_ LPWSTR lpCommandLine,?? ??? ??? ??? ??? ?//輸入的命令行TCHAR*字符串
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,?? ?//結構體SECURTY_ATTRIBUTE,指向進程安全描述符
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,?? ?//結構體SECURITY_ATTRIBUTE,指向線程安全描述符
_In_ BOOL bInheritHandles,?? ??? ??? ??? ??? ??? ??? ?//新進程是否從調用進程處繼承了句柄
_In_ DWORD dwCreationFlags,?? ??? ??? ??? ??? ??? ??? ?//附加的、用來控制優先類和進程的創建標志。設置為CREATE_NEW_CONSOLE可顯示子窗口。
_In_opt_ LPVOID lpEnvironment,?? ??? ??? ??? ??? ??? ?//指向使用父類的環境
_In_opt_ LPCWSTR lpCurrentDirectory,?? ??? ??? ??? ?//使用父類的當前目錄
_In_ LPSTARTUPINFOW lpStartupInfo,?? ??? ??? ??? ??? ?//結構體STARTUPINFO,指向一個用于決定新進程的主窗體如何顯示
_Out_ LPPROCESS_INFORMATION lpProcessInformation?? ?//結構體PROCESS_INFORMATION,指向一個用來接收新進程的識別信息
);
?

2.3函數ReadFile()各個參數如下所示:

BOOL ReadFile(
_In_ HANDLE hFile,?? ??? ??? ??? ??? ??? ?//文件句柄
_Out_writes_bytes_to_opt_(nNumberOfBytesToRead, *lpNumberOfBytesRead) __out_data_source(FILE) LPVOID lpBuffer,?? ?//讀緩沖區
_In_ DWORD nNumberOfBytesToRead,?? ??? ?//要讀取的字節數
_Out_opt_ LPDWORD lpNumberOfBytesRead,?? ?//實際讀取到的字節數
_Inout_opt_ LPOVERLAPPED lpOverlapped?? ?//指向結構體OVERLAPPED,一般設為NULL
);
?

?

參考內容:

https://blog.csdn.net/it2153534/article/details/79064643(參考:重點函數各個參數講解)

https://blog.csdn.net/qq61394323/article/details/39829631(參考:MFC讀取CMD輸出內容代碼)

https://blog.csdn.net/qq61394323/article/details/39253193?utm_source=blogxgwz2(參考:匿名管道讀寫句柄用法)

https://blog.csdn.net/whynottrythis/article/details/39828395(參考:STARTUPINFO結構體各個參數講解)

https://blog.csdn.net/jeanphorn/article/details/44982273(參考:函數ReadFile()參數講解和調用實例,主要參考)

https://blog.csdn.net/virtualdesk/article/details/4379965(參考:函數ReadFile()參數講解和調用實例)

原文:https://blog.csdn.net/naibozhuan3744/article/details/83142860?
?

總結

以上是生活随笔為你收集整理的MFC匿名管道原理详解、函数总结、调用实例(用MFC的匿名管道读取CMD输出内容)(C++语言)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。