Моя задача - печатать этикетки с помощью термопринтера. С этой целью генерируется и отправляется на принтер последовательность команд tspl (язык программирования, который понимает принтер). Последнее делается в C# с помощью следующего метода, взятого из майкрософт примера "How to send raw data to a printer by using Visual C# .NET"Печать этикеток через перенаправленный принтер
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 = "My C#.NET RAW Document";
di.pDataType = "RAW";
// Open the printer.
if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
{
// Start a document.
if (StartDocPrinter(hPrinter, 1, di))
{
// Start a page.
if (StartPagePrinter(hPrinter))
{
// Write your bytes.
bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
EndPagePrinter(hPrinter);
}
EndDocPrinter(hPrinter);
}
ClosePrinter(hPrinter);
}
// If you did not succeed, GetLastError may give more information
// about why not.
if (bSuccess == false)
{
dwError = Marshal.GetLastWin32Error();
MessageBox.Show("Error " + dwError);
}
return bSuccess;
}
фактический принтер выбран в PrintDialog
private void button2_Click(object sender, EventArgs e)
{
string s = "CLS\nPRINT 1\n"; // device-dependent string, need a FormFeed?
// Allow the user to select a printer.
PrintDialog pd = new PrintDialog();
pd.PrinterSettings = new PrinterSettings();
if (DialogResult.OK == pd.ShowDialog(this))
{
// Send a printer-specific to the printer.
RawPrinterHelper.SendStringToPrinter(pd.PrinterSettings.PrinterName, s);
}
}
В моей рабочей среды все работает отлично. Среда ЛВС, состоящий из 3-х компьютеров и 1 общих термопринтера:
- PC_with_printer - он работает на Windows 7 и имеет принтер, подключенный к нему через USB
- PC_aware - он работает на Win 8 и знает об общем принтере
- PC_unaware - он работает на WinXP и не имеет общей печати er установлен
От ПК_аае я подключаюсь к PC_unaware через rdp, и принтер отображается в списке принтеров как перенаправленный. Затем я запускаю свое приложение, выбираю перенаправленный принтер и печатаю мой пустой ярлык. Все идет нормально.
Проблемы возникают при замене PC_unaware на другой компьютер. Он работает на Windows Server 2008 R2 и не находится в нашей локальной сети. Назовем его SERVER. Поэтому я выполняю тот же эксперимент:
- От PC_aware я подключиться к серверу с помощью ПРР, используя свой публичный адрес IP-
- Мой термопринтер появится в «Принтеры и устройства», как «TSC_TDP-244 (перенаправлены 20)»
- Я перехожу к свойствам принтера и нажимаю Print Test Page, и он печатается
- Запуск моего приложения, и принтер ничего не печатает.
Я проверил возвращаемых значений всех функций WinAPI, которые используются в методе SendBytesToPrinter (OpenPrinter, StartDocPrinter, StartPagePrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter), и ни один из них не указывает на ошибку. Любая идея, почему это происходит и как оно может быть исправлено?
Это действительно проблема удаленного рабочего стола. Поскольку PC_unaware не имеет подключения к локальной сети, и общий принтер не установлен на нем, он полагается на функцию клонирования принтера RD, которую я всегда считал проблематичной. Является ли RD действительно важным для проблемы, которую вы пытаетесь решить? Если нет, я бы вытащил его из картинки. –
Эта функция печати должна быть доступна на сервере, и пользователи подключаются к ней через rdp, поэтому я боюсь, что RD является неотъемлемой частью. – zurab
Я не знаю, как RD реализует клонирование принтера, но я сильно подозреваю, что это зависит от задействования спулера, а это значит, что запись непосредственно в клонированные принтеры не будет работать. В RD потребуется много сложного кода для поддержки прямой печати, и это достаточно редко, что я предполагаю, что они не реализовали его. –