找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 1879|回复: 1

【VFB】进程通信之匿名管道

[复制链接]

51

主题

31

回帖

648

积分

用户组: 大·技术宅

UID
3260
精华
7
威望
12 点
宅币
506 个
贡献
1 次
宅之契约
0 份
在线时间
23 小时
注册时间
2017-12-26
发表于 2018-5-19 13:19:01 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
匿名管道可以用来父进程与子进程通信,非父子关系的无法用匿名管道通信

匿名管道功能单一,使用简单,用很少代码即可。

我们用代码启动一个软件,那么被启动的软件成为我们软件的子进程了

准备工作:
  1. #include Once "fbthread.bi"  '需要多线程
  2. Type PipeStruct '
  3.     hPipeInputRead As HANDLE   '数据输入管道  
  4.     hPipeInputWrite As HANDLE  '数据输入管道  
  5.     hPipeOutputRead As HANDLE   '数据输出管道  
  6.     hPipeOutputWrite As HANDLE  '数据输出管道  
  7.     bConsole As PROCESS_INFORMATION    '控制台
  8. End Type
  9. Dim Shared pipe As PipeStruct '保存管道的变量
复制代码

一、建立匿名管道,因为管道是单向的,要双向通信,必须建立2个
  1.   Dim Sa As SECURITY_ATTRIBUTES
  2.   With Sa '设置管道句柄安全属性
  3.       .nLength = SizeOf(SECURITY_ATTRIBUTES)
  4.       .bInheritHandle = True  '必须为TRUE
  5.       .lpSecurityDescriptor = 0
  6.   End With
  7.   '数据输入管道
  8.   CreatePipe(@pipe.hPipeInputRead, @pipe.hPipeInputWrite, @sa, 0)
  9.   '数据输出管道
  10.   CreatePipe(@pipe.hPipeOutputRead, @pipe.hPipeOutputWrite, @sa, 0)
复制代码

二、启动子进程,以 CMD 为例题,当然可以是任意软件,而且隐藏掉软件,在背后偷偷运行
  1.   Dim si As STARTUPINFO, CmdStr As String
  2.   '设置进程的启动信息,这是一个输入参数
  3.   si.cb = SizeOf(STARTUPINFO)
  4.   GetStartupInfo(@si)
  5.   si.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW '这个必须设置,否则仍将显示窗口
  6.   si.hStdOutput = pipe.hPipeOutputWrite '输出由标准输出 -> 输出到管道
  7.   si.hStdError = pipe.hPipeOutputWrite  '输出由标准输出 -> 输出到管道
  8.   Si.hStdInput = pipe.hPipeInputRead    '输入由标准输入 -> 从管道中读取
  9.   si.wShowWindow = SW_HIDE  '隐藏子进程
  10.   '使用刚才设置的各个参数创建隐秘的进程
  11.   '此进程将把ping程序运行的结果写到管道
  12.   CreateProcessA(Null, "CMD", Null, Null, True, Null, Null, Null, @Si, @pipe.bConsole)
复制代码

三、启动读取内容线程,不用多线程会发生堵塞。读取来自子进程,子读父,需要稍微改改即可
  1. Threaddetach ThreadCreate(Cast(Any Ptr, @PipeLineInput), @pipe) '读取无内容时线程会被挂起,因此必须用多线程
复制代码
  1. Sub PipeLineInput(ByRef pipe As PipeStruct) '读取内容,的线程
  2.   '从管道读取上述进程的输出,并显示于界面
  3.   Dim bRet As WINBOOL, buffer As ZString * 1024, dwBytesRead As Long
  4.   Dim BtRead As Long, BtTotal As Long, BtLeft As Long, OutData As String, ff As Long
  5.   Dim tt As String
  6.   Do
  7.       bRet = ReadFile(pipe.hPipeOutputRead, @buffer, 1024, @dwBytesRead, Null)
  8.       If bRet=0 Then Exit Do
  9.       If dwBytesRead > 0 Then
  10.          If Left(buffer,dwBytesRead)="终止引擎" Then Exit Do
  11.           OutData &= Left(buffer,dwBytesRead)
  12.           Do
  13.               ff = InStr(OutData, vbCrLf)
  14.               If ff = 0 Then Exit Do
  15.               tt=FF_Control_GetText(HWND_FORM1_TEXT2)  此处要改,用于输出获取的内容
  16. '              Print  Mid(OutData, 1, ff -1)           此处要改,用于输出获取的内容
  17.               tt &=vbCrLf & Mid(OutData, 1, ff -1)     此处要改,用于输出获取的内容
  18.               FF_Control_SetText HWND_FORM1_TEXT2,tt   此处要改,用于输出获取的内容
  19.               OutData = Mid(OutData, ff + 2)
  20.           Loop
  21.       End If
  22.       Sleep 100
  23.   Loop
  24. '  Print "完成了........"
  25. End Sub
复制代码

四、发送内容,这里是父发给子的,子发给父的稍微改改即可,就是那个句柄
  1. Sub PipeLineOutput(ByRef pipe As PipeStruct, szLineStr As String) '发送
  2.   Dim Buflen As Long, BtWritten As Long, rtn As Long
  3.   rtn = WriteFile(pipe.hPipeInputWrite, StrPtr(szLineStr), Len(szLineStr), @BtWritten, Null)
  4. '  Print rtn, BtWritten
  5. End Sub
复制代码

五、关闭管道,结束子进程
  1. Sub PipeClose(ByRef pipe As PipeStruct) '关闭引擎
  2.   Dim Buflen As Long, BtWritten As Long, rtn As Long, szLineStr As String
  3.   szLineStr = "终止引擎"  '为了让线程退出,只有退了,才可以终止引擎
  4.   rtn = WriteFile(pipe.hPipeOutputWrite, StrPtr(szLineStr), Len(szLineStr), @BtWritten, Null)
  5.   Sleep 10 '留给时间给线程退出
  6.   CloseHandle pipe.hPipeInputRead
  7.   CloseHandle pipe.hPipeInputWrite
  8.   CloseHandle pipe.hPipeOutputRead
  9.   CloseHandle pipe.hPipeOutputWrite
  10.   CloseHandle pipe.bConsole.hThread
  11.   CloseHandle pipe.bConsole.hProcess
  12.   ProcessKill(pipe.bConsole.dwProcessId) 终止进程
  13. End Sub
复制代码

六、子进程获取父进程发来的管道句柄,有了句柄,在子进程里,仿照上面的写法,应该不难写出来吧。
  1.   Print GetStdHandle(STD_INPUT_HANDLE)   'Si.hStdInput  用来读取父进程发来的内容
  2.   Print GetStdHandle(STD_OUTPUT_HANDLE)  'si.hStdOutput 用来发送给父进程内容
  3.   Print GetStdHandle(STD_ERROR_HANDLE)   'si.hStdError
复制代码

以上是为双向通信而写,假如单向,就只搞一个通道即可。

注:本例题源码下载,请进 B语言编程群:78458582  
回复

使用道具 举报

1

主题

159

回帖

624

积分

用户组: 大·技术宅

UID
7535
精华
0
威望
0 点
宅币
464 个
贡献
0 次
宅之契约
0 份
在线时间
71 小时
注册时间
2021-10-16
发表于 2022-5-17 10:19:52 | 显示全部楼层

珍惜生命,果断回帖。
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-4-19 20:21 , Processed in 0.034739 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表