* VB-CODE (3)
Tip 93: Retrieving the Names of Installed Printers

May 22, 1995

Abstract
The Windows® initialization file, WIN.INI, contains a list of all
printers attached to the computer system. This article contains an
example program that retrieves the name of each printer stored in the
WIN.INI initialization file.

Using GetProfileString and GetPrivateProfileString
The Devices section of the WIN.INI initialization file contains the
names of all printers attached to your computer system. You can
retrieve this list of printer names by using two Windows® application
programming interface (API) functions.

The Windows API GetProfileString and GetPrivateProfileString functions
can be used to retrieve the name of a printer as stored in the WIN.INI
file. For a complete discussion of these functions, see the articles
listed in the "Additional References" section of this article.

Example Program
This program retrieves the names of all installed printers from the
WIN.INI initialization file. The printer names are displayed in a
List Box control.

 1. Create a new project in Visual Basic. Form1 is created by default.
 2. Add the following Constant, Declare, and Type statements to the
    General Declarations section of Form1 (note that each Declare
    statement must be typed as a single line of text):

Option Explicit
Private Type WindowsDevice
   WindowsDeviceUserName As String
   WindowsDeviceShortName As String
   WindowsDevicePortName As String
End Type
Private Declare Function GetProfileString Lib "Kernel" (ByVal lpAppName
   As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal
   lpReturnedString As String, ByVal nSize As Integer) As Integer
Private Declare Function GetPrivateProfileString Lib "Kernel" (ByVal lpAppName
   As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal
   lpReturnedString As String, ByVal nSize As Integer, ByVal lpFileName As
   String) As Integer
Private Declare Function GetProfileKeys Lib "Kernel" Alias "GetProfileString"
   (ByVal lpAppName As String, ByVal lpKeyName As Long, ByVal lpDefault As
    String, ByVal lpReturnedString As String, ByVal nSize As Integer) As Integer
Private Declare Function GetPrivateProfileKeys Lib "Kernel" Alias
   "GetPrivateProfileString" (ByVal lpAppName As String, ByVal lpKeyName As
   Long, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal
   nSize As Integer, ByVal lpFileName As String) As Integer

Const WINDOWS_SECTION_NAME = "windows"
Const DEVICES_SECTION_NAME = "devices"
Const DEVICE_KEY_NAME = "device"
Const NO_PRINTER = "(none)"

 3. Add a Text Box control to Form1. Text1 is created by default.
 4. Add a Command Button control to Form1. Command1 is created by default.
 5. Add the following code to the Click event for Command1 (note that the
    List1.AddItem statement must be typed as a single line of code):

Private Sub Command1_Click()
    Dim OrgPrinter As WindowsDevice
    Call GetDefaultPrinter(OrgPrinter)
    Text1.Text = OrgPrinter.WindowsDeviceUserName
    Dim NumPrinters As Integer
    ReDim InstalledPrinters(0) As WindowsDevice
    Call GetInstalledPrinters(InstalledPrinters())
    For NumPrinters = 1 To UBound(InstalledPrinters)
        List1.AddItem InstalledPrinters(NumPrinters).WindowsDeviceUserName + "
          on " + InstalledPrinters(NumPrinters).WindowsDevicePortName
    Next
    List1.AddItem NO_PRINTER, 0
End Sub

 6. Create a new function called GetDefaultPrinter. Add the following
    code to this function:

Private Sub GetDefaultPrinter(recDefaultPrinter As WindowsDevice)
    Dim StrPos As Integer
    Dim DefaultPrinter As String
    Dim RC As Integer
    DefaultPrinter = GetString(WINDOWS_SECTION_NAME, DEVICE_KEY_NAME, "", "")
    StrPos = InStr(DefaultPrinter, ",")
    recDefaultPrinter.WindowsDeviceUserName = Left$(DefaultPrinter, StrPos - 1)
    DefaultPrinter = Mid$(DefaultPrinter, StrPos + 1)
    StrPos = InStr(DefaultPrinter, ",")
    recDefaultPrinter.WindowsDeviceShortName = Left$(DefaultPrinter, StrPos - 1)
    recDefaultPrinter.WindowsDevicePortName = Mid$(DefaultPrinter, StrPos + 1)
End Sub

 7. Create a new function called GetInstalledPrinter. Add the
    following code to this function (note that the InstalledPrinter
    lines must be typed as a single line of code):

Private Sub GetInstalledPrinters(recInstalledPrinters() As WindowsDevice)
    Dim StrPos As Integer
    Dim PrtSub As Integer
    Dim InstalledPrinter As String
    ReDim PrinterNames(0) As String
    Call GetKeyNames(DEVICES_SECTION_NAME, PrinterNames(), "")
    ReDim recInstalledPrinters(UBound(PrinterNames))
    For PrtSub = 1 To UBound(PrinterNames)
        InstalledPrinter = GetString(DEVICES_SECTION_NAME, PrinterNames(PrtSub),
            "", "")
        StrPos = InStr(InstalledPrinter, ",")
        recInstalledPrinters(PrtSub).WindowsDeviceUserName =
            PrinterNames(PrtSub)
        recInstalledPrinters(PrtSub).WindowsDeviceShortName =
            Left$(InstalledPrinter, StrPos - 1)
        InstalledPrinter = Mid$(InstalledPrinter, StrPos + 1)
        StrPos = InStr(InstalledPrinter, ",")
        If StrPos > 0 Then
            recInstalledPrinters(PrtSub).WindowsDevicePortName =
               Left$(InstalledPrinter, StrPos - 1)
        Else
            recInstalledPrinters(PrtSub).WindowsDevicePortName =
               InstalledPrinter
        End If
    Next
End Sub

 8. Create a new function called GetString. Add the following code to
    this function (note that the Function and KeyValueLength lines
    must each be typed as a single line of code):

Function GetString(SectionName As String, KeyName As String, DefaultValue
   As String, ProfileName As String) As String
    Dim KeyValueLength As Integer
    Dim KeyValue As String
    KeyValue = Space$(256)
    If Trim$(ProfileName) = "" Then
        KeyValueLength = GetProfileString(SectionName, KeyName, DefaultValue,
           KeyValue, Len(KeyValue))
    Else
        KeyValueLength = GetPrivateProfileString(SectionName, KeyName,
           DefaultValue, KeyValue, Len(KeyValue), ProfileName)
    End If
    GetString = Left$(KeyValue, KeyValueLength)
End Function

 9. Create a new function called GetKeyName. Add the following code
    to this function (note that the Sub and KeyNamesLength lines must
    each be typed as a single line of code):

Sub GetKeyNames(SectionName As String, KeyNames() As String, ProfileName
   As String)
    Dim StrPos As Integer
    Dim KeyCount As Integer
    Dim Start As Integer
    Dim KeyNamesLength As Integer
    Dim KeyNameString As String
    KeyNameString = Space$(1024)
    If Trim$(ProfileName) = "" Then
        KeyNamesLength = GetProfileKeys(SectionName, 0, "", KeyNameString,
            Len(KeyNameString))
    Else
        KeyNamesLength = GetPrivateProfileKeys(SectionName, 0, "",
            KeyNameString, Len(KeyNameString), ProfileName)
    End If
    KeyCount = 0
    ReDim KeyNames(0)
    If KeyNamesLength > 0 Then
        KeyNameString = Left$(KeyNameString, KeyNamesLength)
        If Right$(KeyNameString, 1) <> Chr$(0) Then
            KeyNameString = KeyNameString + Chr$(0)
        End If
        KeyNamesLength = Len(KeyNameString)
        Start = 1
        Do
            StrPos = InStr(Start, KeyNameString, Chr$(0))
            If StrPos > 0 Then
                KeyCount = KeyCount + 1
                ReDim Preserve KeyNames(KeyCount)
                KeyNames(KeyCount) = Mid$(KeyNameString, Start, StrPos - Start)
                If StrPos < KeyNamesLength Then
                    Start = StrPos + 1
                Else
                    Exit Do

               End If
            Else
                Exit Do
            End If
        Loop
        End If
End Sub

Run the example program by pressing the F5 function key. Click the
Command Button control. The name of the default printer is displayed
in the Text Box control, and a list of all installed printers is
displayed in the List Box control.

Additional References
Knowledge Base Q105839. "Changing WIN.INI Printer Settings from VB
   using Windows API."
"Accessing Initialization Files." (Books and Periodicals, Inside
   Visual Basic Articles [Cobb])
"Querying Windows for Printer Information." (Books and Periodicals,
   Inside Visual Basic Articles [Cobb])
Tip 30: Retrieving the Default Printer's Name from WIN.INI


Return