Tip 93: Retrieving the Names of Installed Printers

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

No comments: