|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic Enumeration/Callback Routines EnumPorts: Identify Windows' Available Ports |
|
Posted: | Friday September 17, 1999 |
Updated: | Monday December 26, 2011 |
Applies to: | VB5, VB6 |
Developed with: | VB6, Windows NT4 |
OS restrictions: | None |
Author: | Richard Cardarelle, Brad Martinez, VBnet - Randy Birch |
Related: |
AddPort: Adding and Deleting Application-Defined Ports AddPrinter: Add/Delete Local/Remote Printers using Existing Drivers EnumPorts: Identify Windows' Available Ports |
Prerequisites |
None. |
|
The
method shows how to enumerate the installed ports that are available for printing on a specified server using the EnumPorts API. The method
populates an array of PORT_INFO_2 UDTs, extracting the values returned using lstrcpyA.
This sample is based on initial code by Richard Cardarelle, and simplified greatly by Brad Martinez. |
BAS Module Code |
Place the following code into the general declarations area of a bas module: |
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Enum PortTypes PORT_TYPE_WRITE = &H1 PORT_TYPE_READ = &H2 PORT_TYPE_REDIRECTED = &H4 PORT_TYPE_NET_ATTACHED = &H8 End Enum Public Type PORT_INFO_2 pPortName As Long pMonitorName As Long pDescription As Long fPortType As Long Reserved As Long End Type 'SIZEOFxxx is a non-windows constant defined for this method Public Const SIZEOFPORT_INFO_2 = 20 Public Const LB_SETTABSTOPS As Long = &H192 'EnumPorts member descriptions: 'pName: String specifying the name of the server whose 'printer ports you wish to enumerate. If pName is 'vbNullString, the function enumerates the local 'machine's printer ports. 'nLevel: Specifies the type of information returned in 'the lpbPorts buffer. If nLevel is 1, lpbPorts receives 'an array of PORT_INFO_1 structures. If nLevel is 2, 'lpbPorts receives an array of PORT_INFO_2 structures. 'lpbPorts: Pointer to a buffer that receives an array of 'PORT_INFO_1 or PORT_INFO_2 structures. Each structure 'contains data that describes an available printer port. 'The buffer must be large enough to store the strings 'pointed to by the structure members. 'cbBuf: the size, in bytes, of the buffer pointed to by lpbPorts. 'pcbNeeded: receives the number of bytes copied to the lpbPorts 'buffer. If the the buffer is too small, the function fails and 'the variable receives the number of bytes required. 'pcReturned: variable that receives the number of PORT_INFO_1 or 'PORT_INFO_2 structures returned in the pPorts buffer. This 'corresponds to the number of printer ports that are available 'on the specified machine. Public Declare Function EnumPorts Lib "winspool.drv" _ Alias "EnumPortsA" _ (ByVal pName As String, _ ByVal nLevel As Long, _ lpbPorts As Any, _ ByVal cbBuf As Long, _ pcbNeeded As Long, _ pcReturned As Long) As Long Public Declare Function lstrlenA Lib "kernel32" _ (lpString As Any) As Long Public Declare Function lstrcpyA Lib "kernel32" _ (lpString1 As Any, lpString2 As Any) As Long Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" _ (ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ lParam As Any) As Long |
Form Code |
On a form add a command button, a listbox and a label for the number of ports returned. Label other items as desired. Add: |
|
Option Explicit Private Sub Form_Load() ReDim TabArray(0 To 2) As Long TabArray(0) = 65 TabArray(1) = 129 TabArray(2) = 188 Call SendMessage(List1.hwnd, LB_SETTABSTOPS, 0&, ByVal 0&) Call SendMessage(List1.hwnd, LB_SETTABSTOPS, 3&, TabArray(0)) List1.Refresh End Sub Private Sub Command1_Click() Dim numPorts As Long numPorts = GetAvailablePorts(List1) Label1.Caption = CStr(numPorts) & " ports found." End Sub Public Function GetStrFromPtrA(lpszA As Long) As String GetStrFromPtrA = String$(lstrlenA(ByVal lpszA), 0) Call lstrcpyA(ByVal GetStrFromPtrA, ByVal lpszA) End Function Private Function GetAvailablePorts(ctl As Control) As Long Dim pcbNeeded As Long Dim pcReturned As Long Dim pi2() As PORT_INFO_2 Dim i As Integer Dim sPortType As String ctl.Clear 'To determine the required buffer size, call EnumPorts with 'cbBuf set to zero. EnumPorts fails, and Err.LastDLLError 'returns ERROR_INSUFFICIENT_BUFFER, filling in the pcbNeeded 'parameter with the size, in bytes, of the buffer required to 'hold the array of structures and their data. Call EnumPorts(vbNullString, 2, 0, 0, pcbNeeded, pcReturned) If pcbNeeded Then 'The strings pointed to by each PORT_INFO_2 struct's members 'reside in memory after the end of the array of structs. So we're 'not only allocating memory for the structs themselves, but all the 'strings pointed to by each struct's member as well. Use floating 'point division, and add an extra struct to the array for padding. ReDim pi2((pcbNeeded / SIZEOFPORT_INFO_2)) If EnumPorts(vbNullString, 2, pi2(0), pcbNeeded, pcbNeeded, pcReturned) Then For i = 0 To (pcReturned - 1) With pi2(i) If (.fPortType And PORT_TYPE_WRITE) Then sPortType = "write " If (.fPortType And PORT_TYPE_READ) Then sPortType = sPortType & "read " If (.fPortType And PORT_TYPE_REDIRECTED) Then sPortType = sPortType & "redirected " If (.fPortType And PORT_TYPE_NET_ATTACHED) Then sPortType = sPortType & "network" ctl.AddItem GetStrFromPtrA(.pPortName) & vbTab & _ GetStrFromPtrA(.pDescription) & vbTab & _ .fPortType & "-" & sPortType & vbTab & _ GetStrFromPtrA(.pMonitorName) End With Next End If 'EnumPorts End If 'pcbNeeded 'return the number of ports found GetAvailablePorts = pcReturned End Function |
Comments |
The MSDN states that while the function returns a value of nonzero when it succeeds, or zero if it fails, that EnumPorts can succeed even if the server specified by pName does not have a printer defined. |
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |