Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!
  • Students Click Here

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here


Streaming a file to a local printer

Streaming a file to a local printer

Streaming a file to a local printer

I have an application that creates a file (it happens to be a PDF file, but my problem occurs with .DOCX and .XLSX files). After creating it, it sends it to your default printer. That's where it gets a little crazy.

If the default printer is a system network one, the printer starts immediately after the file is streamed to it. If it is a locally connected printer, the streaming is immediate, but the printer doesn't start up for several minutes.

To test the connectivity of the printer, I can separately open up the PDF with my default PDF reader and print it and it is instantaneous.

Another test I performed is printing via another application that uses the PrintDocument method and it is immediately printed. I don't know where the problem is, but this is my code that performs the streaming:
public static class myPrinters
[DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetDefaultPrinter(string Name);


private string SendToPrinter ( string strFileName, string strPrinterName )
FileInfo f = new FileInfo ( strFileName );
string fullname = f.FullName;

byte[] file = File.ReadAllBytes ( fullname );

// This is my ideal scenario in case the user wants to print to a different printer.
// I have tried with this line commented out and get the same results.
myPrinters.SetDefaultPrinter( strPrinterName );

PrintQueue printQueue = LocalPrintServer.GetDefaultPrintQueue();

using (var job = printQueue.AddJob())
using (var stream = job.JobStream)
stream.Write ( file, 0, file.Length );

Thanks in advance,

Jerry Scannell

RE: Streaming a file to a local printer

I'm not sure, but this sounds to me like a printer issue. Did a google search for local printer delay, and found this:


On server or desktops of your users (if you are not using a print server you should think of doing that) go to Start > Devices > look for the printer having issues - right-click go to Printer Properties (not properties specifically "Printer Properties") on the Advanced Tab make sure "Start printing immediately" is checked.

(In Windows 10, you find this by opening your start screen, typing "Printers," opening "Printers and Scanners," left-clicking on your default printer in the list, go to "Manage" then "Printer properties," then follow the Advanced Tab instruction above.)


RE: Streaming a file to a local printer

Hrmmm..... how is this supposed to work?

Printers speak a different language than files....
Unless the file is in a printer output file, I wouldn't expect it to work.
For example, if you had a BMP file, you can't just write that BMP out to the printer, the printer wouldn't know it was a BMP file.

You need to load the program as an object, then load the file into the object, then print from the object. You can't just send bytes from assorted files to a printer and have it work, unless it's a pre-formatted for that printer file.

Just my $.02

"What the captain doesn't realize is that we've secretly replaced his Dilithium Crystals with new Folger's Crystals."


RE: Streaming a file to a local printer

JScannel, your approach is not wrong, but you should explicitly P/Invoke at least seven different Windows subroutines in a specific nested order like XML: openprinter, opendoc, openpage, writebytes, closepage, closedoc, closeprinter. I speculate that your printer driver is waiting for your C# code to close all (implicitly?) opened sections. I speculate that your printer driver is closing these sections for you after a timeout. My recommendation is to debug using winspool.drv DocumentEvent because this should expose to you the order and the time of each open and close event.

For the benefit of those who do not have your working code, two of the native subroutines are:

CODE --> c#

static extern int OpenPrinter(string pPrinterName, out IntPtr phPrinter, IntPtr pDefault);

[DllImport("winspool.drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, UInt32 dwCount, out UInt32 dwWritten); 

Usage example:

CODE --> c#

// From: http://support.microsoft.com/kb/322091
    // 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 = "My C#.NET RAW Document";
    di.pDataType = "RAW";

    // Open the printer.
    if( OpenPrinter( szPrinterName.Normalize(), out hPrinter, IntPtr.Zero ) )
        // Start a document. https://msdn.microsoft.com/en-us/library/windows/desktop/dd145115(v=vs.85).aspx
        if( StartDocPrinter(hPrinter, 1, di) )
        // Start a page. https://msdn.microsoft.com/en-us/library/windows/desktop/dd145117(v=vs.85).aspx
        if( StartPagePrinter(hPrinter) )
            // Write your bytes.
            bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
            EndPagePrinter(hPrinter); // https://msdn.microsoft.com/en-us/library/windows/desktop/dd162597(v=vs.85).aspx
        EndDocPrinter(hPrinter); // https://msdn.microsoft.com/en-us/library/windows/desktop/dd162595(v=vs.85).aspx
        ClosePrinter(hPrinter); // https://msdn.microsoft.com/en-us/library/windows/desktop/dd183446(v=vs.85).aspx
    // If you did not succeed, GetLastError may give more information
    // about why not.
    if( bSuccess == false )
        dwError = Marshal.GetLastWin32Error();
    return bSuccess;

The full list of relevant native subroutines that you can P/Invoke is documented here: https://msdn.microsoft.com/en-us/library/windows/d...

A potentially easier approach to P/Invoke is the Windows Driver Kit available at https://docs.microsoft.com/en-us/windows-hardware/... with C# Printer demo at https://github.com/Microsoft/Windows-driver-sample... but in my experience the native methods are more performant and more empowering.

The biggest risk I foresee is the Garbage Collector freeing the managed bytes before the unmanaged printer driver has stopped reading them. The WDK should prevent this from happening, but in my experience Microsoft's (other) managed assemblies work better during lab unit tests than they do in the wild. The wild can stress apps with a mix of unexpectedly large data sets and unexpected order/frequency of user commands. When the GC frees something that the native libraries later read, its the assemblies that misbehaved, and its the user interface that gets blamed. Many programmers disagree with me, but I would put faith in the P/Invoke approach because that empowers us to try and fix some unforeseen memory issues.

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!


Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close