管道 命名管道
匿名管道-父子进程之间的数据传输
创建:CreatePipe
读:ReadFile
写:WriteFile
获取句柄:GetStdHandle
查看管道是否有数据可读:PeekNamedPipe
新建两个MFC应用程序
ParentDlg.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #pragma once class CParentDlg : public CDialogEx{ public: CParentDlg(CWnd* pParent = nullptr); #ifdef AFX_DESIGN_TIME enum { IDD = IDD_PARENT_DIALOG }; #endif protected: virtual void DoDataExchange (CDataExchange* pDX) ; protected: HICON m_hIcon; HANDLE m_hRead = NULL ; HANDLE m_hWrite = NULL ; virtual BOOL OnInitDialog () ; afx_msg void OnSysCommand (UINT nID, LPARAM lParam) ; afx_msg void OnPaint () ; afx_msg HCURSOR OnQueryDragIcon () ; DECLARE_MESSAGE_MAP() public: afx_msg void OnBnClickedButton1 () ; afx_msg void OnBnClickedButton2 () ; };
ParentDlg.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 void CParentDlg::OnBnClickedButton1 () { BOOL bRet = ::CreatePipe(&m_hRead, &m_hWrite, NULL , 0 ); if (!bRet) { AfxMessageBox("创建管道失败" ); return ; } STARTUPINFO si = {}; si.cb = sizeof (si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = m_hRead; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof (pi)); if (!CreateProcess(NULL , "Child.exe" , NULL , NULL , TRUE, 0 , NULL , NULL , &si, &pi) ) { printf ("CreateProcess failed (%d).\n" , GetLastError()); return ; } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); }
修改Child的输出路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 void CChildDlg::OnBnClickedButton1 () { HANDLE hInput = ::GetStdHandle(STD_INPUT_HANDLE); DWORD dwBytesAvail = 0 ; BOOL bRet = ::PeekNamedPipe(hInput, NULL , 0 , NULL , &dwBytesAvail, NULL ); if (!bRet) { AfxMessageBox("无法查看管道剩余数据" ); return ; } if (dwBytesAvail > 0 ) { CString strBuf; DWORD dwBytesToRead = 0 ; BOOL bRet = ::ReadFile( hInput, strBuf.GetBufferSetLength(MAXBYTE), MAXBYTE, &dwBytesToRead, NULL ); if (!bRet) { AfxMessageBox("读取数据失败" ); return ; } strBuf.ReleaseBuffer(dwBytesToRead); SetDlgItemText(EDT_READ, strBuf); } }
运行Parent,点击创建子进程,则可以创建一个Child进程
在Parent里面写入数据,然后子进程可以读取数据
新建句柄
修改编辑框设置
ParentDlg.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 void CParentDlg::OnBnClickedButton3 () { SECURITY_ATTRIBUTES sa = {}; sa.nLength = sizeof (sa); sa.bInheritHandle = TRUE; ::CreatePipe(&m_hSelfRead, &m_hCmdWrite, &sa, 0 ); ::CreatePipe(&m_hCmdRead, &m_hSelfWrite, &sa, 0 ); STARTUPINFO si = {}; si.cb = sizeof (si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = m_hCmdRead; si.hStdOutput = m_hCmdWrite; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof (pi)); if (!CreateProcess(NULL , "cmd.exe" , NULL , NULL , TRUE, 0 , NULL , NULL , &si, &pi) ) { printf ("CreateProcess failed (%d).\n" , GetLastError()); return ; } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } void CParentDlg::OnBnClickedButton4 () { CString strBuf; GetDlgItemText(EDT_COMD, strBuf); strBuf += "\r\n" ; BOOL bRet = WriteFile(m_hSelfWrite, strBuf.GetBuffer(), strBuf.GetLength(), NULL , NULL ); if (!bRet) { AfxMessageBox("写入管道失败" ); } } void CParentDlg::OnBnClickedButton5 () { DWORD dwBytesAvail = 0 ; BOOL bRet = ::PeekNamedPipe(m_hSelfRead, NULL , 0 , NULL , &dwBytesAvail, NULL ); if (!bRet) { AfxMessageBox("无法查看管道剩余数据" ); return ; } if (dwBytesAvail > 0 ) { CString strBuf; DWORD dwBytesToRead = 0 ; BOOL bRet = ::ReadFile( m_hSelfRead, strBuf.GetBufferSetLength(MAXBYTE), MAXBYTE, &dwBytesToRead, NULL ); if (!bRet) { AfxMessageBox("读取数据失败" ); return ; } strBuf.ReleaseBuffer(dwBytesToRead); SetDlgItemText(EDT_SHOW, strBuf); } }
分析:
1 2 3 4 5 6 7 8 9 ::CreatePipe(&m_hSelfRead, &m_hCmdWrite, &sa, 0 ); ::CreatePipe(&m_hCmdRead, &m_hSelfWrite, &sa, 0 ); STARTUPINFO si = {}; si.cb = sizeof (si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = m_hCmdRead; si.hStdOutput = m_hCmdWrite;
第一个管道: ::CreatePipe(&m_hSelfRead, &m_hCmdWrite, &sa, 0);
m_hSelfRead
:父进程读取句柄。父进程通过这个句柄从管道中读取数据,即从子进程cmd.exe
的输出中读取数据
m_hCmdWrite
:子进程写入句柄。子进程通过这个句柄向管道中写入数据,即将cmd.exe
的输出写入管道
第二个管道: ::CreatePipe(&m_hCmdRead, &m_hSelfWrite, &sa, 0);
m_hCmdRead
:子进程读取句柄。子进程通过这个句柄从管道中读取数据,即从父进程输入的数据
m_hSelfWrite
:父进程写入句柄。父进程通过这个句柄向管道中写入数据,即将命令输入到cmd.exe
在STARTUPINFO
结构体中,si.hStdInput
和si.hStdOutput
应该分别设置为用于输入和输出的管道句柄,一编父进程可以通过这些句柄与子进程cmd.exe
进行通信。正确的设置方式如下:
si.hStdInput
:设置为子进程的读取句柄m_hCmdRead
(由句柄m_hSelfWrite写入,m_hCmdRead在子进程读出)这意味着子进程将从此管道中读取数据
si.hStdOutput
:设置为子进程的读取句柄m_hCmdWrite
(由句柄m_hCmdWrite写入,m_hSelfRead在父进程读出)这意味着子进程将把输出数据写入此管道
运行后点击启动cmd可以打开cmd窗口
点击读取回显可以读取cmd窗口的回显
输入命令后再读取回显可以读取cmd窗口输入命令后的回显
进程遍历 进程快照
创建快照:CreateToolhelp32Snapshot
GetDesktopwindow
GetChildWindow-GetnextWindow
第一个参数是保存快照的信息,第二个参数保存指定线程的信息
例子:Taking a Snapshot and Viewing Processes
新建控制台应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 #include <iostream> #include <windows.h> #include <TlHelp32.h> #include <stdio.h> BOOL GetProcessModule (DWORD dwPID, char * szExeName, LPMODULEENTRY32 lpMe32, DWORD cbMe32) { BOOL bRet = FALSE; BOOL bFound = FALSE; HANDLE hModuleSnap = NULL ; MODULEENTRY32 me32 = { 0 }; hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID); if (hModuleSnap == INVALID_HANDLE_VALUE) return (FALSE); me32.dwSize = sizeof (MODULEENTRY32); if (Module32First(hModuleSnap, &me32)) { do { if (strcmp (szExeName, me32.szModule) == 0 ) { CopyMemory(lpMe32, &me32, cbMe32); bFound = TRUE; } } while (!bFound && Module32Next(hModuleSnap, &me32)); bRet = bFound; } else bRet = FALSE; CloseHandle(hModuleSnap); return (bRet); } BOOL GetProcessList () { HANDLE hProcessSnap = NULL ; BOOL bRet = FALSE; PROCESSENTRY32 pe32 = { 0 }; hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0 ); if (hProcessSnap == INVALID_HANDLE_VALUE) { return (FALSE); } pe32.dwSize = sizeof (PROCESSENTRY32); if (Process32First(hProcessSnap, &pe32)) { DWORD dwPriorityClass; BOOL bGotModule = FALSE; MODULEENTRY32 me32 = { 0 }; do { bGotModule = GetProcessModule(pe32.th32ProcessID, pe32.szExeFile, &me32, sizeof (MODULEENTRY32)); if (bGotModule) { HANDLE hProcess; hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID); dwPriorityClass = GetPriorityClass(hProcess); CloseHandle(hProcess); printf ("PID\t\t\t%d\n" , pe32.th32ProcessID); printf ("Thread Count\t\t%d\n" , pe32.cntThreads); printf ("Module Name\t\t%s\n" , me32.szModule); printf ("Full Path\t\t%s\n\n" , me32.szExePath); } } while (Process32Next(hProcessSnap, &pe32)); bRet = TRUE; } else bRet = FALSE; CloseHandle(hProcessSnap); return (bRet); } int main () { GetProcessList(); std ::cout << "Hello World!\n" ; }
运行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 #include <iostream> #include <windows.h> #include <TlHelp32.h> #include <stdio.h> BOOL GetProcessModule (DWORD dwPID, char * szExeName, LPMODULEENTRY32 lpMe32, DWORD cbMe32) { BOOL bRet = FALSE; BOOL bFound = FALSE; HANDLE hModuleSnap = NULL ; MODULEENTRY32 me32 = { 0 }; hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID); if (hModuleSnap == INVALID_HANDLE_VALUE) return (FALSE); me32.dwSize = sizeof (MODULEENTRY32); if (Module32First(hModuleSnap, &me32)) { do { if (strcmp (szExeName, me32.szModule) == 0 ) { CopyMemory(lpMe32, &me32, cbMe32); bFound = TRUE; } } while (!bFound && Module32Next(hModuleSnap, &me32)); bRet = bFound; } else bRet = FALSE; CloseHandle(hModuleSnap); return (bRet); } BOOL GetProcessList () { HANDLE hProcessSnap = NULL ; BOOL bRet = FALSE; PROCESSENTRY32 pe32 = { 0 }; hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0 ); if (hProcessSnap == INVALID_HANDLE_VALUE) { return (FALSE); } pe32.dwSize = sizeof (PROCESSENTRY32); if (Process32First(hProcessSnap, &pe32)) { DWORD dwPriorityClass; BOOL bGotModule = FALSE; MODULEENTRY32 me32 = { 0 }; do { bGotModule = GetProcessModule(pe32.th32ProcessID, pe32.szExeFile, &me32, sizeof (MODULEENTRY32)); if (bGotModule) { HANDLE hProcess; hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID); dwPriorityClass = GetPriorityClass(hProcess); CloseHandle(hProcess); printf ("PID\t\t\t%d\n" , pe32.th32ProcessID); printf ("Thread Count\t\t%d\n" , pe32.cntThreads); printf ("Module Name\t\t%s\n" , me32.szModule); printf ("Full Path\t\t%s\n\n" , me32.szExePath); } } while (Process32Next(hProcessSnap, &pe32)); bRet = TRUE; } else bRet = FALSE; CloseHandle(hProcessSnap); return (bRet); } BOOL CALLBACK EnumWindowsProc (HWND hwnd, LPARAM lParam ) { char szBuff[MAXBYTE] = {}; GetWindowText(hwnd, szBuff, MAXBYTE); printf ("%s \r\n" , szBuff); return TRUE; } int main () { EnumWindows(EnumWindowsProc, NULL ); std ::cout << "Hello World!\n" ; }
运行结果