Sending Data to Océ Printer Using .NET

I was asked to turn a old Inventor printing macro into a .NET add-in. This was a fairly simple task and only translating the SendKeys and Shell commands to code required some thinking.

To print using a Océ 9600 large format printer the macro called the following shell command to send the custom settings along with the plot data (generated using Inventors PrintManager.PrintToFile function) to the printer:

"cmd /c copy settings.txt /a + drawing.plt /b "

This told me I needed to first read the custom settings from a file and turn it into ASCII, then combine that with the data in the binary plot file and finally send it to the printer.

I did not know how to send the data to the printer, so I just tried opening a file stream using the printer’s address (without expecting it to work). This gave me the following exceptionally informative error message:

"FileStream was asked to open a device that was not a file. For support for devices like 'com1:' or 'lpt1:', call CreateFile, then use the FileStream constructors that take an OS handle as an IntPtr."

The message told me exactly what I needed to do. I needed to use the CreateFile Windows API call to get a handle I could pass the the FileStream class. As this was the final piece of the puzzle I quite quickly produced the following code:

public void WriteToPrinter(string pltFile, string settings, string printer)
    IntPtr handle = IntPtr.Zero;
        handle = CreateFile(printer,
            (uint)(EFileShare.Read | EFileShare.Write),
        if (handle.ToInt32() == -1)
            int hresult = Marshal.GetHRForLastWin32Error();
        using (FileStream stream = new FileStream(handle, FileAccess.Write))
            using (BinaryWriter writer = new BinaryWriter(stream))
                byte[] asciiArray = Encoding.Convert(Encoding.UTF8, 
                    Encoding.ASCII, File.ReadAllBytes(settings));
                byte[] binaryArray = File.ReadAllBytes(pltFile);
        if (handle != IntPtr.Zero && handle.ToInt32() != -1)
#region Windows API calls
[DllImport("kernel32", SetLastError = true)]
static extern unsafe IntPtr CreateFile(
    string FileName, 
    uint DesiredAccess, 
    uint ShareMode, 
    uint SecurityAttributes, 
    uint CreationDisposition, 
    uint FlagsAndAttributes, 
    int hTemplateFile);
[DllImport("kernel32", SetLastError = true)]
static extern unsafe bool CloseHandle(
    IntPtr hObject);  
public enum EFileAccess : uint
    GenericWrite = 0x40000000
public enum EFileShare : uint
    Read = 0x00000001,
    Write = 0x00000002
public enum ECreationDisposition : uint
    OpenExisting = 3
public enum EFileAttributes : uint
    NoBuffering = 0x20000000

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s