T
Terry Olsen
More EnumPrinters help wanted. I wrote the following code from an example I
found on .NET 247. Anyhow, look at the For/Next loop. The first iteration,
it works fine. The messagebox shows me the share name of a printer. But on
the 2nd iteration, the Marshal.PtrToStructure line throws an
AccessViolationException was unhandled (Attempted to read or write protected
memory. This is often an indication that other memory is corrupt.). Can
anyone see what may be wrong in the code?
Thanks.
Imports System.Runtime.InteropServices
Module EnumPrinters
Public Function GetPrintShares(ByVal Server As String) As ArrayList
Dim pcbNeeded As Int32
Dim pcbReturned As Int32
Dim outC As IntPtr = IntPtr.Zero
Dim tmp As Integer = (EnumPrinters(PrinterEnum.peNAME Or
PrinterEnum.peSHARED, _
"", 2, outC, 0, pcbNeeded, pcbReturned))
outC = Marshal.AllocHGlobal(pcbNeeded)
tmp = EnumPrinters(PrinterEnum.peNAME Or PrinterEnum.peSHARED, _
"", 2, outC, pcbNeeded, pcbNeeded, pcbReturned)
MsgBox(tmp & " - " & pcbNeeded & " - " & pcbReturned)
Dim manyPR(pcbReturned) As PRINTER_INFO_2
Dim currentP As IntPtr = outC
Dim MyAL As New ArrayList
For i As Integer = 1 To pcbReturned
manyPR(i) = Marshal.PtrToStructure(currentP, manyPR(i).GetType)
MsgBox(manyPR(i).pShareName)
MyAL.Add(manyPR(i).pShareName)
currentP = IntPtr.op_Explicit(currentP.ToInt32 +
Marshal.SizeOf(manyPR(i).GetType))
Next
Marshal.FreeHGlobal(outC)
Return MyAL
End Function
Private Declare Auto Function EnumPrinters Lib "winspool.drv" Alias
"EnumPrintersA" _
(ByVal Flags As Int32, _
ByVal Name As String, _
ByVal Level As Int32, _
ByVal pPrinterEnum As IntPtr, _
ByVal cbBuf As Int32, _
ByRef pcbNeeded As Int32, _
ByRef pcReturned As Int32) As Integer
Private Structure PRINTER_INFO_2
<MarshalAs(UnmanagedType.LPStr)> Dim pServerName As String
<MarshalAs(UnmanagedType.LPStr)> Dim pPrinterName As String
<MarshalAs(UnmanagedType.LPStr)> Dim pShareName As String
<MarshalAs(UnmanagedType.LPStr)> Dim pPortName As String
<MarshalAs(UnmanagedType.LPStr)> Dim pDriverName As String
<MarshalAs(UnmanagedType.LPStr)> Dim pComment As String
<MarshalAs(UnmanagedType.LPStr)> Dim pLocation As String
Dim pDevMode As IntPtr
<MarshalAs(UnmanagedType.LPStr)> Dim pSepFile As String
<MarshalAs(UnmanagedType.LPStr)> Dim pPrintProcessor As String
<MarshalAs(UnmanagedType.LPStr)> Dim pDatatype As String
<MarshalAs(UnmanagedType.LPStr)> Dim pParameters As String
Dim pSecurityDescriptor As IntPtr
Dim Attributes As Long
Dim Priority As Long
Dim DefaultPriority As Long
Dim StartTime As Long
Dim UntilTime As Long
Dim Status As Long
Dim cJobs As Long
Dim AveragePPM As Long
End Structure
Private Enum PrinterEnum
peDEFAULT = &H1
peLOCAL = &H2
peCONNECTIONS = &H4
peNAME = &H8
peREMOTE = &H10
peSHARED = &H20
peNETWORK = &H40
End Enum
End Module
found on .NET 247. Anyhow, look at the For/Next loop. The first iteration,
it works fine. The messagebox shows me the share name of a printer. But on
the 2nd iteration, the Marshal.PtrToStructure line throws an
AccessViolationException was unhandled (Attempted to read or write protected
memory. This is often an indication that other memory is corrupt.). Can
anyone see what may be wrong in the code?
Thanks.
Imports System.Runtime.InteropServices
Module EnumPrinters
Public Function GetPrintShares(ByVal Server As String) As ArrayList
Dim pcbNeeded As Int32
Dim pcbReturned As Int32
Dim outC As IntPtr = IntPtr.Zero
Dim tmp As Integer = (EnumPrinters(PrinterEnum.peNAME Or
PrinterEnum.peSHARED, _
"", 2, outC, 0, pcbNeeded, pcbReturned))
outC = Marshal.AllocHGlobal(pcbNeeded)
tmp = EnumPrinters(PrinterEnum.peNAME Or PrinterEnum.peSHARED, _
"", 2, outC, pcbNeeded, pcbNeeded, pcbReturned)
MsgBox(tmp & " - " & pcbNeeded & " - " & pcbReturned)
Dim manyPR(pcbReturned) As PRINTER_INFO_2
Dim currentP As IntPtr = outC
Dim MyAL As New ArrayList
For i As Integer = 1 To pcbReturned
manyPR(i) = Marshal.PtrToStructure(currentP, manyPR(i).GetType)
MsgBox(manyPR(i).pShareName)
MyAL.Add(manyPR(i).pShareName)
currentP = IntPtr.op_Explicit(currentP.ToInt32 +
Marshal.SizeOf(manyPR(i).GetType))
Next
Marshal.FreeHGlobal(outC)
Return MyAL
End Function
Private Declare Auto Function EnumPrinters Lib "winspool.drv" Alias
"EnumPrintersA" _
(ByVal Flags As Int32, _
ByVal Name As String, _
ByVal Level As Int32, _
ByVal pPrinterEnum As IntPtr, _
ByVal cbBuf As Int32, _
ByRef pcbNeeded As Int32, _
ByRef pcReturned As Int32) As Integer
Private Structure PRINTER_INFO_2
<MarshalAs(UnmanagedType.LPStr)> Dim pServerName As String
<MarshalAs(UnmanagedType.LPStr)> Dim pPrinterName As String
<MarshalAs(UnmanagedType.LPStr)> Dim pShareName As String
<MarshalAs(UnmanagedType.LPStr)> Dim pPortName As String
<MarshalAs(UnmanagedType.LPStr)> Dim pDriverName As String
<MarshalAs(UnmanagedType.LPStr)> Dim pComment As String
<MarshalAs(UnmanagedType.LPStr)> Dim pLocation As String
Dim pDevMode As IntPtr
<MarshalAs(UnmanagedType.LPStr)> Dim pSepFile As String
<MarshalAs(UnmanagedType.LPStr)> Dim pPrintProcessor As String
<MarshalAs(UnmanagedType.LPStr)> Dim pDatatype As String
<MarshalAs(UnmanagedType.LPStr)> Dim pParameters As String
Dim pSecurityDescriptor As IntPtr
Dim Attributes As Long
Dim Priority As Long
Dim DefaultPriority As Long
Dim StartTime As Long
Dim UntilTime As Long
Dim Status As Long
Dim cJobs As Long
Dim AveragePPM As Long
End Structure
Private Enum PrinterEnum
peDEFAULT = &H1
peLOCAL = &H2
peCONNECTIONS = &H4
peNAME = &H8
peREMOTE = &H10
peSHARED = &H20
peNETWORK = &H40
End Enum
End Module