ACC: Enumerating Local and Network Printers

Last reviewed: March 2, 1998
Article ID: Q166008
The information in this article applies to:
  • Microsoft Access versions 7.0, 97

SUMMARY

Advanced: Requires expert coding, interoperability, and multiuser skills.

This article demonstrates two procedures that use the EnumPrinters API function to retrieve a list of printers available locally and that your computer is connected to on the network.

The procedures demonstrate returning data to both the PRINTER_INFO_1 structure and the PRINTER_INFO_4 structure, each of which provides slightly different information about the printer. If you are using Microsoft Windows 95, you can return data to the PRINTER_INFO_1 structure; if you are using Microsoft Windows NT, you can return data to either structure.

This article assumes that you are familiar with Visual Basic for Applications and with creating Microsoft Access applications using the programming tools provided with Microsoft Access. For more information about Visual Basic for Applications, please refer to your version of the "Building Applications with Microsoft Access" manual.

MORE INFORMATION

WARNING: ANY USE BY YOU OF THE CODE PROVIDED IN THIS ARTICLE IS AT YOUR OWN RISK. Microsoft provides this code "as is" without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose.

Use the subroutine EnumeratePrinters1 if you are running Microsoft Windows 95. You can use either subroutine if you are running Microsoft Windows NT.

The code in each of the two examples performs these steps:

  • Calls the EnumPrinters API, which returns a buffer of data, a success flag, and a flag indicating whether the buffer is too small.
  • If the buffer is too small, makes it the correct size and calls the API again.
  • For each entry in the buffer, extracts the data and prints it.

NOTE: When using these functions in your own applications, you may want to return an array of data that can be displayed in a list box or grid rather than print the values.

The buffer is in the following format:

    |rec1|rec2|...|recn|...garbage...|strn|...|str2|str1|

INFO records containing string pointers and numeric values are added from the left, and the string text for each record is added from the right. The area between the end of the last record and the start of the last string text contains garbage.

The buffer is declared as type Long, which makes extracting data from the records easier - all fields are either Long or pointers (pointers map to Long).

The StrLen() and PtrToStr() functions are used to set up the receiving string variable and to copy the text from the buffer to the variable.

  1. Create a module and type the following lines in the Declarations section:

          Option Explicit
    

          Const PRINTER_ENUM_CONNECTIONS = &H4
          Const PRINTER_ENUM_LOCAL = &H2
    

          Type PRINTER_INFO_1
    
             flags As Long
             pDescription As String
             PName As String
             PComment As String
          End Type
    
          Type PRINTER_INFO_4
             pPrinterName As String
             pServerName As String
             Attributes As Long
          End Type
    
          Declare Function EnumPrinters Lib "winspool.drv" Alias _
             "EnumPrintersA" (ByVal flags As Long, ByVal name As String, _
             ByVal Level As Long, pPrinterEnum As Long, ByVal cdBuf As Long, _
             pcbNeeded As Long, pcReturned As Long) As Long
          Declare Function PtrToStr Lib "Kernel32" Alias "lstrcpyA" _
             (ByVal RetVal As String, ByVal Ptr As Long) As Long
          Declare Function StrLen Lib "Kernel32" Alias "lstrlenA" _
             (ByVal Ptr As Long) As Long
    
    

  2. Type the following procedures:

          Sub EnumeratePrinters1()
          Dim Success As Boolean, cbRequired As Long, cbBuffer As Long
          Dim Buffer() As Long, nEntries As Long
          Dim I As Long, PFlags As Long, PDesc As String, PName As String
          Dim PComment As String, Temp As Long
             cbBuffer = 3072
             ReDim Buffer((cbBuffer \ 4) - 1) As Long
             Success = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
                                   PRINTER_ENUM_LOCAL, _
                                   vbNullString, _
                                   1, _
                                   Buffer(0), _
                                   cbBuffer, _
                                   cbRequired, _
                                   nEntries)
             If Success Then
                If cbRequired > cbBuffer Then
                   cbBuffer = cbRequired
                   Debug.Print "Buffer too small.  Trying again with " & _
                            cbBuffer & " bytes."
                   ReDim Buffer(cbBuffer \ 4) As Long
                   Success = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
                                       PRINTER_ENUM_LOCAL, _
                                       vbNullString, _
                                       1, _
                                       Buffer(0), _
                                       cbBuffer, _
                                       cbRequired, _
                                       nEntries)
                   If Not Success Then
                      Debug.Print "Error enumerating printers."
                      Exit Sub
                   End If
                End If
             Debug.Print "There are " & nEntries & _
                          " local and connected printers."
             For I = 0 To nEntries - 1
                PFlags = Buffer(4 * I)
                PDesc = Space$(StrLen(Buffer(I * 4 + 1)))
                Temp = PtrToStr(PDesc, Buffer(I * 4 + 1))
                PName = Space$(StrLen(Buffer(I * 4 + 2)))
                Temp = PtrToStr(PName, Buffer(I * 4 + 2))
                PComment = Space$(StrLen(Buffer(I * 4 + 2)))
                Temp = PtrToStr(PComment, Buffer(I * 4 + 2))
                Debug.Print PFlags, PDesc, PName, PComment
             Next I
             Else
                Debug.Print "Error enumerating printers."
             End If
          End Sub
    
          Sub EnumeratePrinters4()
          Dim Success As Boolean, cbRequired As Long, cbBuffer As Long
          Dim Buffer() As Long, nEntries As Long
          Dim I As Long, PName As String, SName As String
          Dim Attrib As Long, Temp As Long
             cbBuffer = 3072
             ReDim Buffer((cbBuffer \ 4) - 1) As Long
             Success = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
                                   PRINTER_ENUM_LOCAL, _
                                   vbNullString, _
                                   4, _
                                   Buffer(0), _
                                   cbBuffer, _
                                   cbRequired, _
                                   nEntries)
             If Success Then
                If cbRequired > cbBuffer Then
                   cbBuffer = cbRequired
                   Debug.Print "Buffer too small.  Trying again with " & _
                            cbBuffer & " bytes."
                   ReDim Buffer(cbBuffer \ 4) As Long
                   Success = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
                                       PRINTER_ENUM_LOCAL, _
                                       vbNullString, _
                                       4, _
                                       Buffer(0), _
                                       cbBuffer, _
                                       cbRequired, _
                                       nEntries)
                   If Not Success Then
                      Debug.Print "Error enumerating printers."
                      Exit Sub
                   End If
                End If
                Debug.Print "There are " & nEntries & _
                          " local and connected printers."
                For I = 0 To nEntries - 1
                PName = Space$(StrLen(Buffer(I * 3)))
                Temp = PtrToStr(PName, Buffer(I * 3))
                SName = Space$(StrLen(Buffer(I * 3 + 1)))
                Temp = PtrToStr(SName, Buffer(I * 3 + 1))
                Attrib = Buffer(I * 3 + 2)
                Debug.Print "Printer: " & PName, "Server: " & SName, _
                            "Attributes: " & Hex$(Attrib)
                Next I
             Else
                Debug.Print "Error enumerating printers."
             End If
          End Sub
    
    

  3. To test this function, type the following line in the Debug window, and then press ENTER.

           EnumeratePrinters1
    

    The output should be similar to the following:

           There are 1 local and connected printers.
    
           8388608      \\NCPRINT\HP5SI@1155,HP LaserJet 5Si MX,HP5SI@1155
           \\NCPRINT\HP5SI@1155        \\NCPRINT\HP5SI@1155
    
       If you are using Microsoft Windows NT, type:
    
           EnumeratePrinters4
    
       The output should be similar to the following:
    
           There are 1 local and connected printers.
           Printer: \\NCPRINT\HP5SI@1155             Server: \\NCPRINT
           Attributes: 10
    
    

REFERENCES

For more information about the EnumPrinters function, please refer to the Win32 SDK.

Keywords          : kbcode kbnetwork kbprg kbprint
Version           : 7.0 97
Platform          : WINDOWS
Hardware          : x86
Issue type        : kbhowto


================================================================================


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: March 2, 1998
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.