Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / October 2004

Tip: Looking for answers? Try searching our database.

Printer HardwareID

Thread view: 
Enable EMail Alerts  Start New Thread
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 Magazines

Get 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 ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.