Отправка необработанного текста на принтер через usb

Я пытаюсь отправить команды ZPL на принтер Zebra ZT230. Принтер и драйверы установлены, а порт принтера - «USB003». ПК отлично взаимодействует с принтером с помощью служебных программ настройки принтера Zebra или ZebraDesign. Я пробовал следующий код:

Private Declare Function CreateFile Lib "kernel32.dll" (ByVal lpFileName As String, ByVal dwDesiredAccess As FileAccess, _
ByVal dwShareMode As UInteger, ByVal lpSecurityAttributes As IntPtr, ByVal dwCreationDisposition As FileMode, _
ByVal dwFlagsAndAttributes As UInteger, ByVal hTemplateFile As IntPtr) As System.Runtime.InteropServices.SafeHandle

    ' Command to be sent to the printer
    Dim command As String = "^XA^FO10,10,^AO,30,20^FDFDTesting^FS^FO10,30^BY3^BCN,100,Y,N,N^FDTesting^FS^XZ"
    ' Create a buffer with the command
    Dim buffer() As Byte = New Byte((command.Length) - 1) {}
    buffer = System.Text.Encoding.ASCII.GetBytes(command)
    ' Use the CreateFile external func to connect to the LPT1 port
    Dim printer As System.Runtime.InteropServices.SafeHandle = CreateFile("USB003:", FileAccess.ReadWrite, 0, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero)
    ' Aqui verifico se a impressora � v�lida
    If (printer.IsInvalid = true) Then
        Return
    End If

    ' Open the filestream to the lpt1 port and send the command
    Dim lpt1 As FileStream = New FileStream(printer, FileAccess.ReadWrite)
    lpt1.Write(buffer, 0, buffer.Length)
    ' Close the FileStream connection
    lpt1.Close 

Я получаю сообщение об ошибке в этой строке: Тусклый принтер как System.Runtime.InteropServices.SafeHandle = CreateFile ("USB003:", FileAccess.ReadWrite, 0, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero)

Сообщение об ошибке и трассировка стека:

Невозможно упорядочить «возвращаемое значение»: возвращаемые SafeHandles не могут быть абстрактными.

в PerfectPotatoInventory.vb.PotatoGlobals.CreateFile (String & lpFileName, FileAccess dwDesiredAccess, UInt32 dwShareMode, IntPtr lpSecurityAttributes, FileMode dwCreationDisposition, UInt32 dwFlagsAndAndAttributes) в PerfectPotatoInventory.vb.PotatoGlobals.PrintLabelsTest () в C: \ Potatoes \ PerfectPotatoInventory.vb \ PerfectPotatoInventory.vb \ PotatoGlobals.vb: строка 798

Я работаю в VB.net, используя VS2008 с целевым x86 и .Net 3.5.

Посоветуйте, пожалуйста, что делаю не так.

См. Пример для SafeFileHandle - класс.

TnTinMn 16.11.2018 05:03
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
3 169
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Используя Zebra .Net SDK, вы можете вызвать следующую функцию: Метод PrinterUtil.SendContents (String, String)

Где первая строка - это ZPL для отправки, а вторая строка - это строка подключения к принтеру. Более подробную информацию можно найти здесь: http://techdocs.zebra.com/link-os/2-14/pc_net/

Совместим ли SDK с VS2008, x86 и .Net 3.5?

John Lee 16.11.2018 16:49

Поскольку мне нужно отправить только строку ZPL, я бы предпочел простой подход, основанный на опубликованном коде.

John Lee 16.11.2018 16:56

Надежный комплект для разработки многоплатформенного программного обеспечения Link-OS® позволяет создавать приложения на ПК, смартфонах и планшетах, поддерживая самые популярные операционные системы. Link-OS SDK делает создание мощных приложений простым и понятным. Многоплатформенный SDK поддерживает: Java, Objective C, VB, C# и .NET. Набор инструментов кроссплатформенной разработки Xamarin для принтеров iOS и Android Link-OS, а также для принтеров семейства ZC.

banno 16.11.2018 17:03

В моем плохом файле readme указано, что Microsoft ™ .NET Framework 4.7 (или выше)

banno 16.11.2018 17:07

Вот чего я боялся.

John Lee 16.11.2018 19:25
Ответ принят как подходящий

Добавьте этот класс в свой проект

Imports System.IO
Imports System.Drawing.Printing
Imports System.Runtime.InteropServices
Public Class RAWPOSPrinter
' Structure and API declarions:
<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

<DllImport("winspool.Drv", EntryPoint: = "OpenPrinterW", _
   SetLastError:=True, CharSet:=CharSet.Unicode, _
   ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function OpenPrinter(ByVal src As String, ByRef hPrinter As IntPtr, ByVal pd As Long) As Boolean
End Function
<DllImport("winspool.Drv", EntryPoint: = "ClosePrinter", _
   SetLastError:=True, CharSet:=CharSet.Unicode, _
   ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
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.StdCall)> _
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.StdCall)> _
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.StdCall)> _
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.StdCall)> _
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.StdCall)> _
Public Shared Function WritePrinter(ByVal hPrinter As IntPtr, ByVal pBytes As IntPtr, ByVal dwCount As Int32, ByRef dwWritten As Int32) As Boolean
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 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.

    ' Set up the DOCINFO structure.
    di = New DOCINFOW
    With di
        .pDocName = "RAW DOC"
        .pDataType = "RAW"
    End With
    ' Assume failure unless you specifically succeed.
    bSuccess = False
    If OpenPrinter(szPrinterName, hPrinter, 0) 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 = Marshal.GetLastWin32Error()
    End If
    Return bSuccess
End Function ' SendBytesToPrinter()

' SendFileToPrinter()
' When the function is given a file name and a printer name, 
' the function reads the contents of the file and sends the
' contents to the printer.
' Presumes that the file contains printer-ready data.
' Shows how to use the SendBytesToPrinter function.
' Returns True on success or False on failure.
Public Shared Function SendFileToPrinter(ByVal szPrinterName As String, ByVal szFileName As String) As Boolean
    ' Open the file.
    Dim fs As New FileStream(szFileName, FileMode.Open)
    ' Create a BinaryReader on the file.
    Dim br As New BinaryReader(fs)
    ' Dim an array of bytes large enough to hold the file's contents.
    Dim bytes(fs.Length) As Byte
    Dim bSuccess As Boolean
    ' Your unmanaged pointer.
    Dim pUnmanagedBytes As IntPtr

    ' Read the contents of the file into the array.
    bytes = br.ReadBytes(fs.Length)
    ' Allocate some unmanaged memory for those bytes.
    pUnmanagedBytes = Marshal.AllocCoTaskMem(fs.Length)
    ' Copy the managed byte array into the unmanaged array.
    Marshal.Copy(bytes, 0, pUnmanagedBytes, fs.Length)
    ' Send the unmanaged bytes to the printer.
    bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, fs.Length)
    ' Free the unmanaged memory that you allocated earlier.
    Marshal.FreeCoTaskMem(pUnmanagedBytes)
    Return bSuccess
End Function ' SendFileToPrinter()

' When the function is given a string and a printer name,
' the function sends the string to the printer as raw bytes.
Public Shared Sub SendStringToPrinter(ByVal szPrinterName As String, ByVal szString As String)
    Dim pBytes As IntPtr
    Dim dwCount As Int32
    ' 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)
End Sub
End Class

Затем в своем коде вызовите следующее:

RAWPOSPrinter.SendStringToPrinter("<NAME OF PRINTER AS IT APPEARS IN DEVICES AND PRINTERS>", "<YOUR ZEBRA COMMAND STRING>")

Другие вопросы по теме