Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Косяк с принтером, а точнее с определением его статуса [D7, WinXP]


ChainikDenis ©   (2006-05-16 22:02:00) 

Коллеги, беда!

Коротко:
Чековый принтер на COM2. Типа печатает чеки с номерками клиентов. Задача - определить когда кончается бумага и соответсвенно не печатать.
Засада в том что Винда не обращает внимание на то что в принтере нет бумаги или то что он вообще не подключен. Просто отправляет в COM2 массив байт и считает что на том конце все нормально. Отправку массива определаяю визуально - у меня светодиодики на RxD и TxD сидят.

Принтер достаточно умный и по RS232 может сообщить о своем состоянии все что нужно, НО драйвер принтера занял порт в монопольном режиме и этот порт теперь недоступен!

Хрен бы с ним, сделал так:

var  PrnHandle: THandle;
var  PrnInfo: TPRINTERINFO2;
var  pcbNeeded: DWord;
var  PrinterName: string;

     PrinterName := 'TPTCM60 Dispenser';

     if OpenPrinter(PChar(PrinterName), PrnHandle, nil) then
        begin
        GetPrinter(PrnHandle, 2 , @PrnInfo, 0, @pcbNeeded); // Получаем размер
        SetLastError(0); // Собственно толку от нее ни какого
        if GetPrinter(PrnHandle, 2 , @PrnInfo, pcbNeeded, @pcbNeeded) then
          Form1.StatusBar1.Panels[3].Text := IntToStr(PrnInfo.Status) // Выводим статус
          else
          Form1.StatusBar1.Panels[3].Text := 'Статус не известен...';
        ClosePrinter(PrnHandle);
        end
        else Form1.StatusBar1.Panels[3].Text := 'Принтер не доступен';

Но данная конструкция всегда выводит 0 - вне зависимости от состояния принтера, даже если он ваще отключен...

Кстати, если этот кусок втыкаю в обработчик кнопки, то все нормально, а если в обработчик таймера который срабатывает каждые 250 мс, то на этой строке: if GetPrinter(PrnHandle, 2 , @PrnInfo, pcbNeeded, @pcbNeeded) then... в первом же вызове Acces Vialation вылезает... С чего бы это...

Волнует другой вопрос. Для этого принтера есть StatusMonitor - программулина, которая собственно этот статус и показывает. Причем при ее запуске видно что она где-то раз в секунду посылает запрос в COM2 и соответсвенно оттуда ответ получает.. Я б и сам послал_принял, да доступа к порту нет...

Млин..

Что делать-то? Как определить состояние принтера, или как получить доступ к порту?

P.S. Перевел принтер и соответсвенно драйвер принтера на hardware control - стало лучше, но не то. Просто если нет бумаги, то задание висит в очереди печати пока принтер не включишь (или не вставишь бумагу)...


tesseract   (2006-05-17 12:10:00) [1]


> Порочный путь.

да как раз наоборот.
погеммороишься с рендерингом пару дней, зато потом лафа.


ChainikDenis   (2006-05-17 12:03:00) [2]

Порочный путь.
В графическом режиме ручками печатать достаточтно геморойно. Понятно когда собственный контроллер заставляешь печатать, а тут винда с гигабайтами памяти, мышками и клавиатурами.

Отказ от попытки решения теоретически решаемой задачи - путь слабых.

Нашел пока только один способ - GetPrinter выдает количество задач стоящих в очереди на печать. Зная примерное время печати чека можно сделать вывод о работе/неработе принтера.

Отправляем на печать и засекаем время. Если по окончании опеределенного периода задача еще висит в очереди - значит принтер не работает.

Теперь бы понять почему вышепреведенный код нормально работает только в обработчкие IdUDPServer1UDPRead, а в паралельном потоке и в таймере не работает...


Германн   (2006-05-17 03:59:00) [3]

1. Устройство подключено к Com-порту
2. Спецификация команд известна.

Удалить это устройство, то бишь принтер, из системы. Порт освободится. Работать с принтером как с COM-портом.


ChainikDenis   (2006-05-17 00:48:00) [4]

Все, млин совсем хана...
Вот это:

procedure TForm1.Button1Click(Sender: TObject);
var  PrnHandle: THandle;
var  PrnInfo: TPRINTERINFO2;
var  pcbNeeded: longword;
var  PrinterName : string;

begin
     PrinterName := 'TPTCM60 Dispenser';

     if OpenPrinter(PChar(PrinterName), PrnHandle, nil) then
        begin
        GetPrinter(PrnHandle, 2 , nil, 0, @pcbNeeded);
        if GetPrinter(PrnHandle, 2 , @PrnInfo, pcbNeeded, @pcbNeeded) then
          Form1.Label1.Caption := IntToStr(PrnInfo.Status)
          else
          Form1.Label1.Caption := Статус не известен...';
//           ClosePrinter(PrnHandle);
        end
        else Form1.Label1.Caption := 'Принтер не доступен!';

end;

нихрена не работает,

А если этот кусок вставить в обработчик от IdUDPServer1UDPRead  то все работает. Похоже при втором вызове GetPrinter куда-то теряется  содержимое PrnHandle ...

Хана мне. Спать пойду..

Поможите кто чем можете. ...


ChainikDenis   (2006-05-17 00:41:00) [5]

PortMon от SysInternals? Так этож из другой песни...Я про RS232 расказываю. А для того что б понять что порт занять достаточно попытаться его открыть в Терминал Эмуляторе. Но я для надежности еще и класическим CreateFile проверял - занят нафик.


GanibalLector   (2006-05-17 00:27:00) [6]

2 ChainikDenis
>Для этого принтера есть StatusMonitor - программулина, которая собственно этот статус и показывает. Причем при ее запуске видно что она где-то раз в секунду посылает запрос в COM2 и соответсвенно оттуда ответ получает

Как так? Программулина имеет доступ к порту, а ты нет. Чудеса какие-то.
В конце концов,запусти PortMon и посмотри что творится.

З.Ы. Как вариант,не использовать тот драйвер,а самому взять брозды правления, написав СОМ-сервер.


ChainikDenis   (2006-05-16 22:31:00) [7]


> бумаги, то задание висит в очереди печати пока принтер не
> включишь (или не вставишь бумагу)...


Фиг там - потихоничку "печатается". Примернт по 3 кб в минуту от задания в очереди печати куда-то печатаются. Так что минит через 10 вроде как и напечатал чек... На выключенный принтер...


Наверх

Титульная страница Поиск, карта сайта Написать письмо