How to call the EnumJobs function from a Visual Basic .NET application (821769)
The information in this article applies to:
- Microsoft Visual Basic .NET (2003)
- Microsoft Visual Basic .NET (2002)
SUMMARYThe EnumJobs function is available in the Winspool.drv print spool interface.
You can use the EnumJobs function to retrieve the status of the jobs that are queued in a
local print queue. The EnumJobs function enumerates the number of jobs, the job identification,
the job status, and other parameters based on your
requirements. When you try to print any document, the print job is queued in the local print queue until the printer performs that job. The port monitor communicates with the printer to obtain information about a print job and then communicates the information to the local print queue. Therefore, you can monitor the local print queue to retrieve the status of your print job. The local print queue accepts any number of jobs, even if the printer hardware is in an error state. Therefore, the Ready state of the print queue does not determine whether the job will print. Many statuses are available to report. However, many of them are not supported. The printer hardware and the port monitor determine the status that appears.
INTRODUCTIONThis step-by-step article describes how to use Microsoft
Windows API functions in Microsoft Visual Basic .NET to determine the printer
status or the print job status programmatically. Although an application does
not typically have to examine the status of a printer before the printer
prints, it may be useful to determine the status of a printer or a print job
programmatically. back to the
topTechnical descriptionThe following information will help you use the sample application
to obtain information about your printer status:
- The term printer refers to a hardware device, a queue, a driver, or a port. Here,
the term printer status refers to the status of a local print queue.
- The sample code in the "Step-by-step sample" section
returns the status that the operating system reports. This is the same status
that the spooler reports. You can verify this status by monitoring the local
print queue. The application continuously monitors the printer status.
To view the local print queue on a computer that is running the
Microsoft Windows XP operating system, follow these steps:
- Click Start, point to
Settings, and then click Printers and
Faxes.
- In the Printers and Faxes window,
double-click the icon for the printer whose queue you want to view.
- You cannot communicate directly with the physical printer.
We recommend that you do not do this because the operating system controls
access to the hardware. The "Step-by-step sample" section examines the local
print queue that obtains the information from the port monitor.
- The port monitor communicates with the physical device. The
sample code in the "Step-by-step sample" section reports the printer status and
the job statuses.
- The queue is considered to be in a Ready state because it can accept jobs, even if the hardware is in an
error state. For example, if the last job that printed used the last sheet of
paper, the operating system cannot determine that the printer is out of paper
until the system tries to print again.
- Although many statuses can be reported, many statuses are
not supported in practice. The printer hardware and the port monitor determine
the status to report. For example, if the printer is out of paper and is
offline, the status may be reported as Printing because that is what the job is trying to do. Therefore,
regardless of whether a local print queue displays the Ready status, the print job may not be completed
successfully.
- The sample code in the "Step-by-step sample" section
examines only the local print queue. This information may be sufficient for
most applications. However, when you connect to remote printers, the process to
obtain sufficient information may become complex. You may have a chain of print
queues, and the port for the local print queue may be another queue.
- You may also use printer pooling. In printer pooling, multiple printers work from a common super queue. When the architecture becomes more complex, the code to retrieve
a meaningful status also becomes more complex, and the usefulness of the status
is reduced.
back to the topStep-by-step sample- Start Microsoft Visual Studio .NET.
- On the File menu, point to
New, and then click Project. The New
Project dialog box appears.
- Under Project Types, click Visual
Basic Projects.
- Under Templates, click Windows
Application.
- In the Name box, type
PrinterStatus, and then click OK. By
default, a form that is named Form1 is created.
- On the Project menu, click Add
Module. The Add New Item - PrinterStatus dialog box
appears.
- Under Templates, click
Module, and then click Open. By default, a
file that is named Module1.vb is created.
- In
the Module1.vb file, replace the existing code with the following sample code.
Option Explicit On
Imports System.Drawing.Printing.PrinterSettings
Imports System.Runtime.InteropServices
Module Module1
Public Class WINAPI
Declare Auto Function GetPrinter Lib "winspool.drv" (ByVal hPrinter As _
IntPtr, ByVal Level As Integer, ByRef pPrinter As Byte, ByVal cbBuf _
As Integer, ByRef pcbNeeded As Integer) As Boolean
Declare Auto Function lstrcpy Lib "Kernel32.Lib" Alias "lstrcpyA" _
(<OutAttribute(), MarshalAs(UnmanagedType.LPStr)> ByVal lpString1 As String, _
<MarshalAs(UnmanagedType.LPStr)> ByVal lpString2 As String) As Long
Declare Auto Function ClosePrinter Lib "winspool.drv" Alias "ClosePrinter" (ByVal hPrinter As IntPtr) As Long
Public Declare Function EnumJobs Lib "winspool.drv" Alias "EnumJobsA" _
(ByVal hPrinter As IntPtr, _
ByVal FirstJob As Int32, _
ByVal NoJobs As Int32, _
ByVal Level As Int32, _
ByVal pJob As Byte(), _
ByVal cdBuf As Int32, _
ByRef pcbNeeded As Int32, _
ByRef pcReturned As Int32) _
As Long
Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, _
ByRef phPrinter As IntPtr, ByVal pDefault As PRINTER_DEFAULTS) As Long
End Class
'Constants for the PRINTER_DEFAULTS structure
Public Const PRINTER_ACCESS_USE = &H8
Public Const PRINTER_ACCESS_ADMINISTER = &H4
'Constants for the DEVMODE structure
Public Const CCHDEVICENAME = 32
Public Const CCHFORMNAME = 32
Public API As New WINAPI
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> Structure SYSTEMTIME
Public wYear As Short
Public wMonth As Short
Public wDayOfWeek As Short
Public wDay As Short
Public wHour As Short
Public wMinute As Short
Public wSecond As Short
Public wMilliseconds As Short
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> Structure JOB_INFO_2
Public PrinterJobId As Integer
Public pPrinterName As Integer
Public PrinterName As Integer
Public PrinterUserName As Integer
Public PrinterDocument As Integer
Public PrinterNotifyName As Integer
Public PrinterDatatype As Integer
Public PrintProcessor As Integer
Public PrinterParameters As Integer
Public PrinterDriverName As Integer
Public PrinterDevMode As Integer
Public PrinterStatus As Integer
Public PrinterSecurityDescriptor As Integer
Public pStatus As Integer
Public PrinterPriority As Integer
Public Position As Integer
Public StartTime As Integer
Public UntilTime As Integer
Public TotalPages As Integer
Public Size As Integer
Public Submitted As SYSTEMTIME
Public time As Integer
Public PagesPrinted As Integer
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> Structure PRINTER_INFO_2
Public pServerName As Integer
Public pPrinterName As Integer
Public pShareName As Integer
Public pPortName As Integer
Public pDriverName As Integer
Public pComment As Integer
Public pLocation As Integer
Public pDevMode As Integer
Public pSepFile As Integer
Public pPrintProcessor As Integer
Public pDatatype As Integer
Public pParameters As Integer
Public pSecurityDescriptor As Integer
Public Attributes As Integer
Public Priority As Integer
Public DefaultPriority As Integer
Public StartTime As Integer
Public UntilTime As Integer
Public Status As Integer
Public cJobs As Integer
Public AveragePPM As Integer
End Structure
Public Function Pointer_to_String(ByVal Add As Long) As String
Dim Temp_var As String
Temp_var = New String(CChar(""), 512)
Dim x As Long
x = API.lstrcpy(Temp_var, Add)
If (InStr(1, Temp_var, Chr(0)) = 0) Then
Pointer_to_String = ""
Else
Pointer_to_String = Left(Temp_var, InStr(1, Temp_var, Chr(0)) - 1)
End If
End Function
Public Function DatatoDeserial(ByVal datas() As Byte, ByVal type_to_change As Type, _
ByVal NumJub As Long) As Object
'Returns the size of the JOB_INFO_2 structure
Dim Data_to_Size As Long = Marshal.SizeOf(type_to_change)
If Data_to_Size > datas.Length Then
Return Nothing
End If
Dim buffer As IntPtr = Marshal.AllocHGlobal(Data_to_Size)
Dim startindex As Long
Dim i As Integer
For i = 0 To NumJub - 1
If i = 0 Then
startindex = 0
Else
startindex = startindex + Data_to_Size
End If
Next
'Copy data from the datas array to the unmanaged memory pointer.
Marshal.Copy(datas, startindex, buffer, Data_to_Size)
'Marshal data from the buffer pointer to a managed object.
Dim result_obj As Object = Marshal.PtrToStructure(buffer, type_to_change)
'Free the memory that is allocated from the unmanaged memory.
Marshal.FreeHGlobal(buffer)
Return result_obj
End Function
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Structure PRINTER_DEFAULTS
Public pDatatype As String
Public pDevMode As Long
Public DesiredAccess As Long
End Structure
'Define the printer status constants.
Public Const ERROR_INSUFFICIENT_BUFFER = 122
Public Const PRINTER_STATUS_BUSY = &H200
Public Const PRINTER_STATUS_DOOR_OPEN = &H400000
Public Const PRINTER_STATUS_ERROR = &H2
Public Const PRINTER_STATUS_INITIALIZING = &H8000
Public Const PRINTER_STATUS_IO_ACTIVE = &H100
Public Const PRINTER_STATUS_MANUAL_FEED = &H20
Public Const PRINTER_STATUS_NO_TONER = &H40000
Public Const PRINTER_STATUS_NOT_AVAILABLE = &H1000
Public Const PRINTER_STATUS_OFFLINE = &H80
Public Const PRINTER_STATUS_OUT_OF_MEMORY = &H200000
Public Const PRINTER_STATUS_OUTPUT_BIN_FULL = &H800
Public Const PRINTER_STATUS_PAGE_PUNT = &H80000
Public Const PRINTER_STATUS_PAPER_JAM = &H8
Public Const PRINTER_STATUS_PAPER_OUT = &H10
Public Const PRINTER_STATUS_PAPER_PROBLEM = &H40
Public Const PRINTER_STATUS_PAUSED = &H1
Public Const PRINTER_STATUS_PENDING_DELETION = &H4
Public Const PRINTER_STATUS_PRINTING = &H400
Public Const PRINTER_STATUS_PROCESSING = &H4000
Public Const PRINTER_STATUS_TONER_LOW = &H20000
Public Const PRINTER_STATUS_USER_INTERVENTION = &H100000
Public Const PRINTER_STATUS_WAITING = &H2000
Public Const PRINTER_STATUS_WARMING_UP = &H10000
'Define the job status constants.
Public Const JOB_STATUS_PAUSED = &H1
Public Const JOB_STATUS_ERROR = &H2
Public Const JOB_STATUS_DELETING = &H4
Public Const JOB_STATUS_SPOOLING = &H8
Public Const JOB_STATUS_PRINTING = &H10
Public Const JOB_STATUS_OFFLINE = &H20
Public Const JOB_STATUS_PAPEROUT = &H40
Public Const JOB_STATUS_PRINTED = &H80
Public Const JOB_STATUS_DELETED = &H100
Public Const JOB_STATUS_BLOCKED_DEVQ = &H200
Public Const JOB_STATUS_USER_INTERVENTION = &H400
Public Const JOB_STATUS_RESTART = &H800
Public Function GetString(ByVal PtrStr As Long) As String
Dim StrBuff As String
StrBuff = New String(CChar(""), 256)
'Determine if a zero address is used.
If PtrStr = 0 Then
GetString = " "
Exit Function
End If
'Copy data from PtrStr to the buffer.
Dim PtrInt As IntPtr = New IntPtr(PtrStr)
StrBuff = Marshal.PtrToStringAuto(PtrInt)
'Remove any trailing nulls from the string.
GetString = StripNulls(StrBuff)
End Function
Public Function StripNulls(ByVal OriginalStr As String) As String
'Remove any trailing nulls from the input string.
If (InStr(OriginalStr, Chr(0)) > 0) Then
OriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
End If
'Return the modified string.
StripNulls = OriginalStr
End Function
Public Function CheckPrinterStatus(ByVal PI2Status As Long) As String
Dim tempStr As String
If PI2Status = 0 Then ' Return the "Ready" status.
CheckPrinterStatus = "Printer Status = Ready" & vbCrLf
Else
tempStr = ""
'Determine the printer state.
If (PI2Status And PRINTER_STATUS_BUSY) Then
tempStr = tempStr & "Busy "
End If
If (PI2Status And PRINTER_STATUS_DOOR_OPEN) Then
tempStr = tempStr & "Printer Door Open "
End If
If (PI2Status And PRINTER_STATUS_ERROR) Then
tempStr = tempStr & "Printer Error "
End If
If (PI2Status And PRINTER_STATUS_INITIALIZING) Then
tempStr = tempStr & "Initializing "
End If
If (PI2Status And PRINTER_STATUS_IO_ACTIVE) Then
tempStr = tempStr & "I/O Active "
End If
If (PI2Status And PRINTER_STATUS_MANUAL_FEED) Then
tempStr = tempStr & "Manual Feed "
End If
If (PI2Status And PRINTER_STATUS_NO_TONER) Then
tempStr = tempStr & "No Toner "
End If
If (PI2Status And PRINTER_STATUS_NOT_AVAILABLE) Then
tempStr = tempStr & "Not Available "
End If
If (PI2Status And PRINTER_STATUS_OFFLINE) Then
tempStr = tempStr & "Off Line "
End If
If (PI2Status And PRINTER_STATUS_OUT_OF_MEMORY) Then
tempStr = tempStr & "Out of Memory "
End If
If (PI2Status And PRINTER_STATUS_OUTPUT_BIN_FULL) Then
tempStr = tempStr & "Output Bin Full "
End If
If (PI2Status And PRINTER_STATUS_PAGE_PUNT) Then
tempStr = tempStr & "Page Punt "
End If
If (PI2Status And PRINTER_STATUS_PAPER_JAM) Then
tempStr = tempStr & "Paper Jam "
End If
If (PI2Status And PRINTER_STATUS_PAPER_OUT) Then
tempStr = tempStr & "Paper Out "
End If
If (PI2Status And PRINTER_STATUS_OUTPUT_BIN_FULL) Then
tempStr = tempStr & "Output Bin Full "
End If
If (PI2Status And PRINTER_STATUS_PAPER_PROBLEM) Then
tempStr = tempStr & "Page Problem "
End If
If (PI2Status And PRINTER_STATUS_PAUSED) Then
tempStr = tempStr & "Paused "
End If
If (PI2Status And PRINTER_STATUS_PENDING_DELETION) Then
tempStr = tempStr & "Pending Deletion "
End If
If (PI2Status And PRINTER_STATUS_PRINTING) Then
tempStr = tempStr & "Printing "
End If
If (PI2Status And PRINTER_STATUS_PROCESSING) Then
tempStr = tempStr & "Processing "
End If
If (PI2Status And PRINTER_STATUS_TONER_LOW) Then
tempStr = tempStr & "Toner Low "
End If
If (PI2Status And PRINTER_STATUS_USER_INTERVENTION) Then
tempStr = tempStr & "User Intervention "
End If
If (PI2Status And PRINTER_STATUS_WAITING) Then
tempStr = tempStr & "Waiting "
End If
If (PI2Status And PRINTER_STATUS_WARMING_UP) Then
tempStr = tempStr & "Warming Up "
End If
If Len(tempStr) = 0 Then
tempStr = "Unknown Status of " & PI2Status
End If
'Return the status.
CheckPrinterStatus = "Printer Status = " & tempStr & vbCrLf
End If
End Function
End Module
- In Solution Explorer, right-click the
Form1.vb file, and then click View
Code.
- In the Form1.vb file, replace the existing code with the
following sample code.
Imports System.Diagnostics.Debug
Imports System.Drawing.Printing
Imports System.Runtime.InteropServices
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
Friend WithEvents TextBox2 As System.Windows.Forms.TextBox
Friend WithEvents Command1 As System.Windows.Forms.Button
Friend WithEvents Command2 As System.Windows.Forms.Button
Friend WithEvents Command3 As System.Windows.Forms.Button
Friend WithEvents Timer1 As System.Windows.Forms.Timer
Friend WithEvents TextBox3 As System.Windows.Forms.TextBox
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container
Me.Command1 = New System.Windows.Forms.Button
Me.Command2 = New System.Windows.Forms.Button
Me.Command3 = New System.Windows.Forms.Button
Me.TextBox1 = New System.Windows.Forms.TextBox
Me.TextBox2 = New System.Windows.Forms.TextBox
Me.Timer1 = New System.Windows.Forms.Timer(Me.components)
Me.TextBox3 = New System.Windows.Forms.TextBox
Me.SuspendLayout()
'
'Command1
'
Me.Command1.Location = New System.Drawing.Point(352, 24)
Me.Command1.Name = "Command1"
Me.Command1.Size = New System.Drawing.Size(136, 23)
Me.Command1.TabIndex = 0
Me.Command1.Text = "Button1"
'
'Command2
'
Me.Command2.Location = New System.Drawing.Point(360, 112)
Me.Command2.Name = "Command2"
Me.Command2.Size = New System.Drawing.Size(128, 23)
Me.Command2.TabIndex = 1
Me.Command2.Text = "Button2"
'
'Command3
'
Me.Command3.Location = New System.Drawing.Point(360, 224)
Me.Command3.Name = "Command3"
Me.Command3.Size = New System.Drawing.Size(128, 23)
Me.Command3.TabIndex = 2
Me.Command3.Text = "Button3"
'
'TextBox1
'
Me.TextBox1.Location = New System.Drawing.Point(8, 24)
Me.TextBox1.Multiline = True
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.Size = New System.Drawing.Size(320, 80)
Me.TextBox1.TabIndex = 3
Me.TextBox1.Text = "TextBox1"
'
'TextBox2
'
Me.TextBox2.Location = New System.Drawing.Point(8, 120)
Me.TextBox2.Multiline = True
Me.TextBox2.Name = "TextBox2"
Me.TextBox2.Size = New System.Drawing.Size(320, 80)
Me.TextBox2.TabIndex = 4
Me.TextBox2.Text = "TextBox2"
'
'Timer1
'
Me.Timer1.Enabled = True
'
'TextBox3
'
Me.TextBox3.Location = New System.Drawing.Point(8, 216)
Me.TextBox3.Multiline = True
Me.TextBox3.Name = "TextBox3"
Me.TextBox3.ScrollBars = System.Windows.Forms.ScrollBars.Vertical
Me.TextBox3.Size = New System.Drawing.Size(320, 80)
Me.TextBox3.TabIndex = 5
Me.TextBox3.Text = "TextBox3"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(504, 317)
Me.Controls.Add(Me.TextBox3)
Me.Controls.Add(Me.TextBox2)
Me.Controls.Add(Me.TextBox1)
Me.Controls.Add(Me.Command3)
Me.Controls.Add(Me.Command2)
Me.Controls.Add(Me.Command1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
#End Region
Public Shared Sub main()
Dim PrntInfo As New Form1
PrntInfo.ShowDialog()
End Sub
Private Sub Command1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Command1.Click
'Enable the timer to start printer status checks.
Timer1.Enabled = True
Timer1.Start()
'Enable and disable the start and stop buttons.
Command1.Enabled = False
Command2.Enabled = True
Command3.Enabled = True
End Sub
Private Sub Command2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Command2.Click
'Disable the timer to stop additional printer checks.
Timer1.Enabled = False
'Enable and disable the start and stop buttons.
Command1.Enabled = True
Command2.Enabled = False
Command3.Enabled = True
API = Nothing
End Sub
Private Sub Command3_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Command3.Click
'Clear the text boxes to display the printer status.
TextBox1.Text = ""
TextBox2.Text = ""
TextBox3.Text = ""
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles MyBase.Load
'Initialize captions for the buttons.
Command1.Text = "Start"
Command2.Text = "Stop"
Command3.Text = "Clear"
'Clear the text boxes to display the printer status.
TextBox1.Text = ""
TextBox2.Text = ""
TextBox3.Text = ""
Command1.Enabled = True
'Disable the stop and clear buttons.
Command2.Enabled = False
Command3.Enabled = False
'Set the timer interval to 500 milliseconds to examine the printer status.
Timer1.Enabled = False
Timer1.Interval = 500
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Timer1.Tick
Dim PrinterStatus As String
Dim JobStatus As String
Dim ErrorInfo As String
'Clear the text boxes to display the status.
TextBox1.Text = ""
TextBox2.Text = ""
TextBox3.Text = ""
'Call the CheckPrinter function.
TextBox1.Text = CheckPrinter(PrinterStatus, JobStatus)
TextBox2.Text = PrinterStatus
TextBox3.Text = JobStatus
End Sub
Public Function CheckPrinter(ByRef PrinterStr As String, _
ByRef JobStr As String) As String
Dim hPrinter As IntPtr
Dim ByteBuf As Long
Dim BytesNeeded As Int32
Dim PI2 As New PRINTER_INFO_2
Dim intCount As Long
Dim JI2(intCount) As JOB_INFO_2
Dim PrinterInfo() As Byte
Dim JobInfo() As Byte
Dim result As Long
Dim LastError As Long
Dim PrinterName As String
Dim tempStr As String
Dim NumJI2 As Int32
Dim pDefaults As PRINTER_DEFAULTS
'Set a default return value if no errors occur.
CheckPrinter = "Printer info retrieved!"
Dim PD As New PrintDocument
PrinterName = PD.PrinterSettings.PrinterName
'Set the access security setting that you want.
pDefaults.DesiredAccess = PRINTER_ACCESS_USE
'Call the API to obtain a handle to the printer.
'If an error occurs, display the error.
result = API.OpenPrinter(PrinterName, hPrinter, pDefaults)
If result = 0 Then
CheckPrinter = "Cannot open printer " & PrinterName & _
", Error: " & Marshal.GetLastWin32Error()
Exit Function
End If
'Initialize the BytesNeeded variable.
BytesNeeded = 0
'Clear the error object.
Err.Clear()
'Determine the buffer size that is required to obtain the printer information.
result = API.GetPrinter(hPrinter, 2, 0&, 0, BytesNeeded)
'Display the error message that you receive when you call the GetPrinter function,
'and then close the printer handle.
If Marshal.GetLastWin32Error() <> ERROR_INSUFFICIENT_BUFFER Then
CheckPrinter = " > GetPrinter Failed on initial call! <"
API.ClosePrinter(hPrinter)
Exit Function
End If
ReDim PrinterInfo(BytesNeeded)
ByteBuf = BytesNeeded
'Call the GetPrinter function to obtain the status.
result = API.GetPrinter(hPrinter, 2, PrinterInfo(0), ByteBuf, _
BytesNeeded)
'Check for any errors.
If result = 0 Then
'Get the error.
LastError = Marshal.GetLastWin32Error()
'Display the error message, and then close the printer handle.
CheckPrinter = "Could not get Printer Status! Error = " _
& LastError
API.ClosePrinter(hPrinter)
Exit Function
End If
'Copy the contents of the printer status byte array into a
'PRINTER_INFO_2 structure.
PI2 = CType(DatatoDeserial(PrinterInfo, GetType(PRINTER_INFO_2), 1), PRINTER_INFO_2)
PrinterStr = CheckPrinterStatus(PI2.Status)
'Add the printer name, the driver, and the port to the text box.
PrinterStr = PrinterStr & "Printer Name = " & _
GetString(PI2.pPrinterName) & vbCrLf
PrinterStr = PrinterStr & "Printer Driver Name = " & _
GetString(PI2.pDriverName) & vbCrLf
PrinterStr = PrinterStr & "Printer Port Name = " & _
GetString(PI2.pPortName) & vbCrLf
'Call the API to obtain the buffer size that is required.
result = API.EnumJobs(hPrinter, 0, &HFFFFFFFF, 2, JobInfo, 0, BytesNeeded, NumJI2)
If result = 0 Then
'Display the error, and then close the printer handle.
LastError = Marshal.GetLastWin32Error()
CheckPrinter = " > EnumJobs Failed on initial call! < Error = " _
& LastError
API.ClosePrinter(hPrinter)
Exit Function
End If
'If no current jobs exist, display the message.
If BytesNeeded = 0 Then
JobStr = "No Print Jobs!"
Else
'Resize the byte array to hold information about the print jobs.
ReDim JobInfo(BytesNeeded - 1)
'Call the API to obtain the print job information.
result = API.EnumJobs(hPrinter, 0, &HFFFFFFFF, 2, JobInfo, _
BytesNeeded, BytesNeeded, NumJI2)
'Check for errors.
If result = 0 Then
'Display the error, and then close the printer handle.
LastError = Marshal.GetLastWin32Error()
CheckPrinter = " > EnumJobs Failed on second call! < Error = " _
& LastError
API.ClosePrinter(hPrinter)
Exit Function
End If
ReDim JI2(NumJI2)
'Copy the contents of print job info byte array into a
'JOB_INFO_2 structure.
Try
For intCount = 0 To NumJI2 - 1 ' Loop through jobs and obtain the job information.
Dim test As Object
JI2(intCount) = CType(DatatoDeserial(JobInfo, _
GetType(JOB_INFO_2), intCount + 1), JOB_INFO_2)
JobStr = JobStr & "Job ID = " & JI2(intCount).PrinterJobId & _
vbCrLf & "Total Pages = " & JI2(intCount).TotalPages & vbCrLf
tempStr = ""
'Check for a ready state.
If JI2(intCount).pStatus = 0& Then ' If pStatus is Null, check Status.
If JI2(intCount).pStatus = 0 Then
tempStr = tempStr & "Ready! " & vbCrLf
Else 'Check for the various print job states.
If (JI2(intCount).pStatus And JOB_STATUS_SPOOLING) Then
tempStr = tempStr & "Spooling "
End If
If (JI2(intCount).pStatus And JOB_STATUS_OFFLINE) Then
tempStr = tempStr & "Off line "
End If
If (JI2(intCount).pStatus And JOB_STATUS_PAUSED) Then
tempStr = tempStr & "Paused "
End If
If (JI2(intCount).pStatus And JOB_STATUS_ERROR) Then
tempStr = tempStr & "Error "
End If
If (JI2(intCount).pStatus And JOB_STATUS_PAPEROUT) Then
tempStr = tempStr & "Paper Out "
End If
If (JI2(intCount).pStatus And JOB_STATUS_PRINTING) Then
tempStr = tempStr & "Printing "
End If
If (JI2(intCount).pStatus And JOB_STATUS_USER_INTERVENTION) Then
tempStr = tempStr & "User Intervention Needed "
End If
If Len(tempStr) = 0 Then
tempStr = "Unknown Status of " & JI2(intCount).PrinterStatus
End If
End If
Else
tempStr = Pointer_to_String(JI2(intCount).pStatus)
End If
'Report the job status.
JobStr = JobStr & tempStr & vbCrLf
Next intCount
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End If
'Close the printer handle.
API.ClosePrinter(hPrinter)
End Function
End Class
- On the Build menu, click Build
Solution.
- Click Start, and then click
Printers and Faxes.
Note On a computer that is running Microsoft Windows 2000, click
Start, point to Settings, and then click
Printers. - In the Printers and Faxes window,
double-click the icon for the printer whose queue you want to view.
Note In the Printers window on a computer that is
running Windows 2000, double-click the icon for the printer whose queue you
want to view. - On the Printer menu in the
PrinterName dialog box, click Pause
Printing.
Note You may not be able to pause the print queue on a network
printer. - On the Debug menu in Visual Studio .NET,
click Start to run the application.
- In the Form1 form, click
Start to obtain the printer information and the list of jobs
in the queue.
back to the topTroubleshootingOnly a specific device driver can obtain accurate printer status
information. This sample code obtains the same status that the Windows spooler
reports. The exact status that is reported may vary for different
printers and for different drivers. back to the topREFERENCESFor more information about the PrinterSettings class, visit the following Microsoft Developer Network (MSDN) Web
site:
For more information, click the following article number to view the article in the Microsoft Knowledge Base:
202480
How to determine printer status
and print job status from Visual Basic
back to the
top
Modification Type: | Minor | Last Reviewed: | 2/13/2006 |
---|
Keywords: | kbvs2005doesnotapply kbvs2005swept kbprinters kbMarshal kbinterop kbHOWTOmaster KB821769 kbAudDeveloper kbAudEndUser |
---|
|
|
©2004 Microsoft Corporation. All rights reserved.
|
|