У меня есть приложение .NET 8 C# Консольное приложение, которое печатает метки с использованием принтера TSC TTP-225 через команды RAW. При первом исполнении печатная метка имеет неверные координаты, вызывая смещение. Однако, если я немедленно запускаю приложение снова, метка отлично напечатает без каких -либо проблем. < /P>
Симптомы: < /strong> < /p>
[*] При первом пробеже: < /p>
Pertode и Parcode Positions Shieds Offect. Размещенная. < /li>
< /ul>
< /li>
Последующие прогоны: < /p>
Правильно отпечатки метки с правильным выравниванием и координатами. /> Команды: < /strong> < /p>
Код: Выделить всё
var command = "";
command += "SIZE 43 mm, 25 mm\r\n";
command += "GAP 2 mm, 0 mm\r\n";
command += "DIRECTION 1,0\r\n";
command += "CLS\r\n";
command += "TEXT 10,25,\"FONT005\",0,1,1,\"S04-19-8948589-46\"\r\n";
command += "BARCODE 1,70,\"EAN13\",60,0,0,3,3,0,\"3200000004634\"\r\n";
command += "TEXT 90,145,\"FONT005\",0,1,1,\"46042081\"\r\n";
command += "TEXT -30,180,\"FONT005\",0,1,1,\"п.4 ч.1 ст.46\"\r\n";
command += "TEXT 165,180,\"FONT005\",0,1,1,\"27.12.2023\"\r\n";
command += "PRINT 1,1\r\n";
PrinterHelper.SendStringToPrinter("TSC TTP-225", command);
< /code>
Полный код: < /strong> < /p>
using Lib.Logging;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using System.Diagnostics;
using System.Runtime.InteropServices;
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
var services = new ServiceCollection();
services.AddMyLogger(options =>
{
options.LogTargets = LogTarget.Console
| LogTarget.File
| LogTarget.Json;
options.UseSerilogRequestLogging = false;
});
try
{
Log.Information(
"Console application started");
var stopwatch = new Stopwatch();
stopwatch.Start();
services.AddSingleton();
var provider = services.BuildServiceProvider();
var businessLogic = provider.GetRequiredService();
try
{
await businessLogic.PrintAsync();
}
catch (Exception ex)
{
Log.Error(ex, "PrintAsync method failed");
}
stopwatch.Stop();
Log.Information(
"All subtasks completed, elapsed time: {Elapsed}"
, stopwatch.Elapsed);
}
catch (Exception exception)
{
Log.Error(
exception
, "Application terminated with error");
}
Log.Information(
"Press any key to exit ......");
Console.ReadKey();
return;
public class PrinterLogic
{
public async Task PrintAsync()
{
var command = "";
// Printer initialization and calibration
command += "SIZE 43 mm, 25 mm\r\n";
command += "GAP 2 mm, 0 mm\r\n";
//Rotation / mirroring
command += "DIRECTION 1,0\r\n";
// Clear buffer
command += "CLS\r\n";
// Content (FONT005 is a custom font that has been previously downloaded (uploaded) to the printer’s memory.)
command += "TEXT 10,25,\"FONT005\",0,1,1,\"S04-19-8948589-46\"\r\n";
command += "BARCODE 1,70,\"EAN13\",60,0,0,3,3,0,\"3200000004634\"\r\n";
command += "TEXT 90,145,\"FONT005\",0,1,1,\"46042081\"\r\n";
command += "TEXT -30,180,\"FONT005\",0,1,1,\"п.4 ч.1 ст.46\"\r\n";
command += "TEXT 165,180,\"FONT005\",0,1,1,\"27.12.2023\"\r\n";
// Print
command += "PRINT 1,1\r\n";
Log.Information("Sending commands to printer: {{Commands}}", command);
var success = PrinterHelper.SendStringToPrinter("TSC TTP-225", command);
if (success)
{
Log.Information("Commands successfully sent to printer");
// Short pause to allow printer to process commands
await Task.Delay(500);
}
else
{
Log.Error("Failed to send commands to printer");
}
}
}
public class PrinterHelper
{
// Structure and API declarions:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class DOCINFOA
{
[MarshalAs(UnmanagedType.LPStr)] public string pDocName;
[MarshalAs(UnmanagedType.LPStr)] public string pOutputFile;
[MarshalAs(UnmanagedType.LPStr)] public string pDataType;
}
[DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);
[DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
[DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndDocPrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartPagePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndPagePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);
// 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, false on failure.
public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
{
Int32 dwError = 0, dwWritten = 0;
IntPtr hPrinter = new IntPtr(0);
DOCINFOA di = new DOCINFOA();
bool bSuccess = false; // Assume failure unless you specifically succeed.
di.pDocName = "TSC Label Print Job";
di.pDataType = "RAW";
try
{
// Open the printer
if (!OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
{
dwError = Marshal.GetLastWin32Error();
Log.Error($"Failed to open printer '{szPrinterName}'. Error code: {dwError}");
return false;
}
// Start document
if (!StartDocPrinter(hPrinter, 1, di))
{
dwError = Marshal.GetLastWin32Error();
Log.Error($"Failed to start print document. Error code: {dwError}");
return false;
}
// Start page
if (!StartPagePrinter(hPrinter))
{
dwError = Marshal.GetLastWin32Error();
Log.Error($"Failed to start print page. Error code: {dwError}");
EndDocPrinter(hPrinter);
return false;
}
// Send data
bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
if (!bSuccess)
{
dwError = Marshal.GetLastWin32Error();
Log.Error($"Error writing data to printer. Error code: {dwError}");
}
else if (dwWritten != dwCount)
{
Log.Warning($"Wrote {dwWritten} bytes out of {dwCount} during sticker print");
}
// End page
EndPagePrinter(hPrinter);
// End document
EndDocPrinter(hPrinter);
}
catch (Exception ex)
{
Log.Error(ex, "Exception while sending data to printer");
bSuccess = false;
}
finally
{
// Close printer
if (hPrinter != IntPtr.Zero)
{
ClosePrinter(hPrinter);
}
}
return bSuccess;
}
public static bool SendStringToPrinter(string szPrinterName, string szString)
{
if (string.IsNullOrEmpty(szString))
{
Log.Warning("Attempt to send empty string to printer");
return false;
}
if (string.IsNullOrEmpty(szPrinterName))
{
Log.Error("Printer name not specified");
return false;
}
var pBytes = IntPtr.Zero;
bool result;
try
{
// Convert string to ANSI for TSC printer
pBytes = Marshal.StringToCoTaskMemAnsi(szString);
var dwCount = szString.Length;
result = SendBytesToPrinter(szPrinterName, pBytes, dwCount);
}
catch (Exception ex)
{
Log.Error(ex, "Error preparing data for printer");
result = false;
}
finally
{
// Free memory
if (pBytes != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(pBytes);
}
}
return result;
}
}
. /> Добавлены задержки перед отправкой команд (до 500 мс). < /li>
Проверенные команды инициализации принтера (
Код: Выделить всё
SIZEОбеспечить очистку буфера принтера перед каждой печати. Проблема последовательно возникает только при первой печати после запуска приложения. /> модель принтера: TSC TTP-225
language/platform: .net 8, c#, Windows
Метод связи: RAW через API Win32 (
Код: Выделить всё
winspool.drvПодробнее здесь: https://stackoverflow.com/questions/797 ... onsole-app
Мобильная версия