|
|
![]() |
|
||
|
|
|||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic Enumeration/Callback Routines EnumPrinterDrivers: Enumerate Print Drivers on Specific Printer Server |
|
| Posted: | Monday February 10, 2003 |
| Updated: | Monday December 26, 2011 |
| Applies to: | VB5, VB6 |
| Developed with: | VB6, Windows XP |
| OS restrictions: | Windows 2000, Windows XP. See Prerequisites |
| Author: | 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 EnumPrinters: Enumerating Local and Network Printers EnumPrinterDrivers: Enumerate Print Drivers on Specific Printer Server SetDefaultPrinter: Changing Windows' Default Printer WriteProfileString: Changing Windows' Default Printer |
| Prerequisites | ||||||||||||||||
| As coded, this demo uses the DRIVER_INFO_4 structure for Windows 2000 and Windows XP, although the code below can be modified to run on all Windows versions using the appropriate driver info level. | ||||||||||||||||
|
|
||||||||||||||||
EnumPrinterDrivers
enumerates the printer drivers installed on a specified printer server.
This demo targets Windows 2000 and Windows XP specifically through the
use of the DRIVER_INFO_4 structure.
There are six DRIVER_INFO_* structures available for the various versions of Windows:
Each of the different DRIVER_INFO_* types is defined in the code below. In order to allow the routines to handle any of the six DRIVER_INFO_* types (when supported by the operating system), two sets of constants are defined: one, prefixed DRIVER_LEVEL and with the values 1 through 6, represents the DRIVER_INFO_* level you are using in the call. The second, prefixed SIZEOF_DRIVERINFO_, contains a long value representing the size (Len) of the corresponding DRIVER_INFO_* structure. Therefore, in order to use a DRIVER_INFO_* level other than the demo's DRIVER_INFO_4, you must change variables in four places within the EnumPrintServerDrivers function:
|
||||||||||||||||
| BAS Module Code | ||||||||||||||||
| None. | ||||||||||||||||
|
|
||||||||||||||||
| Form Code | ||||||||||||||||
|
|
||||||||||||||||
| Add a command button (Command1) and a listbox (List1) to a form, along with the following code: | ||||||||||||||||
|
|
||||||||||||||||
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. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Type DRIVER_INFO_1
pName As Long
End Type
Private Type DRIVER_INFO_2
cVersion As Long
pName As Long
pEnvironment As Long
pDriverPath As Long
pDataFile As Long
pConfigFile As Long
End Type
Private Type DRIVER_INFO_3
cVersion As Long
pName As Long
pEnvironment As Long
pDriverPath As Long
pDataFile As Long
pConfigFile As Long
pHelpFile As Long
pDependentFiles As Long
pMonitorName As Long
pDefaultDataType As Long
End Type
Private Type DRIVER_INFO_4
cVersion As Long
pName As Long
pEnvironment As Long
pDriverPath As Long
pDataFile As Long
pConfigFile As Long
pHelpFile As Long
pDependentFiles As Long
pMonitorName As Long
pDefaultDataType As Long
pszzPreviousNames As Long
End Type
Private Type DRIVER_INFO_5
cVersion As Long
pName As Long
pEnvironment As Long
pDriverPath As Long
pDataFile As Long
pConfigFile As Long
dwDriverAttributes As Long
dwConfigVersion As Long
dwDriverVersion As Long
End Type
Private Type DRIVER_INFO_6
cVersion As Long
pName As Long
pEnvironment As Long
pDriverPath As Long
pDataFile As Long
pConfigFile As Long
pHelpFile As Long
pDependentFiles As Long
pMonitorName As Long
pDefaultDataType As Long
pszzPreviousNames As Long
ftDriverDate As Long 'FILETIME pointer
dwlDriverVersion As Long
pszMfgName As Long
pszOEMUrl As Long
pszHardwareID As Long
pszProvider As Long
End Type
Private Const SIZEOFDRIVER_INFO_1 = 4
Private Const SIZEOFDRIVER_INFO_2 = 24
Private Const SIZEOFDRIVER_INFO_3 = 40
Private Const SIZEOFDRIVER_INFO_4 = 44
Private Const SIZEOFDRIVER_INFO_5 = 36
Private Const SIZEOFDRIVER_INFO_6 = 68
Private Const DRIVER_LEVEL1 = &H1
Private Const DRIVER_LEVEL2 = &H2
Private Const DRIVER_LEVEL3 = &H3
Private Const DRIVER_LEVEL4 = &H4
Private Const DRIVER_LEVEL5 = &H5
Private Const DRIVER_LEVEL6 = &H6
Private Const LB_SETTABSTOPS As Long = &H192
Private Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" _
(ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
Private Declare Function EnumPrinterDrivers Lib "winspool.drv" _
Alias "EnumPrinterDriversA" _
(ByVal pName As String, _
ByVal pEnvironment As String, _
ByVal Level As Long, _
pDriverInfo As Any, _
ByVal cdBuf As Long, _
pcbNeeded As Long, _
pcReturned As Long) As Long
Private Declare Function lstrcpyA Lib "kernel32" _
(ByVal RetVal As String, ByVal Ptr As Long) As Long
Private Declare Function lstrlenA Lib "kernel32" _
(ByVal Ptr As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" _
Alias "RtlMoveMemory" _
(dst As Any, src As Any, ByVal bcount As Long)
Private Sub Form_Load()
ReDim TabArray(0 To 0) As Long
Command1.Caption = "Enum Printer Drivers"
TabArray(0) = 60
Call SendMessage(List1.hwnd, LB_SETTABSTOPS, 0&, ByVal 0&)
Call SendMessage(List1.hwnd, LB_SETTABSTOPS, 1&, TabArray(0))
List1.Refresh
End Sub
Private Sub Command1_Click()
Dim numPrinters As Long
'list printers and drivers on the
'local machine, for the environment
'specified. Note that if vbNullString
'is passed as the environment parameter,
'the function uses the current environment of
'the caller/client (not of the destination/server).
'Under XP the string "All" can also be used
'to enumerate printer drivers for all platforms
'installed on the specified server.
numPrinters = EnumPrintServerDrivers(vbNullString, "Windows NT x86", List1)
'numPrinters = EnumPrintServerDrivers("\\svrWhatever", "All", List1)
End Sub
Private Function EnumPrintServerDrivers(ByVal sServer As String, _
ByVal sEnviron As String, _
ctl As ListBox) As Long
Dim cbRequired As Long
Dim cbBuffer As Long
Dim pntr() As DRIVER_INFO_4
Dim nEntries As Long
Dim cnt As Long
Dim j As Long
Dim dwFileCount As Long
Dim sDriverFiles() As String
ctl.Clear
'To determine the required buffer size,
'call EnumPrinterDrivers with cbBuffer set
'to zero. The call will fails specifying
'ERROR_INSUFFICIENT_BUFFER and filling in
'cbRequired with the required size, in bytes,
'of the buffer required to hold the array
'of structures and data.
Call EnumPrinterDrivers(sServer, _
sEnviron, _
DRIVER_LEVEL4, _
0, 0, _
cbRequired, _
nEntries)
'Allocate space for the structure
ReDim pntr((cbRequired \ SIZEOFDRIVER_INFO_4))
'Set cbBuffer equal to the size of the buffer
cbBuffer = cbRequired
'Enumerate the print drivers. If the
'function succeeds, the return value
'is nonzero; 0 if it fails
If EnumPrinterDrivers(sServer, _
sEnviron, _
DRIVER_LEVEL4, _
pntr(0), _
cbBuffer, _
cbRequired, _
nEntries) <> 0 Then
'sanity check - these should still be the same!
If cbRequired = cbBuffer Then
'for each returned entry
For cnt = 0 To nEntries - 1
With pntr(cnt)
'add the printer name to the list
ctl.AddItem "printer:" & vbTab & GetStrFromPtrA(.pName)
'add some other driver info
ctl.AddItem "environ:" & vbTab & LCase$(GetStrFromPtrA(.pEnvironment))
ctl.AddItem "driver path:" & vbTab & LCase$(GetStrFromPtrA(.pDriverPath))
ctl.AddItem "config file:" & vbTab & LCase$(GetStrFromPtrA(.pConfigFile))
ctl.AddItem "data file:" & vbTab & LCase$(GetStrFromPtrA(.pDataFile))
'determine if the print driver lists
'dependent files
dwFileCount = GetDependentDriverFiles(.pDependentFiles, sDriverFiles())
If dwFileCount > 0 Then
ctl.AddItem "dependent files:" & vbTab & dwFileCount
'add each to the list
For j = 0 To dwFileCount - 1 '0-based!
ctl.AddItem vbTab & LCase$(sDriverFiles(j))
Next
Else
'no dependencies returned
ctl.AddItem "dependent files:" & vbTab & dwFileCount
ctl.AddItem vbTab & "(no dependent files)"
End If 'dwFileCount > 0
End With 'pntr(cnt)
'add spacer line
ctl.AddItem ""
Next cnt
Else
ctl.AddItem "Error enumerating printer drivers."
End If 'cbRequired
Else
ctl.AddItem "Error enumerating printer drivers."
End If 'EnumPrinterDrivers
'return the number of entries read
'as a sign of success
EnumPrintServerDrivers = nEntries
End Function
Public Function GetStrFromPtrA(ByVal lpszA As Long) As String
GetStrFromPtrA = String$(lstrlenA(ByVal lpszA), 0)
Call lstrcpyA(ByVal GetStrFromPtrA, ByVal lpszA)
End Function
Public Function GetDependentDriverFiles(ByVal lpszA As Long, _
sDriverFiles() As String) As Long
Dim buff As String
Dim pos As Long
'ensure string has data
If lstrlenA(ByVal lpszA) > 0 Then
'pad a buffer large enough to
'hold the dependent strings. On
'my system the Epson driver has
'71 dependent files. If pos below
'fails to locate the pair of terminating
'nulls indicating the end of data, buff
'is too small.
buff = Space$(8192)
'copy the data from the string
'pointed to by lpsza
CopyMemory ByVal buff, ByVal lpszA, Len(buff)
'Sanity check. The MSDN states each driver
'file is separated from the next by a null
'char, with the entire list terminated by
'a pair of nulls. This checks to ensure
'the pair are present. Note too the full
'path is returned for each file!
pos = InStr(buff, vbNullChar & vbNullChar)
If pos > 0 Then
'remove the pair of terminating nulls
buff = Left$(buff, pos - 1)
'create an array from the remaining data
sDriverFiles() = Split(buff, vbNullChar)
'return the number of files in the
'array, adding 1 to accommodate the
'0-based array.
GetDependentDriverFiles = UBound(sDriverFiles) + 1
Exit Function
End If
End If
GetDependentDriverFiles = 0
End Function |
||||||||||||||||
| Comments | ||||||||||||||||
|
|
||||||||||||||||
|
|
|
|||||
|
|||||
|
|
|||||
|
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |
![]() |