Solved

retrieve printer data (status)

Posted on 2014-04-07
10
1,842 Views
Last Modified: 2014-05-06
Hi
i use a POS/receipt Printer (e.g. Citizen CS 300).
For special functions the printer has special ESC-Sequences.
E.g. Cut Paper, Open a connected Cash Drawer etc.

I Use winspool.drv functions in c# to send the esc-sequence as raw data to the printer.
[DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", .....
[DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", ...
[DllImport("winspool.Drv", EntryPoint = "StartPagePrinter"....
[DllImport("winspool.Drv", EntryPoint = "WritePrinter"...
....
Sending the ESC-sequences - to use the special functions - works fine.

Now my question.
The printer supports also specific status information, e.g. status of an connected cash drawer (open ore close), paper sensor etc.

The way to get these Information is to send a status request (ESC-Sequence) to the printer, then the printer "transmit the requested information".

How can I read these "transmitted" Information.

Thank you

 
(pls: no wmi)
0
Comment
Question by:PeterInStingbert
  • 4
  • 4
10 Comments
 
LVL 16

Expert Comment

by:hjgode
ID: 39985141
Hello

to read data back from printer you need a bi-directional communication port. Although USB is a bi-directional comm channel, it is normaly occupied by the printer driver and a second app may not open the same comm channel.

Possibly the driver exposes a direct communication channel to the printer wrapping ReadPort and WritePort (see http://msdn.microsoft.com/en-us/library/windows/hardware/ff561757%28v=vs.85%29.aspx).

But Citizen also provide virtual com port for there POS printers (I assume you have a CT S300 and not CS 300): https://www.citizen-systems.co.jp/english/support/download/printer/driver/windows/drvdown-e.htm and look for "V-COM(Virtual COM port) Drivers":

V-COM(Virtual COM port) Drivers
V-COM_3.0.0.12-3.0.0.19_E.zip
File size 985k bytes
This is for the software to support serial port only.
Using this driver, USB port can be used as serial port.
* Installation manual and Release Note in English are included in ZIP file.

Open in new window


direct link https://www.citizen-systems.co.jp/english/support/download/printer/driver/windows/V-COM_3.0.0.12-3.0.0.19_E.zip

I assume this driver offers a bi-directional direct comm channel to the USB connectd printer.

If you have the oportunity to connect the printer via serial (RS232) you may just use the provided COMx port to directly communicate with the printer.

If you start to comm directly with the printer you should NOT use driver functions any more. Instead send data to print using the native printer language. A cmd ref guide is availalable here: http://www.citizen-systems.com/Pages/UisSupport/downloads/commandRef/CommandReference015E_120607.pdf. The printer language is based on the simple to use ESCP standard extended with special printer commands.

Citizien also offers a POS for .NET driver: http://www.citizen-systems.com/Pages/UisSupport/drivers/pos_dot_net/pos_dot_net_drivers.aspx. I am not sure what it exactly provides, but chances that it supports direct communication too. It does not mention CT-S300, whereas citizen talks about CT-300/310 on other pages and both printers share the same cmd ref guide. Please check with citizen if that driver supports your printer.

I would first go with the .NET driver. If that does not meet your needs you may go on with the V_COM driver and the cmd ref guide. Remember that for both solutions there is no need to use winspool functions any more.
0
 
LVL 1

Author Comment

by:PeterInStingbert
ID: 39985433
Hello
Is the fact that the printer driver occupy the comm channel why ReadPrinter fails ?  (error 6 invalid handle) or is ReadPrinter for something else ?

My wish is "a simple/universal" solution based on the given windows printer because we use also other printers (epson, bixolon, ibm, tbi...).

Do you have an c# ReadPort/WrtiePort example for me?

Peter
0
 
LVL 16

Expert Comment

by:hjgode
ID: 39985576
Hello

MS is not detailed about the winspool ReadPrinter API call, but keep in mind that this a winspool API, the spooler is not the printer direct communication channel. The spooler is a queue buffer with data to (and from?) the printer.

OTOH there are sites with info about error 6 with ReadPrinter(): http://www.codeproject.com/Questions/175205/Reading-printer-settings-with-ReadPrinter-method. The problem is the MS doc, ReadPrinter seems to be only callable with a printjob handle BUT NOT with a printer handle: https://groups.google.com/forum/?hl=en#!msg/microsoft.public.win32.programmer.gdi/C-uBnDGfwOo/G0lDqm5zKq0J

Hopefully the last link solves your problem and let you go on universal.

~josef
0
 
LVL 1

Author Comment

by:PeterInStingbert
ID: 39986197
Hallo,
I have played with the solution. (s. code below)

Yes, I Can read from the print job handle
BUT the result ist not the transmited status, the result is always the value that was sent to the printer (the status-Request-Command)!

Any Ideas ????


public static byte[] ReadBytesFromPrinter(string szPrinterName, byte[] statusRequest)
{
    bool bSuccess = false;
    IntPtr hPrinter = new IntPtr(0);
    IntPtr hPrintJob = new IntPtr(0);
    byte[] status = new byte[0];


    // Open the printer.
    if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
    {
        // Start a document.
        DOCINFOA di = new DOCINFOA() { pDocName = "Peters RAW PrintDocument", pDataType = "RAW" };

        Int32 jobId = StartDocPrinter(hPrinter, 1, di);

        if (jobId > 0)
        {
            // We can't read from a printer handle, but we can read from a printer job handle, 
            // So the trick is to create a Job using StartDocPrinter, then open a handle to the printer job...
            string jobName = string.Format("{0}, Job {1}", szPrinterName, jobId);

            if (OpenPrinter(jobName.Normalize(), out hPrintJob, IntPtr.Zero))
            {

                // Start a page and print the Status-Request Sequence
                if (StartPagePrinter(hPrinter))
                {
                    {
                        Int32 dwCount = statusRequest.Length;
                        IntPtr pStatusRequest = Marshal.AllocCoTaskMem(dwCount);
                        Marshal.Copy(statusRequest, 0, pStatusRequest, dwCount);
                        Int32 dwWritten = 0;

                        bSuccess = WritePrinter(hPrinter, pStatusRequest, dwCount, out dwWritten);

                        EndPagePrinter(hPrinter);
                        EndDocPrinter(hPrinter);                        // EndPage and EndDoc here, otherwise ReadPrinter ist always null

                        Marshal.FreeCoTaskMem(pStatusRequest);
                    }
                    
                     // System.Threading.Thread.Sleep(2000);              // Force ReadPrinter-Error 0x3F

                    if (bSuccess)
                    {
                        //read request from "Job Handle"
                        Int32 bufLen = 32;
                        IntPtr pStatus = Marshal.AllocCoTaskMem(bufLen);        
                        Int32 statusLen = 0;

                        bSuccess = ReadPrinter(hPrintJob, pStatus, bufLen, out statusLen);

                        int err = Marshal.GetLastWin32Error();          // Sometimes is error 0x3F : Your file waiting to be printed was deleted.

                        status = new byte[statusLen];
                        if (statusLen > 0)
                            Marshal.Copy(pStatus, status, 0, statusLen);


                        Marshal.FreeCoTaskMem(pStatus);                         
                    }

                    //EndPagePrinter(hPrinter);
                    //EndDocPrinter(hPrinter);
                }
                
                ClosePrinter(hPrintJob);
            }
        }
        ClosePrinter(hPrinter);
    }
    return status;
}

Open in new window

0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 16

Accepted Solution

by:
hjgode earned 500 total points
ID: 39986562
Hello Peter

that is similar to what I esspct to get from a spooler, it does not read the printer status but the spooler 'status'.

The only valid approach is using a RS232 or Network or USB V-COM connection. But you need to write wrappers for the various models you want to control and to print on.

I am sorry, but there is no general read print status solution for all printer types. The status is normally queried inside the printer driver and there is no standard to read that back into an application (the specialized printer driver status monitor software are able to show ink levels etc, as the manufaturer know there drivers).
There are only some general errors that are reported back into the windows system as PaperOut etc.

Sorry

Josef
0
 
LVL 1

Author Comment

by:PeterInStingbert
ID: 39988804
Hello Josef
thank you.

What is readport/writeport (printmonitor) ? - or is this a wrong track ?



Peter
0
 
LVL 16

Expert Comment

by:hjgode
ID: 39989340
You  might give ReadPort/WritePort a try, but as MSDN says, it "should do...".

Let me know your results. I cannot check for your printers.
0
 
LVL 38

Expert Comment

by:Herman D'Hondt
ID: 40046460
I've requested that this question be closed as follows:

Accepted answer: 500 points for hjgode's comment #a39986562

for the following reason:

This question has been classified as abandoned and is closed as part of the Cleanup Program. See the recommendation for more details.
0
 
LVL 1

Author Comment

by:PeterInStingbert
ID: 40046459
Sorry for the delay....

I didn't checked ReadPort/WritePort ...

I use  FileIO.CreateFile(...) in combination with setupapi.dll to evaluate the "devicename".
It works but only with USB Devices
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

This article describes a simple method to resize a control at runtime.  It includes ready-to-use source code and a complete sample demonstration application.  We'll also talk about C# Extension Methods. Introduction In one of my applications…
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now