Reputation: 1
I've been trying to get it to work for a while, but I just can't. And looking online there don't seem to be many USB oriented answers for communicating with a printer.
The final objective is to communicate with the printer by USB, send information and receive data back. Using a different application I was able to send the informaton as a binary file to the printer. Using Wireshark-usbcap I also sniffed the answer from the printer to see it does actually arrive and that the printer is able to respond to my queries via the USB connection.
I've looked at various resources, but some of the more useful ones were: ChatGPT and this thread as it allowed to fix the code generated by ChatGPT and actually connect to the device.
Starting from this code provided by ChatGPT:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateFile(string fileName,
[MarshalAs(UnmanagedType.U4)] uint fileAccess,
[MarshalAs(UnmanagedType.U4)] uint fileShare,
IntPtr securityAttributes,
[MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
[MarshalAs(UnmanagedType.U4)] uint flags,
IntPtr template);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteFile(IntPtr hFile, byte[] lpBuffer,
uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten,
[In] ref System.Threading.NativeOverlapped lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadFile(IntPtr hFile, [Out] byte[] lpBuffer,
uint nNumberOfBytesToRead, out uint nNumberOfBytesRead, [In] ref System.Threading.NativeOverlapped lpOverlapped);
class Program
{
static void Main()
{
string printerName = "YourPrinterName";
string usbPort = "USB001"; // Replace with your port
IntPtr printerHandle = CreateFile(usbPort, FileAccess.ReadWrite, 0, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
if (printerHandle != IntPtr.Zero)
{
byte[] dataToWrite = new byte[] { /* Your byte data */ };
WriteToPrinter(printerHandle, dataToWrite);
byte[] dataRead = ReadFromPrinter(printerHandle);
}
else
{
Console.WriteLine("Failed to get printer handle.");
}
}
public static void WriteToPrinter(IntPtr handle, byte[] data)
{
uint bytesWritten;
System.Threading.NativeOverlapped lpOverlapped = new System.Threading.NativeOverlapped();
WriteFile(handle, data, (uint)data.Length, out bytesWritten, ref lpOverlapped);
}
public static byte[] ReadFromPrinter(IntPtr handle)
{
byte[] buffer = new byte[256]; // Adjust the size as needed
uint bytesRead;
System.Threading.NativeOverlapped lpOverlapped = new System.Threading.NativeOverlapped();
ReadFile(handle, buffer, (uint)buffer.Length, out bytesRead, ref lpOverlapped);
Array.Resize(ref buffer, (int)bytesRead);
return buffer;
}
}
After changing up the code, adding it into my application and testing different solutions, this is what I have right now:
public static class KernelPrinterWriter
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateFile(
[MarshalAs(UnmanagedType.LPTStr)] string filename,
UInt32 desiredaccess, UInt32 sharemode, IntPtr securityattributes,
UInt32 creationdisposition, UInt32 flagsandattributes,
IntPtr templatefile);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteFile(IntPtr hFile, byte[] lpBuffer,
uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten,
[In] ref System.Threading.NativeOverlapped lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadFile(IntPtr hFile, [Out] byte[] lpBuffer,
uint nNumberOfBytesToRead, out uint nNumberOfBytesRead, [In] ref System.Threading.NativeOverlapped lpOverlapped);
public static bool WriteToPort(string port, ref byte[] data)
{
IntPtr hPrinter = IntPtr.Zero;
bool success = true;
uint bytesWritten = 0;
hPrinter = CreateFile(port,
(UInt32)(FileAccess.ReadWrite),
(UInt32)(FileShare.ReadWrite),
IntPtr.Zero,
(UInt32)FileMode.OpenOrCreate,
(UInt32)(FileAttribute.Normal),
IntPtr.Zero);
System.Threading.NativeOverlapped lpOverlapped = new System.Threading.NativeOverlapped();
success = WriteFile(hPrinter, data, (uint)data.Length, out bytesWritten, ref lpOverlapped);
CloseHandle(hPrinter);
return success && bytesWritten > 0;
}
}
The parameters used inside the WriteToPort function are port: "USB001" and data is a small array of 4 bytes I'm sending to the printer to request for information.
Running this code I can see that bytesWritten ends up as 4 and success is true. But outside the application I am unable to see any reaction from the printer (the screen lights up whenever a command is received, but running this code nothing happens) and from wireshark-usbcap I can't see any outgoing packets, whereas I could see both outgoing and incoming packets using the PrintFile application.
Upvotes: 0
Views: 505