.NET Forum / .NET Framework / New Users / October 2004
Printer HardwareID
|
|
Thread rating:  |
Eric Howard - 04 Oct 2004 04:11 GMT I'm trying to get the hardware ID for the printers on a machine. Below is my code. The problem appears to get in my second call to GetPrinterDriver. I think it may be a problem with the DRIVER_INFO_6 definition. Any help would be appreciated.
Thanks in Advance.
 Signature Eric Howard Director of Process Automation Synergis Technologies, Inc.
<StructLayout(LayoutKind.Sequential)> _ Private Structure DRIVER_INFO_6 Public cVersion As Int32 Public pName As String ' QMS 810 Public pEnvironment As String ' Win32 x86 Public pDriverPath As String ' c:\drivers\pscript.dll Public pDataFile As String ' c:\drivers\QMS810.PPD Public pConfigFile As String ' c:\drivers\PSCRPTUI.DLL Public pHelpFile As String ' c:\drivers\PSCRPTUI.HLP Public pDependentFiles As String ' Public pMonitorName As String ' "PJL monitor" Public pDefaultDataType As String ' "EMF" Public pszzPreviousNames As String Public ftDriverDate As FILETIME Public dwlDriverVersion As Int32 Public pszMfgName As String Public pszOEMUrl As String Public pszHardwareID As String Public pszProvider As String End Structure
<DllImport("winspool.drv", EntryPoint:="OpenPrinterA", _ SetLastError:=True, CharSet:=CharSet.Ansi, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Public Function OpenPrinter(ByVal pPrinterName As String, _ ByRef phPrinter As Int32, _ ByVal pDefault As Int32 _ ) As Boolean
End Function
<DllImport("winspool.drv", EntryPoint:="ClosePrinter", _ SetLastError:=True, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Public Function ClosePrinter(ByVal hPrinter As Int32) As Boolean
End Function
<DllImport("winspool.drv", EntryPoint:="GetPrinterDriverA", _ SetLastError:=True, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Private Function GetPrinterDriver(ByVal hPrinter As Int32, _ ByVal pEnvironment As String, _ ByVal Level As Int32, _ ByRef pDriverInfo As DRIVER_INFO_6, _ ByVal cdBuf As Int32, _ ByRef pcbNeeded As Int32 _ ) As Boolean
End Function
Sub Main() Dim lIndex As Integer Dim sName As String
Dim hResult As Int32 Dim hPrinter As Int32 Dim vInfo As DRIVER_INFO_6 Dim lBytesNeeded As Integer
For lIndex = 0 To PrinterSettings.InstalledPrinters.Count - 1 sName = PrinterSettings.InstalledPrinters.Item(lIndex)
If Not OpenPrinter(sName, hPrinter, 0) Then Throw New ApiException(Marshal.GetLastWin32Error, "OpenPrinter") Else Try GetPrinterDriver(hPrinter, vbNullString, 6, vInfo, 0, lBytesNeeded) GetPrinterDriver(hPrinter, vbNullString, 6, vInfo, lBytesNeeded, lBytesNeeded) Catch ex As Exception If ClosePrinter(hPrinter) Then Throw ex Else Throw New ApiException("ClosePrinter") End If End Try End If
Console.WriteLine(sName) Next
Console.ReadLine() End Sub
Imran Koradia - 04 Oct 2004 05:44 GMT Your structure is fine. I usually prefer to use IntPtr for handles although its ok to use Integer as well. More importantly, since the function requires a pointer to a structure, we declare the API prototype to take in an IntPtr which will point to a buffer to store the structure that is returned by the function. Then we use Marshal.PtrToStructure to retrieve the structure from the pointer. here's the code:
<DllImport("winspool.drv", EntryPoint:="OpenPrinterA", _ SetLastError:=True, CharSet:=CharSet.Ansi, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function OpenPrinter(ByVal pPrinterName As String, _ ByRef phPrinter As IntPtr, _ ByVal pDefault As Int32 _ ) As Boolean End Function
<DllImport("winspool.drv", EntryPoint:="ClosePrinter", _ SetLastError:=True, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function ClosePrinter(ByVal hPrinter As IntPtr) As Boolean
End Function
<DllImport("winspool.drv", EntryPoint:="GetPrinterDriverA", _ SetLastError:=True, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function GetPrinterDriver(ByVal hPrinter As IntPtr, _ ByVal pEnvironment As String, _ ByVal Level As Int32, _ ByVal pDriverInfo As IntPtr, _ ByVal cdBuf As Int32, _ ByRef pcbNeeded As Int32 _ ) As Boolean End Function
Private Sub GetPrinterInfo( ) Dim lIndex As Integer Dim sName As String
Dim hResult As Int32 Dim hPrinter As IntPtr Dim InfoPtr As IntPtr Dim lBytesNeeded As Integer
For lIndex = 0 To Printing.PrinterSettings.InstalledPrinters.Count - 1 sName = Printing.PrinterSettings.InstalledPrinters.Item(lIndex)
If Not OpenPrinter(sName, hPrinter, 0) Then MessageBox.Show("Could not open printer") End If
' Allocate an unmanaged buffer in which to store the returned structure ' InfoPtr is the pointer pointing to that buffer InfoPtr = Marshal.AllocHGlobal( _ Marshal.SizeOf(GetType(DRIVER_INFO_6)))
GetPrinterDriver( _ hPrinter, vbNullString, 6, InfoPtr, _ 0, lBytesNeeded)
GetPrinterDriver( _ hPrinter, vbNullString, 6, InfoPtr, _ lBytesNeeded, lBytesNeeded)
Dim Info As DRIVER_INFO_6 = CType( _ Marshal.PtrToStructure( _ InfoPtr, GetType(DRIVER_INFO_6)), _ DRIVER_INFO_6)
Console.WriteLine(Info.pName) Console.WriteLine(Info.pDriverPath) Console.WriteLine(Info.pDataFile)
If Not ClosePrinter(hPrinter) Then MessageBox.Show("Could not close printer") End If
Marshal.FreeHGlobal(InfoPtr)
Next End Sub
hope that helps.. Imran.
> I'm trying to get the hardware ID for the printers on a machine. Below is > my [quoted text clipped - 4 lines] > > Thanks in Advance. Eric Howard - 07 Oct 2004 15:05 GMT Thanks. That got me further, however I get an error at the Marshal.PtrToStructure line. The error is:
An unhandled exception of type 'System.NullReferenceException' occurred in mscorlib.dll
Additional information: Object reference not set to an instance of an object.
Can you offer any insite?
Thanks In Advance,
Eric
> Your structure is fine. I usually prefer to use IntPtr for handles although > its ok to use Integer as well. [quoted text clipped - 94 lines] > > > > Thanks in Advance. Imran Koradia - 08 Oct 2004 03:56 GMT Are you getting that error for the exact same code? I tried it on my machine and it's working fine. If you have something different, could you post the code so that we could look into whats wrong?
Imran.
> Thanks. That got me further, however I get an error at the > Marshal.PtrToStructure line. The error is: [quoted text clipped - 116 lines] >> > >> > Thanks in Advance. Eric Howard - 08 Oct 2004 14:11 GMT I create a console app to test this code. Here's the code for the module.
Imports System.Drawing.Printing Imports System.Runtime.InteropServices
Module Module1
<StructLayout(LayoutKind.Sequential)> _ Private Structure DRIVER_INFO_6 Public cVersion As Int32 Public pName As String ' QMS 810 Public pEnvironment As String ' Win32 x86 Public pDriverPath As String ' c:\drivers\pscript.dll Public pDataFile As String ' c:\drivers\QMS810.PPD Public pConfigFile As String ' c:\drivers\PSCRPTUI.DLL Public pHelpFile As String ' c:\drivers\PSCRPTUI.HLP Public pDependentFiles As String ' Public pMonitorName As String ' "PJL monitor" Public pDefaultDataType As String ' "EMF" Public pszzPreviousNames As String Public ftDriverDate As FILETIME Public dwlDriverVersion As Int64 Public pszMfgName As String Public pszOEMUrl As String Public pszHardwareID As String Public pszProvider As String End Structure
<DllImport("winspool.drv", EntryPoint:="OpenPrinterA", _ SetLastError:=True, CharSet:=CharSet.Ansi, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Public Function OpenPrinter(ByVal pPrinterName As String, _ ByRef phPrinter As IntPtr, _ ByVal pDefault As Int32 _ ) As Boolean End Function
<DllImport("winspool.drv", EntryPoint:="ClosePrinter", _ SetLastError:=True, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Public Function ClosePrinter(ByVal hPrinter As IntPtr) As Boolean
End Function
<DllImport("winspool.drv", EntryPoint:="GetPrinterDriverA", _ SetLastError:=True, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Public Function GetPrinterDriver(ByVal hPrinter As IntPtr, _ ByVal pEnvironment As String, _ ByVal Level As Int32, _ ByVal pDriverInfo As IntPtr, _ ByVal cdBuf As Int32, _ ByRef pcbNeeded As Int32 _ ) As Boolean End Function
Sub Main() Dim lIndex As Integer Dim sName As String
Dim hResult As Int32 Dim hPrinter As IntPtr Dim InfoPtr As IntPtr Dim lBytesNeeded As Integer
For lIndex = 0 To PrinterSettings.InstalledPrinters.Count - 1 sName = PrinterSettings.InstalledPrinters.Item(lIndex)
Console.WriteLine(sName)
If Not OpenPrinter(sName, hPrinter, 0) Then Console.WriteLine("Could not open printer") End If
' Allocate an unmanaged buffer in which to store the returned structure ' InfoPtr is the pointer pointing to that buffer InfoPtr = Marshal.AllocHGlobal( _ Marshal.SizeOf(GetType(DRIVER_INFO_6)))
GetPrinterDriver( _ hPrinter, vbNullString, 6, InfoPtr, _ 0, lBytesNeeded)
GetPrinterDriver( _ hPrinter, vbNullString, 6, InfoPtr, _ lBytesNeeded, lBytesNeeded)
Dim Info As DRIVER_INFO_6 Info = CType( _ Marshal.PtrToStructure( _ InfoPtr, GetType(DRIVER_INFO_6)), _ DRIVER_INFO_6)
Console.WriteLine(vbTab + Info.pName) Console.WriteLine(vbTab + Info.pDriverPath) Console.WriteLine(vbTab + Info.pDataFile) Console.WriteLine(vbTab + Info.pszHardwareID) Console.WriteLine()
If Not ClosePrinter(hPrinter) Then Console.WriteLine("Could not close printer") End If
Marshal.FreeHGlobal(InfoPtr)
Next
Console.ReadLine() End Sub
End Module
> Are you getting that error for the exact same code? I tried it on my machine > and it's working fine. If you have something different, could you post the [quoted text clipped - 122 lines] > >> > > >> > Thanks in Advance. Eric Howard - 08 Oct 2004 14:33 GMT My Bad. I just re-ran the code I just posted and everything worked. Maybe my machine needed a rest. :-) Thanks for your help.
> Are you getting that error for the exact same code? I tried it on my machine > and it's working fine. If you have something different, could you post the [quoted text clipped - 122 lines] > >> > > >> > Thanks in Advance. Imran Koradia - 08 Oct 2004 14:58 GMT > My Bad. I just re-ran the code I just posted and everything worked. Maybe my > machine needed a rest. :-) Thanks for your help. And probably you too :)
Glad that worked out :)
Eric Howard - 13 Oct 2004 14:15 GMT You are correct about me needing more rest.
I'm still having some problems. The code runs fine for the meat of the process however when the application ends, I get the following error:
The instruction at "0x00000000" referenced memory at "0x00000000". The memory could not be "read".
I'm assuming this is some sort of memory allocation error or such. Where am I not clearing things properly?
Below is the code I am using for a console application:
Imports System.Drawing.Printing Imports System.Runtime.InteropServices
Module Module1
<StructLayout(LayoutKind.Sequential)> _ Public Structure DRIVER_INFO_6 Public cVersion As Int32 Public pName As String ' QMS 810 Public pEnvironment As String ' Win32 x86 Public pDriverPath As String ' c:\drivers\pscript.dll Public pDataFile As String ' c:\drivers\QMS810.PPD Public pConfigFile As String ' c:\drivers\PSCRPTUI.DLL Public pHelpFile As String ' c:\drivers\PSCRPTUI.HLP Public pDependentFiles As String ' Public pMonitorName As String ' "PJL monitor" Public pDefaultDataType As String ' "EMF" Public pszzPreviousNames As String Public ftDriverDate As FILETIME Public dwlDriverVersion As Int64 Public pszMfgName As String Public pszOEMUrl As String Public pszHardwareID As String Public pszProvider As String End Structure
<DllImport("winspool.drv", EntryPoint:="OpenPrinterA", _ SetLastError:=True, CharSet:=CharSet.Ansi, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Public Function OpenPrinter(ByVal pPrinterName As String, _ ByRef phPrinter As IntPtr, _ ByVal pDefault As Integer _ ) As Boolean End Function
<DllImport("winspool.drv", EntryPoint:="ClosePrinter", _ SetLastError:=True, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Public Function ClosePrinter(ByVal hPrinter As IntPtr) As Boolean
End Function
<DllImport("winspool.drv", EntryPoint:="GetPrinterDriverA", _ SetLastError:=True, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Public Function GetPrinterDriver(ByVal hPrinter As IntPtr, _ ByVal pEnvironment As String, _ ByVal Level As Integer, _ ByVal pDriverInfo As IntPtr, _ ByVal cdBuf As Integer, _ ByRef pcbNeeded As Integer _ ) As Boolean End Function
Sub Main() Dim sName As String
For Each sName In PrinterSettings.InstalledPrinters Console.WriteLine(sName) Dim bVirtual As Boolean = IsPrinterVirtual(sName)
Console.WriteLine(vbTab + "IsVirtual?: " + bVirtual.ToString + vbTab)
Console.ReadLine() Next
Console.Write("Done: ") Console.ReadLine() End Sub
Public Function IsPrinterVirtual(ByVal printerName As String) As Boolean Dim hPrinter As IntPtr = IntPtr.Zero Dim InfoPtr As IntPtr = IntPtr.Zero Dim lBytesNeeded As Integer = 0 Dim bReturn As Boolean = True
Try If Not OpenPrinter(printerName, hPrinter, 0) Then Console.WriteLine("Could not open printer") End If
' Allocate an unmanaged buffer in which to store the returned structure ' InfoPtr is the pointer pointing to that buffer InfoPtr = Marshal.AllocHGlobal( _ Marshal.SizeOf(GetType(DRIVER_INFO_6)))
GetPrinterDriver( _ hPrinter, vbNullString, 6, InfoPtr, _ 0, lBytesNeeded)
GetPrinterDriver( _ hPrinter, vbNullString, 6, InfoPtr, _ lBytesNeeded, lBytesNeeded)
If Not ClosePrinter(hPrinter) Then Console.WriteLine("Could not close printer") End If
Dim Info As DRIVER_INFO_6 Info = CType( _ Marshal.PtrToStructure( _ InfoPtr, GetType(DRIVER_INFO_6)), _ DRIVER_INFO_6)
If Info.pszHardwareID = Nothing Then bReturn = True Else bReturn = False End If
Marshal.FreeHGlobal(InfoPtr)
Catch ex As Exception Console.WriteLine(ex.Message) End Try
Return bReturn
End Function
End Module
Imran Koradia - 14 Oct 2004 14:18 GMT Eric,
Instead of Marshal.FreeHGlobal, try using Marshal.DestroyStructure:
Marshal.DestroyStructure(InfoPtr, GetType(DRIVER_INFO_6))
hope that helps.. Imran.
> You are correct about me needing more rest. > [quoted text clipped - 135 lines] > > End Module Eric Howard - 20 Oct 2004 18:21 GMT That made it worse. I'm going back to Marshal.FreeHGlobal.
Thanks
> Eric, > [quoted text clipped - 146 lines] > > > > End Module
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|