Using standard printing from windows

There are many applications where I don't really want to use the usual windows page print. Instead I want output to go directly to the printer using standard print i/o. It's actually a topic that is hard to find in any of the books on Windows, at least I've never found anything on it. But to my surprise I recently learned that standard (DOS/UNIX) printing is alive and well underneath windows. All we need to do is open a printer port and print to it.

If the printer is directly attached to the computer it's trivial. The method for obtaining a printer port when the printer is on the network isn't hard either.

The example below shows how I use the Windows NET USE command to re-direct LPT1 to a shared printer on an NT Server. The same technique applies for Novell networks with a slightly different syntax.

Try this out by creating a new MFC Form-based project. Put a button on the form and attach this code to it. You can actually print with only 3 lines of code:


        FILE *fp = fopen("LPT1", "w");
        fprintf(fp,"What's up, Doc?\n");
        fclose(fp);

Instant print gratification!!

While the program is open it hogs the printer port. In my shop that isn't a problem but be aware of the effect on your windows spooled output.


      *********************************************************
                        THE CODE
      *********************************************************

// the headers for the conventional i/o routines
#include 
#include 
#include 

using namespace std;      // makes string and ofstream
                          // work without std:: qualifier

void CLineprtView::OnButton1()
{
    // I could have used a CString instead of the buff[]
    // but I wanted to show how this is used with lightweight
    // ATL code and STD library
    
    char buff[MAX_BUFF_SIZE];
    
    // My printer is located on another server so I must re-direct the
    // printer port.  If the printer is directly attached this extra step
    // is not needed.
    // on my network the printer is published as \\GREEN\hp5annex
    // All those back-slashes escape the backslash in the path name
    
    if (PRINTER_IS_REMOTE)
    {
        system("NET USE LPT1 /d");  // free up the port
        system("net use lpt1 \\\\green\\hp5annex");
    }
    
    // old fashioned file handle with
    // old fashioned open of the printer port
    FILE *ptr = fopen("LPT1","w");
    
    // laser printer setup string
    sprintf(buff,"\033E\033(s0p4102t1b16.66H\033&l1O");
    fprintf(ptr,buff);
    
    // old fashioned print
    fprintf(ptr,"Who of late doth make a thimble.\n");
    fprintf(ptr,"Is a lower bunk a status symbol??\n");
    
    // old fashioned close
    fclose(ptr);
    
    // now the same thing with stream io
    ofstream optr("LPT1", ios::out);
    
    string str_text = "Hey Doc, Ain't this a print test from windows\n";
    str_text += "with more lines to follow?\n";

    optr << str_text << endl;
    optr << "Quiet, wabbit. I'm conversing with my muse!!\n";
    
    optr << "That's all folks." << "\f" << flush;     // add a formfeed
    
    // the printer connection is still open so close it
    optr.close();
    
    // drop the network link
    if (PRINTER_IS_REMOTE)
    {
        system("net use lpt1 /d");
    }
}

In practice I get printer path information from the registry on each machine, so the real live code is a little busier than this example, but not much.



Comments

  • PRINTER_IS_REMOTE

    Posted by Legacy on 02/26/2004 12:00am

    Originally posted by: sushma

    what is this defined as?

    Reply
  • Help with commtimeouts

    Posted by Legacy on 10/01/2003 12:00am

    Originally posted by: Benny

    I been working in a project that involves seria communication, and i have found a problem, i have a device that send me information, lets say that i send a status request to the device (a string containing 6 characters) and the the device sends another string with the current status (a string containing 31 characters) all these is fine, BUT, after a while the string recieved from the device is truncated or splited in two pieces, i asked to a frien and he told me that is something worn with the read intervals in the port configuration, but a dont know what to do now, because i�ve moved a lot of params and it gives me the same result, so what can i do? who can help me?
    
    

    m_TimeOuts.ReadIntervalTimeout = 2500;
    m_TimeOuts.ReadTotalTimeoutMultiplier = 2500;
    m_TimeOuts.ReadTotalTimeoutConstant = 2500;
    m_TimeOuts.WriteTotalTimeoutMultiplier = 1;
    m_TimeOuts.WriteTotalTimeoutConstant = 250;

    those are the values that i been used

    Reply
  • Problem with GetJob Function.

    Posted by Legacy on 07/04/2003 12:00am

    Originally posted by: lray

    How can use the GetJob function to retrieve the document Name from the printer.

    your help is highly appreciated.

    Reply
  • Want to print a Image on CWnd

    Posted by Legacy on 03/04/2003 12:00am

    Originally posted by: Mallikarjun

    Hay I want to print a Picture which is one the CWnd and
    also print preview

    Reply
  • how to print a picture

    Posted by Legacy on 12/28/2002 12:00am

    Originally posted by: linxs

    In this example, it print text. If i want to print a picture, how to do it ?

    Reply
  • Please use SetCommTimeouts first, and u can ....

    Posted by Legacy on 09/16/2002 12:00am

    Originally posted by: kevin chen

    Please use SetCommTimeouts first,
    After you execute the ::CreateFile(...),
    you can use SetCommTimeouts to set the TimeOut of read/write. by default, it will blocks when the device is Off-line or has some other errors.
    So, when you use WriteFile/ReadFile, you will "timeout" if the error occurs, and next call the GetLastError(), you will get the detail error info.

    for example:
    ------------------------------------------------
    HANDLE hPrinter = ::CreateFile( "LPT1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL );
    if ( hPrint == INVALID_HANDLE_VALUE {
    nErrID = ERR_OPENPORT;
    return FALSE;
    }

    //set timeout to 3 seconds ... 设置超时, 3秒
    COMMTIMEOUTS timeout;
    memset(&timeout, 0, sizeof(COMMTIMEOUTS));
    timeout.ReadTotalTimeoutMultiplier = 3000;
    timeout.ReadTotalTimeoutConstant = 3000;
    timeout.WriteTotalTimeoutConstant = 3000;
    timeout.WriteTotalTimeoutMultiplier = 3000;

    SetCommTimeouts(hPrinter, &timeout);


    if ( !::WriteFile( hPrinter, lpBuf, dwLen, &dwBytes, NULL ) ) {
    strcpy(szErrText, "From Printer: ");
    FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
    NULL,
    GetLastError(),
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    szErrText + strlen(szErrText),
    240,
    NULL);
    AfxMessageBox(szErrText);
    }

    ::CloseHandle(hPrinter);
    return TRUE;

    -----------------------------------------

    good luck!

    Reply
  • Want to know if a printrer is attached

    Posted by Legacy on 09/13/2002 12:00am

    Originally posted by: Steve Lee

    I have a program that scans a system and collects data on any given system. This program will also collect all the configured printers even if they are not attached to the LPT port.

    All of our Windows systems are configured with every printer driver that are oranization has. Meaning, they could not have the printer installed to LPT1 but the drivers are present.

    What I need to know is there a utlity that will allow me to report the printer is attached to LPT1 and then pipe this output to a file.

    Steve Lee

    Reply
  • Want to know if a printrer is attached

    Posted by Legacy on 09/13/2002 12:00am

    Originally posted by: Steve Lee

    I have a program that scans a system and collects data on any given system. This program will also collect all the configured printers even if they are not attached to the LPT port.

    All of our Windows systems are configured with every printer driver that are oranization has. Meaning, they could not have the printer installed to LPT1 but the drivers are present.

    What I need to know is there a utlity that will allow me to report the printer is attached to LPT1 and then pipe this output to a file.

    Steve Lee

    Reply
  • How I can send to the printer a value, but I used Developer Forms 6i.

    Posted by Legacy on 08/27/2002 12:00am

    Originally posted by: Gabriela Silvestri

    I try send to the printer a value of variable using Developer Forms 6i, but I couldn't it. I created a new form in Forms, I push buttom item with a trigger When Buttom Pressed with follow code:
    
    

    declare
    fvariable text_io.file_type;

    begin
    fvariable := text_io.fopen('my_file.txt','w');
    text_io.put_line(fvariable,'test for writing this');
    text_io.fclose(fvariable);
    end;


    I want sen to the print the value of "fvariable"

    I appreciated if you can help me. I workin with PL/SQL and de fprintf don�t workin with PL/SQL.

    Reply
  • Print to file

    Posted by Legacy on 07/25/2002 12:00am

    Originally posted by: geronimo

    Hallo,
    Can you advise me, how can I send the file directly into the "print to file"?
    Thank's a lot.
    Geronimo

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

  • The hard facts on SaaS adoption in over 80,000 enterprises: Public vs. private companies Mid-market vs. large enterprise GoogleApps, Office365, Salesforce & more Why security is a growing concern Fill out the form to download the full cloud adoption report.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds