- UID
- 3260
- 精华
- 积分
- 648
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
匿名管道可以用来父进程与子进程通信,非父子关系的无法用匿名管道通信
匿名管道功能单一,使用简单,用很少代码即可。
我们用代码启动一个软件,那么被启动的软件成为我们软件的子进程了
准备工作:
- #include Once "fbthread.bi" '需要多线程
- Type PipeStruct '
- hPipeInputRead As HANDLE '数据输入管道
- hPipeInputWrite As HANDLE '数据输入管道
- hPipeOutputRead As HANDLE '数据输出管道
- hPipeOutputWrite As HANDLE '数据输出管道
- bConsole As PROCESS_INFORMATION '控制台
- End Type
- Dim Shared pipe As PipeStruct '保存管道的变量
复制代码
一、建立匿名管道,因为管道是单向的,要双向通信,必须建立2个
- Dim Sa As SECURITY_ATTRIBUTES
- With Sa '设置管道句柄安全属性
- .nLength = SizeOf(SECURITY_ATTRIBUTES)
- .bInheritHandle = True '必须为TRUE
- .lpSecurityDescriptor = 0
- End With
- '数据输入管道
- CreatePipe(@pipe.hPipeInputRead, @pipe.hPipeInputWrite, @sa, 0)
- '数据输出管道
- CreatePipe(@pipe.hPipeOutputRead, @pipe.hPipeOutputWrite, @sa, 0)
复制代码
二、启动子进程,以 CMD 为例题,当然可以是任意软件,而且隐藏掉软件,在背后偷偷运行
- Dim si As STARTUPINFO, CmdStr As String
- '设置进程的启动信息,这是一个输入参数
- si.cb = SizeOf(STARTUPINFO)
- GetStartupInfo(@si)
- si.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW '这个必须设置,否则仍将显示窗口
- si.hStdOutput = pipe.hPipeOutputWrite '输出由标准输出 -> 输出到管道
- si.hStdError = pipe.hPipeOutputWrite '输出由标准输出 -> 输出到管道
- Si.hStdInput = pipe.hPipeInputRead '输入由标准输入 -> 从管道中读取
- si.wShowWindow = SW_HIDE '隐藏子进程
- '使用刚才设置的各个参数创建隐秘的进程
- '此进程将把ping程序运行的结果写到管道
- CreateProcessA(Null, "CMD", Null, Null, True, Null, Null, Null, @Si, @pipe.bConsole)
复制代码
三、启动读取内容线程,不用多线程会发生堵塞。读取来自子进程,子读父,需要稍微改改即可
- Threaddetach ThreadCreate(Cast(Any Ptr, @PipeLineInput), @pipe) '读取无内容时线程会被挂起,因此必须用多线程
复制代码- Sub PipeLineInput(ByRef pipe As PipeStruct) '读取内容,的线程
- '从管道读取上述进程的输出,并显示于界面
- Dim bRet As WINBOOL, buffer As ZString * 1024, dwBytesRead As Long
- Dim BtRead As Long, BtTotal As Long, BtLeft As Long, OutData As String, ff As Long
- Dim tt As String
- Do
- bRet = ReadFile(pipe.hPipeOutputRead, @buffer, 1024, @dwBytesRead, Null)
- If bRet=0 Then Exit Do
- If dwBytesRead > 0 Then
- If Left(buffer,dwBytesRead)="终止引擎" Then Exit Do
- OutData &= Left(buffer,dwBytesRead)
- Do
- ff = InStr(OutData, vbCrLf)
- If ff = 0 Then Exit Do
- tt=FF_Control_GetText(HWND_FORM1_TEXT2) 此处要改,用于输出获取的内容
- ' Print Mid(OutData, 1, ff -1) 此处要改,用于输出获取的内容
- tt &=vbCrLf & Mid(OutData, 1, ff -1) 此处要改,用于输出获取的内容
- FF_Control_SetText HWND_FORM1_TEXT2,tt 此处要改,用于输出获取的内容
- OutData = Mid(OutData, ff + 2)
- Loop
- End If
- Sleep 100
- Loop
- ' Print "完成了........"
- End Sub
复制代码
四、发送内容,这里是父发给子的,子发给父的稍微改改即可,就是那个句柄
- Sub PipeLineOutput(ByRef pipe As PipeStruct, szLineStr As String) '发送
- Dim Buflen As Long, BtWritten As Long, rtn As Long
- rtn = WriteFile(pipe.hPipeInputWrite, StrPtr(szLineStr), Len(szLineStr), @BtWritten, Null)
- ' Print rtn, BtWritten
- End Sub
复制代码
五、关闭管道,结束子进程
- Sub PipeClose(ByRef pipe As PipeStruct) '关闭引擎
- Dim Buflen As Long, BtWritten As Long, rtn As Long, szLineStr As String
- szLineStr = "终止引擎" '为了让线程退出,只有退了,才可以终止引擎
- rtn = WriteFile(pipe.hPipeOutputWrite, StrPtr(szLineStr), Len(szLineStr), @BtWritten, Null)
- Sleep 10 '留给时间给线程退出
- CloseHandle pipe.hPipeInputRead
- CloseHandle pipe.hPipeInputWrite
- CloseHandle pipe.hPipeOutputRead
- CloseHandle pipe.hPipeOutputWrite
- CloseHandle pipe.bConsole.hThread
- CloseHandle pipe.bConsole.hProcess
- ProcessKill(pipe.bConsole.dwProcessId) 终止进程
- End Sub
复制代码
六、子进程获取父进程发来的管道句柄,有了句柄,在子进程里,仿照上面的写法,应该不难写出来吧。
- Print GetStdHandle(STD_INPUT_HANDLE) 'Si.hStdInput 用来读取父进程发来的内容
- Print GetStdHandle(STD_OUTPUT_HANDLE) 'si.hStdOutput 用来发送给父进程内容
- Print GetStdHandle(STD_ERROR_HANDLE) 'si.hStdError
复制代码
以上是为双向通信而写,假如单向,就只搞一个通道即可。
注:本例题源码下载,请进 B语言编程群:78458582 |
|