如何使用名为 Visual Basic 的 32 位程序中的管道

参考:http://support.microsoft.com/kb/177696/zh-cn


如何使用名为 Visual Basic 的 32 位程序中的管道

文章编号: 177696 -  查看本文应用于的产品
系统提示 注意:本篇文章的内容适用于其他版本的 Windows (不包括您正在使用的版本) 。本篇文章的内容可能不适用您的电脑。 浏览 Windows 7 帮助和支持中心

本页

概要

Visual Basic 可以创建与其他进程通信通过命名管道的应用程序。 必须在 Windows 2000 或 Windows NT ; 创建命名管道 但是,您可以读取和写入该管道从任何 32 位平台。

本文演示如何在 Visual Basic 中使用命名管道客户端/服务器通信。

更多信息

在本文中,创建命名管道的过程被称为服务器,并连接到命名管道的过程被称为客户端。

有六个步骤创建一个命名的管道服务器:
  1. 创建安全令牌管道允许对它 (以使通过创建安全令牌与自由访问控制列表 (DACL) 包含零个条目的任何进程可用的命名管道) 的访问。
  2. 创建命名的管道。
  3. 调用 ConnectNamedPipe,阻止直到客户端连接。
  4. 调用 ReadFile 和/或写文件通过管道进行通信。
  5. 在完成该过程调用 DisconnectNamedPipe 使用管道。
  6. 任一 CloseHandle 上的命名的管道或转到步骤 4。
有三个步骤,使用命名管道客户端从命名管道:
  1. 调用 CreateFile 以获取命名管道的句柄。
  2. 调用 ReadFile 和/或写文件通过管道进行通信。
  3. 在 CreateFile 中创建的文件句柄上调用 CloseHandle。
或者,可以调用 CallNamedPipe,通过管道执行一次性交易记录。 CallNamedPipe 打开管道,将写入到它,读取它,然后关闭管道。 这是下面的客户端所做的事情。

下面的示例演示如何创建命名管道服务器和客户端。 它实现了只有最基本必需的功能为此,请使用少量的错误检查。 全功能的程序应该检查的 api 的调用时,返回的值,而不是假定它们成功。

命名的管道服务器

  1. 创建新的项目。默认情况下,将创建 Form1。
  2. 向表单中添加以下代码:
       Option Explicit
       Private Const szPipeName = "\\.\pipe\bigtest"
       Private Const BUFFSIZE = 20000
       Private BigBuffer(BUFFSIZE) As Byte, pSD As Long
       Private sa As SECURITY_ATTRIBUTES
       Private hPipe As Long
    
       Private Sub Form_Click()
          Dim i As Long, dwOpenMode As Long, dwPipeMode As Long
          Dim res As Long, nCount As Long, cbnCount As Long
          For i = 0 To BUFFSIZE - 1       'Fill an array of numbers
             BigBuffer(i) = i Mod 256
          Next i
    
          'Create the NULL security token for the pipe
          pSD = GlobalAlloc(GPTR, SECURITY_DESCRIPTOR_MIN_LENGTH)
          res = InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)
          res = SetSecurityDescriptorDacl(pSD, -1, 0, 0)
          sa.nLength = LenB(sa)
          sa.lpSecurityDescriptor = pSD
          sa.bInheritHandle = True
    
          'Create the Named Pipe
          dwOpenMode = PIPE_ACCESS_DUPLEX Or FILE_FLAG_WRITE_THROUGH
          dwPipeMode = PIPE_WAIT Or PIPE_TYPE_MESSAGE Or PIPE_READMODE_MESSAGE
          hPipe = CreateNamedPipe(szPipeName, dwOpenMode, dwPipeMode, _
                                  10, 10000, 2000, 10000, sa)
    
          Do  'Wait for a connection, block until a client connects
             res = ConnectNamedPipe(hPipe, ByVal 0)
    
             'Read/Write data over the pipe
             cbnCount = 4
    
             res = ReadFile(hPipe, nCount, LenB(nCount), cbnCount, ByVal 0)
    
             If nCount <> 0 Then
    
                If nCount > BUFFSIZE Then 'Client requested nCount bytes
                   nCount = BUFFSIZE      'but only send up to 20000 bytes
                End If
                'Write the number of bytes requested
                res = WriteFile(hPipe, BigBuffer(0), nCount, cbnCount, ByVal 0)
                'Make sure the write is finished
                res = FlushFileBuffers(hPipe)
             End If
    
             'Disconnect the NamedPipe
             res = DisconnectNamedPipe(hPipe)
          Loop Until nCount = 0
    
          'Close the pipe handle
          CloseHandle hPipe
          GlobalFree (pSD)
          End
       End Sub
    					
  3. 创建一个新的模块并添加以下声明:
       Option Explicit
    
       Public Const FILE_ATTRIBUTE_NORMAL = &H80
       Public Const FILE_FLAG_NO_BUFFERING = &H20000000
       Public Const FILE_FLAG_WRITE_THROUGH = &H80000000
    
       Public Const PIPE_ACCESS_DUPLEX = &H3
       Public Const PIPE_READMODE_MESSAGE = &H2
       Public Const PIPE_TYPE_MESSAGE = &H4
       Public Const PIPE_WAIT = &H0
    
       Public Const INVALID_HANDLE_VALUE = -1
    
       Public Const SECURITY_DESCRIPTOR_MIN_LENGTH = (20)
       Public Const SECURITY_DESCRIPTOR_REVISION = (1)
    
       Type SECURITY_ATTRIBUTES
               nLength As Long
               lpSecurityDescriptor As Long
               bInheritHandle As Long
       End Type
    
       Public Const GMEM_FIXED = &H0
       Public Const GMEM_ZEROINIT = &H40
       Public Const GPTR = (GMEM_FIXED Or GMEM_ZEROINIT)
    
       Declare Function GlobalAlloc Lib "kernel32" ( _
          ByVal wFlags As Long, ByVal dwBytes As Long) As Long
       Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
       Declare Function CreateNamedPipe Lib "kernel32" Alias _
          "CreateNamedPipeA" ( _
          ByVal lpName As String, _
          ByVal dwOpenMode As Long, _
          ByVal dwPipeMode As Long, _
          ByVal nMaxInstances As Long, _
          ByVal nOutBufferSize As Long, _
          ByVal nInBufferSize As Long, _
          ByVal nDefaultTimeOut As Long, _
          lpSecurityAttributes As Any) As Long
    
       Declare Function InitializeSecurityDescriptor Lib "advapi32.dll" ( _
          ByVal pSecurityDescriptor As Long, _
          ByVal dwRevision As Long) As Long
    
       Declare Function SetSecurityDescriptorDacl Lib "advapi32.dll" ( _
          ByVal pSecurityDescriptor As Long, _
          ByVal bDaclPresent As Long, _
          ByVal pDacl As Long, _
          ByVal bDaclDefaulted As Long) As Long
    
       Declare Function ConnectNamedPipe Lib "kernel32" ( _
          ByVal hNamedPipe As Long, _
          lpOverlapped As Any) As Long
    
       Declare Function DisconnectNamedPipe Lib "kernel32" ( _
          ByVal hNamedPipe As Long) As Long
    
       Declare Function WriteFile Lib "kernel32" ( _
          ByVal hFile As Long, _
          lpBuffer As Any, _
          ByVal nNumberOfBytesToWrite As Long, _
          lpNumberOfBytesWritten As Long, _
          lpOverlapped As Any) As Long
    
       Declare Function ReadFile Lib "kernel32" ( _
          ByVal hFile As Long, _
          lpBuffer As Any, _
          ByVal nNumberOfBytesToRead As Long, _
          lpNumberOfBytesRead As Long, _
          lpOverlapped As Any) As Long
    
       Declare Function FlushFileBuffers Lib "kernel32" ( _
          ByVal hFile As Long) As Long
    
       Declare Function CloseHandle Lib "kernel32" ( _
          ByVal hObject As Long) As Long
    					
  4. 保存该窗体。

命名的管道客户端

  1. 创建新的项目。默认情况下,将创建 Form1。
  2. 向表单中添加下列控件:
       Type             Name               Caption/Default Value
       ----             ----               ---------------------
       TextBox          cbBytes            500
       CommandButton    cmdCallNamedPipe   Call Named Pipe
       TextBox          txtReceive
    					
  3. 向表单中添加以下代码:
       Option Explicit
       Private Const szPipeName = "\\.\pipe\bigtest", BUFFSIZE = 20000
       Private Declare Function CallNamedPipe Lib "kernel32" Alias _
          "CallNamedPipeA" ( _
          ByVal lpNamedPipeName As String, _
          lpInBuffer As Any, _
          ByVal nInBufferSize As Long, _
          lpOutBuffer As Any, _
          ByVal nOutBufferSize As Long, _
          lpBytesRead As Long, _
          ByVal nTimeOut As Long) As Long
    
       Private Sub cmdCallNamedPipe_Click()
          Dim res As Long, myStr As String, i As Long, cbRead As Long
          Dim numBytes As Long, bArray() As Byte, temp As String
    
          numBytes = cbBytes.Text
          If cbBytes.Text < 0 Then
             MsgBox "Value must be at least 0.", vbOKOnly
             Exit Sub
          End If
          If numBytes > BUFFSIZE Then
             numBytes = BUFFSIZE
          End If
          ReDim bArray(numBytes)  'Build the return buffer
    
          'Call CallNamedPipe to do the transaction all at once
          res = CallNamedPipe(szPipeName, numBytes, LenB(numBytes), _
             bArray(0), numBytes, _
             cbRead, 30000) 'Wait up to 30 seconds for a response
    
          If res > 0 Then
             temp = Format(bArray(0), " 000")
             For i = 1 To cbRead - 1
                If (i Mod 16) = 0 Then temp = temp & vbCrLf
                temp = temp & " " & Format(bArray(i), "000")
             Next i
             txtReceive.Text = temp
          Else
             MsgBox "Error number " & Err.LastDllError & _
                    " attempting to call CallNamedPipe.", vbOKOnly
          End If
       End Sub
    
    					
  4. 请注意是否服务器正在运行而不是客户端所在的计算机上,您需要更改。 为服务器计算机的名称变量 szPipeName 中。
  5. 保存该窗体。若要测试上面的代码,第一次启动服务器,并在窗体上的任意位置单击。服务器应用程序现在阻止即会显示已中断,但实际上正在等待客户端连接。然后启动客户端应用程序并单击"呼叫命名管道"。客户端应将 500 的值发送到服务器将响应 500 字节的数据。您可以设置值的 cbBytes 文本框中从 0 到 20000 个字节。要停止服务器,只需从客户端发送 0 (零)。客户端可能会收到错误 233 (ERROR_PIPE_NOT_CONNECTED),但这是正常现象。

    该示例的另一改进可能包括使用 IO 完成端口和/或非阻塞读取和写入使用重叠 IO。您可以在 Microsoft 平台 SDK 中发现这些主题的详细信息。

参考

有几种进程间通信 (IPC) 方法在 Windows 2000、 Windows NT 和允许单向或双向传输数据的多个进程之间的 Windows 95 中可用。 每个平台上可用的 IPC 方法的完整列表,请参阅 Microsoft 知识库中相应的文章:
95900 : Windows NT、 Windows 95 和 win32 进程间通信

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值