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

来源:互联网 发布:淘宝店挣钱吗 编辑:程序博客网 时间:2024/06/05 19:26

参考: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 进程间通信
回到顶端 | 提供反馈

原创粉丝点击