|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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. |