Ошибка PInvokeStackImbalance - класс чекового принтера - PullRequest
0 голосов
/ 05 октября 2019

Я получаю эту ошибку: -

Помощник по управляемой отладке 'PInvokeStackImbalance' Сообщение = Помощник по управляемой отладке 'PInvokeStackImbalance': 'Вызов функции PInvoke' CompuBytePos.net! Pos.net.ReceiptPrintClass :: OpenPrinter«разбалансировал стек. Это вероятно потому, что управляемая подпись PInvoke не совпадает с неуправляемой целевой подписью. Убедитесь, что соглашение о вызовах и параметры подписи PInvoke соответствуют целевой неуправляемой подписи. '

Это мой код: -

 Imports System.IO
 Imports System.Runtime.InteropServices
 Public Class ReceiptPrintClass
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Structure DOCINFOW
    <MarshalAs(UnmanagedType.LPWStr)> Public pDocName As String
    <MarshalAs(UnmanagedType.LPWStr)> Public pOutputFile As String
    <MarshalAs(UnmanagedType.LPWStr)> Public pDataType As String
End Structure

Structure PRINTER_DEFAULTS
    Public pDatatype As IntPtr
    Public pDevMode As IntPtr
    Public DesiredAccess As Integer
End Structure

Public Structure AsciiControlChars
    'Standard ASCII Control Characters
    Public Shared Null As String = Chr(0)               'NUL
    Public Shared StartOfHeader As String = Chr(1)      'SOH
    Public Shared StartofText As String = Chr(2)        'SOT
    Public Shared EndOfTransmission As String = Chr(4)  'EOT
    Public Shared XON As String = Chr(17)               'XON
    Public Shared Escape As String = Chr(27)            'ESC
    Public Shared FileSperator As String = Chr(28)      'FS
    Public Shared GroupSeperator As String = Chr(29)    'GS
    Public Shared NewLine As String = Chr(13) & Chr(10) 'CR & LF
    'ESCPOS Control Sequences
    Public Shared ESCPOSlogo As String = AsciiControlChars.FileSperator & "p" & Chr(1) & AsciiControlChars.Null 'This will print logo 1, change Chr(1) to a different value (Chr(2) etc) to print different logos
    Public Shared ESCPOSfontNormal As String = AsciiControlChars.Escape & "!" & AsciiControlChars.StartOfHeader
    Public Shared ESCPOSFontDoubleHeight As String = AsciiControlChars.Escape & "!" & AsciiControlChars.XON
    Public Shared ESCPOSFontDoubleWidth As String = AsciiControlChars.Escape & "!" & "!"
    Public Shared ESCPOSFontDoubleHeightAndWidth As String = AsciiControlChars.Escape & "!" & "0"
    Public Shared ESCPOSBarcodePrefix As String = AsciiControlChars.GroupSeperator & "h" & "(" & AsciiControlChars.GroupSeperator & "w" & AsciiControlChars.StartofText & AsciiControlChars.GroupSeperator & "k" & AsciiControlChars.EndOfTransmission
    Public Shared ESCPOSBarcodeSuffix As String = AsciiControlChars.Null
    Public Shared ESCPOSCut As String = AsciiControlChars.Escape & "m"
    Public Shared ESCPOSKickDrawer As String = AsciiControlChars.Escape & "p" & Chr(0) & Chr(100) & Chr(250)
    Public Shared ESCPOSBoldON As String = AsciiControlChars.Escape & "E" & AsciiControlChars.StartOfHeader
    Public Shared ESCPOSBoldOFF As String = AsciiControlChars.Escape & "E" & AsciiControlChars.Null

    Public Shared ESCPOSDoubleStrikeON As String = AsciiControlChars.Escape & "G" & AsciiControlChars.StartOfHeader
    Public Shared ESCPOSDoubleStrikeOFF As String = AsciiControlChars.Escape & "G" & AsciiControlChars.Null
    Public Shared ESCPOSUnderlineON As String = AsciiControlChars.Escape & "-" & AsciiControlChars.StartOfHeader
    Public Shared ESCPOSUnderlineOFF As String = AsciiControlChars.Escape & "-" & AsciiControlChars.Null
End Structure



<DllImport("winspool.drv", EntryPoint:="OpenPrinterA", ExactSpelling:=True, SetLastError:=True, CallingConvention:=CallingConvention.Cdecl, CharSet:=CharSet.Ansi)>
Private Shared Function OpenPrinter(ByVal pPrinterName As String, ByRef hPrinter As IntPtr, ByRef pDefault As PRINTER_DEFAULTS) As Boolean
End Function
<DllImport("winspool.Drv", EntryPoint:="ClosePrinter", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.Cdecl)>
Public Shared Function ClosePrinter(ByVal hPrinter As IntPtr) As Boolean
End Function
<DllImport("winspool.Drv", EntryPoint:="StartDocPrinterW", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.Cdecl)>
Public Shared Function StartDocPrinter(ByVal hPrinter As IntPtr, ByVal level As Int32, ByRef pDI As DOCINFOW) As Boolean
End Function
<DllImport("winspool.Drv", EntryPoint:="EndDocPrinter", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.Cdecl)>
Public Shared Function EndDocPrinter(ByVal hPrinter As IntPtr) As Boolean
End Function
<DllImport("winspool.Drv", EntryPoint:="StartPagePrinter", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.Cdecl)>
Public Shared Function StartPagePrinter(ByVal hPrinter As IntPtr) As Boolean
End Function
<DllImport("winspool.Drv", EntryPoint:="EndPagePrinter", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.Cdecl)>
Public Shared Function EndPagePrinter(ByVal hPrinter As IntPtr) As Boolean
End Function
<DllImport("winspool.Drv", EntryPoint:="WritePrinter", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.Cdecl)>
Public Shared Function WritePrinter(ByVal hPrinter As IntPtr, ByVal pBytes As IntPtr, ByVal dwCount As Int32, ByRef dwWritten As Int32) As Long
End Function
<DllImport("kernel32.dll", EntryPoint:="GetLastError", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.Cdecl)>
Public Shared Function GetLastError() As Int32
End Function

' SendBytesToPrinter()
' When the function is given a printer name and an unmanaged array of  
' bytes, the function sends those bytes to the print queue.
' Returns True on success or False on failure.
Public Shared Function SendBytesToPrinter(ByVal szPrinterName As String, ByVal pBytes As IntPtr, ByVal dwCount As Int32) As Boolean
    Dim hPrinter As IntPtr      ' The printer handle.
    Dim dwError As Int32        ' Last error - in case there was trouble.
    Dim di As New DOCINFOW      ' Describes your document (name, port, data type).
    Dim dwWritten As Int32      ' The number of bytes written by WritePrinter().
    Dim bSuccess As Boolean     ' Your success code.
    Dim pd As PRINTER_DEFAULTS

    Try
        ' Set up the DOCINFO structure.
        With di
            .pDocName = "RAW Document (Docket)"
            .pDataType = "RAW"
        End With
        ' Assume failure unless you specifically succeed.v  ByVal src As String, ByRef hPrinter As Integer, ByVal pd As Integer

        If OpenPrinter(szPrinterName, hPrinter, pd) Then
                If StartDocPrinter(hPrinter, 1, di) Then
                    If StartPagePrinter(hPrinter) Then
                        ' Write your printer-specific bytes to the printer.
                        bSuccess = WritePrinter(hPrinter, pBytes, dwCount, dwWritten)
                        EndPagePrinter(hPrinter)
                    End If
                    EndDocPrinter(hPrinter)
                End If
                ClosePrinter(hPrinter)
            End If


        ' If you did not succeed, GetLastError may give more information
        ' about why not.
        If bSuccess = False Then
            dwError = GetLastError()
        End If
    Catch ex As Exception
        msgbox(ex.message)
    End Try
    Return bSuccess
End Function


' When the function is given a string and a printer name,
' the function sends the string to the printer as raw bytes.
Public Shared Function SendStringToPrinter(ByVal szPrinterName As String, ByVal szString As String)
    Dim pBytes As IntPtr
    Dim dwCount As UInteger
    ' How many characters are in the string?
    dwCount = szString.Length()
    ' Assume that the printer is expecting ANSI text, and then convert
    ' the string to ANSI text.
    pBytes = Marshal.StringToCoTaskMemAnsi(szString)
    ' Send the converted ANSI string to the printer.
    SendBytesToPrinter(szPrinterName, pBytes, dwCount)
    Marshal.FreeCoTaskMem(pBytes)
    Return 0
End Function
  End Class

В этот момент возникает ошибка: -

    If OpenPrinter(szPrinterName, hPrinter, pd) Then
                If StartDocPrinter(hPrinter, 1, di) Then
                    If StartPagePrinter(hPrinter) Then
                        ' Write your printer-specific bytes to the printer.
                        bSuccess = WritePrinter(hPrinter, pBytes, dwCount, dwWritten)
                        EndPagePrinter(hPrinter)
                    End If
                    EndDocPrinter(hPrinter)
                End If
                ClosePrinter(hPrinter)
            End If

Этот класс принтера компилируется и отлично работает в framework 2.0, однако в 4.5 он встречает указанную ошибку.

Я искал на многих форумах, включенных stackoverflow, чтобы найти обходной путь для этой проблемы, помогаявыяснить, почему генерируется эта ошибка, будет очень ценно.

...