技术宅的结界

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

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 118|回复: 0
收起左侧

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

[复制链接]

47

主题

67

帖子

590

积分

用户组: 大·技术宅

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

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

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

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

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

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

准备工作:
[Visual Basic] 纯文本查看 复制代码
#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个
[Visual Basic] 纯文本查看 复制代码
  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 为例题,当然可以是任意软件,而且隐藏掉软件,在背后偷偷运行
[Visual Basic] 纯文本查看 复制代码
  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)

三、启动读取内容线程,不用多线程会发生堵塞。读取来自子进程,子读父,需要稍微改改即可
[Visual Basic] 纯文本查看 复制代码
Threaddetach ThreadCreate(Cast(Any Ptr, @PipeLineInput), @pipe) '读取无内容时线程会被挂起,因此必须用多线程

[Visual Basic] 纯文本查看 复制代码
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

四、发送内容,这里是父发给子的,子发给父的稍微改改即可,就是那个句柄
[Visual Basic] 纯文本查看 复制代码
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

五、关闭管道,结束子进程
[Visual Basic] 纯文本查看 复制代码
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

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

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

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

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|技术宅的结界 ( 滇ICP备16008837号|网站地图

GMT+8, 2018-8-18 12:41 , Processed in 0.081466 second(s), 15 queries , Gzip On, Memcache On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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