SetPrinter for network printers

F

Francisco Araujo

I have been trying to change printer settings thru SetPrinter API and it
works successfully for local printers, but with network printers i don't get
neither an error message or anything else.

Here is my code.

'Class DevMode

' Used to get data from PrintDialog thru a pointer using Marshal .NET
functionality.

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _

Friend Class DevMode

<VBFixedString(32), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=32)>
Public dmDeviceName As String

Public dmSpecVersion As Short

Public dmDriverVersion As Short

Public dmSize As Short

Public dmDriverExtra As Short

Public dmFields As Integer

Public dmOrientation As Short

Public dmPaperSize As Short

Public dmPaperLength As Short

Public dmPaperWidth As Short

Public dmScale As Short

Public dmCopies As Short

Public dmDefaultSource As Short

Public dmPrintQuality As Short

Public dmColor As Short

Public dmDuplex As Short

Public dmYResolution As Short

Public dmTTOption As Short

Public dmCollate As Short

<VBFixedString(32), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=32)>
Public dmFormName As String

Public dmUnusedPadding As Short

Public dmBitsPerPel As Short

Public dmPelsWidth As Integer

Public dmPelsHeight As Integer

Public dmDisplayFlags As Integer

Public dmDisplayFrequency As Integer

End Class

<Serializable(), StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
_

Friend Structure PRINTER_INFO_2

Public pServerName As String

Public pPrinterName As String

Public pShareName As String

Public pPortName As String

Public pDriverName As String

Public pComment As String

Public pLocation As String

Public pDevMode As IntPtr

Public pSepFile As String

Public pPrintProcessor As String

Public pDatatype As String

Public pParameters As String

Public pSecurityDescriptor As IntPtr

Public Attributes As System.UInt32

Public Priority As System.UInt32

Public DefaultPriority As System.UInt32

Public StartTime As System.UInt32

Public UntilTime As System.UInt32

Public Status As System.UInt32

Public cJobs As System.UInt32

Public AveragePPM As System.UInt32

End Structure

<StructLayout(LayoutKind.Sequential)> _

Private Structure PRINTER_DEFAULTS

Public pDatatype As IntPtr

Public pDevMode As IntPtr

Public DesiredAccess As Integer

End Structure

Private Enum PrinterAccessRights

PRINTER_ACCESS_ADMINISTER = &H4

PRINTER_ACCESS_USE = &H8

PRINTER_ALL_ACCESS = &HF000C

End Enum

'* DEVMODE collation selections

Private Const DMCOLLATE_FALSE As Short = 0

Private Const DMCOLLATE_TRUE As Short = 1

<DllImport("winspool.drv", EntryPoint:="OpenPrinterW", _

CharSet:=CharSet.Auto, SetLastError:=True, ExactSpelling:=True, _

CallingConvention:=CallingConvention.StdCall)> _

Private Shared Function OpenPrinter( _

ByVal pPrinterName As String, ByRef hPrinter As IntPtr, _

ByVal pDefault As IntPtr) As Boolean

End Function

<DllImport("winspool.drv", EntryPoint:="OpenPrinterW", _

CharSet:=CharSet.Auto, SetLastError:=True, ExactSpelling:=True, _

CallingConvention:=CallingConvention.StdCall)> _

Private Shared Function OpenPrinter( _

ByVal pPrinterName As String, ByRef hPrinter As IntPtr, _

ByRef pDefault As PRINTER_DEFAULTS) As Boolean

End Function

<DllImport("winspool.drv", CharSet:=CharSet.Auto, _

SetLastError:=True, ExactSpelling:=True, _

CallingConvention:=CallingConvention.StdCall)> _

Private Shared Function ClosePrinter( _

ByVal hPrinter As IntPtr) As Boolean

End Function

<DllImport("winspool.drv", EntryPoint:="GetPrinterW", _

CharSet:=CharSet.Auto, SetLastError:=True, ExactSpelling:=True, _

CallingConvention:=CallingConvention.StdCall)> _

Private Shared Function GetPrinter( _

ByVal hPrinter As IntPtr, ByVal dwLevel As Integer, _

ByVal pPrinter As IntPtr, ByVal cbBuf As Integer, _

ByRef pcbNeeded As Integer) As Boolean

End Function

<DllImport("winspool.drv", entrypoint:="SetPrinterW", _

CharSet:=CharSet.Auto, SetLastError:=True, ExactSpelling:=True, _

CallingConvention:=CallingConvention.StdCall)> _

Private Shared Function SetPrinter( _

ByVal hPrinter As IntPtr, ByVal dwLevel As Integer, _

ByVal pPrinter As IntPtr, ByVal Command As Integer) As Boolean

End Function

Public Sub ChangeSettings()

Dim hPrinter As IntPtr

Dim pPrinterInfo As IntPtr

Dim PrinterInfo As PRINTER_INFO_2

Dim PrinterName As String

Dim MyPrintDialog As New PrintDialog

If MyPrintDialog.ShowDialog() = DialogResult.OK Then

PrinterName = MyPrintDialog.PrinterSettings.PrinterName

hPrinter = OpenPrinter(PrinterName)

pPrinterInfo = IntPtr.Zero

Try

Dim needed As Integer

GetPrinter(hPrinter, 2, IntPtr.Zero, 0, needed)

If needed <= 0 Then

Throw New Exception("It failed getting printer settings.")

End If

pPrinterInfo = Marshal.AllocHGlobal(needed)

Dim temp As Integer

If Not GetPrinter(hPrinter, 2, pPrinterInfo, needed, temp) Then

Throw New Win32Exception(Marshal.GetLastWin32Error())

End If

'* Marshalling it does in type

PrinterInfo = CType(Marshal.PtrToStructure(pPrinterInfo,
GetType(PRINTER_INFO_2)), PRINTER_INFO_2)

Dim Copies As Short = CType(New Random(Minute(Now) + Second(Now)).Next(1,
9999), Short)

Dim m_dvmode As New DevMode

m_dvmode = CType(Marshal.PtrToStructure(PrinterInfo.pDevMode,
GetType(DevMode)), DevMode)

With m_dvmode

..dmCopies = Copies

..dmCollate = CType(IIf(Copies Mod 2 = 0, DMCOLLATE_TRUE, DMCOLLATE_FALSE),
Short)

..dmOrientation = CType(IIf(Copies Mod 2 = 0, EOrientation.eoLandscape,
EOrientation.eoPortrait), Short)

End With

Marshal.StructureToPtr(m_dvmode, PrinterInfo.pDevMode, True)

If Not SetPrinter(hPrinter, 2, pPrinterInfo, 0) Then

Throw New Win32Exception(Marshal.GetLastWin32Error())

End If

Finally

Marshal.FreeHGlobal(pPrinterInfo)

End Try

'''Serialization.SaveObjectToFile("c:\temp\test.before.txt", pinfo)

ClosePrinter(hPrinter)

End If

End Sub

Private Function OpenPrinter(ByVal PrinterName As String) As IntPtr

Dim hPrinter As IntPtr

Dim pd As New PRINTER_DEFAULTS

Dim pPrinterDefaults As IntPtr = IntPtr.Zero

With pd

..DesiredAccess = PrinterAccessRights.PRINTER_ALL_ACCESS

..pDevMode = GetPrinterInfo(PrinterName).pDevMode

..pDatatype = IntPtr.Zero

End With

'Marshal.StructureToPtr(pd, pPrinterDefaults, True)

If Not OpenPrinter(PrinterName, hPrinter, pd) Then 'IntPtr.Zero) Then

Throw New Win32Exception(Marshal.GetLastWin32Error())

End If

Return hPrinter

End Function

Private Function GetPrinterInfo(ByVal PrinterName As String) As
PRINTER_INFO_2

Dim hPrinter As IntPtr

If Not OpenPrinter(PrinterName, hPrinter, IntPtr.Zero) Then

Throw New Win32Exception(Marshal.GetLastWin32Error())

End If

Dim pPrinterInfo As IntPtr = IntPtr.Zero

Try

Dim needed As Integer

GetPrinter(hPrinter, 2, IntPtr.Zero, 0, needed)

If needed <= 0 Then

Throw New Exception("It failed getting printer settings.")

End If

pPrinterInfo = Marshal.AllocHGlobal(needed)

Dim temp As Integer

If Not GetPrinter(hPrinter, 2, pPrinterInfo, needed, temp) Then

Throw New Win32Exception(Marshal.GetLastWin32Error())

End If

'* Marshalling it does in type

Dim printerInfo As PRINTER_INFO_2 = _

CType(Marshal.PtrToStructure( _

pPrinterInfo, GetType(PRINTER_INFO_2)), PRINTER_INFO_2)

Return printerInfo

Finally

ClosePrinter(hPrinter)

Marshal.FreeHGlobal(pPrinterInfo)

End Try

End Function
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top