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;
 
    try
    {
        handle = CreateFile(printer,
            (uint)EFileAccess.GenericWrite,
            (uint)(EFileShare.Read | EFileShare.Write),
            (uint)0,
            (uint)(ECreationDisposition.OpenExisting),
            (uint)(EFileAttributes.NoBuffering),
            (int)IntPtr.Zero);
 
        if (handle.ToInt32() == -1)
        {
            int hresult = Marshal.GetHRForLastWin32Error();
            Marshal.ThrowExceptionForHR(hresult);
        }
 
        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));
 
                writer.Write(asciiArray);
 
                byte[] binaryArray = File.ReadAllBytes(pltFile);
                writer.Write(binaryArray);
 
                writer.Close();
            }
        }
    }
    finally
    {
        if (handle != IntPtr.Zero && handle.ToInt32() != -1)
            CloseHandle(handle);
    }
}
 
#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);  
 
[Flags]
public enum EFileAccess : uint
{
    GenericWrite = 0x40000000
}
 
[Flags]
public enum EFileShare : uint
{
    Read = 0x00000001,
    Write = 0x00000002
}
 
public enum ECreationDisposition : uint
{
    OpenExisting = 3
}
 
[Flags]
public enum EFileAttributes : uint
{
    NoBuffering = 0x20000000
}
 
#endregion
Advertisements

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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