Click here to Skip to main content
15,887,267 members
Articles / Web Development / HTML

EMF Printer Spool File Viewer

Rate me:
Please Sign up or sign in to vote.
4.72/5 (32 votes)
23 Apr 2014CPOL3 min read 812.8K   25.3K   92   181
A viewer application for EMF format spool files

What is an EMF Spool File?

When an application sends pages to a printer, they are held in an intermediary file which the application can write to and the printer driver can read from simultaneously. This speeds up the print process as control can return to the application before the printer has finished printing the document.

Usually, this spool file is held in the raw printer page definition language (which could be PCL, PostScript or one of many other options) but in Windows NT, 2000, XP and 2003, it is possible to make the spooler use a different, more device independent format known as an EMF spool file.

The file layout of an EMF spool file is not officially documented by Microsoft, but the newly released documentation reveals that it is a series of enhanced metafile records (one for each page) and a number of other record types which are specific to the business of printing these pages.

The EMF Spool File Record Types

The spool file is composed of the following record types:

VB
Private Enum SpoolerRecordTypes
    SRT_EOF = &H0            ' // int32 zero
    SRT_RESERVED_1 = &H1     '*  1                               */
    SRT_FONTDATA = &H2       '  2 Font Data                      */
    SRT_DEVMODE = &H3        '  3 DevMode                        */
    SRT_FONT2 = &H4          '4 Font Data                        */
    SRT_RESERVED_5 = &H5     ' 5                                 */
    SRT_FONT_MM = &H6        ' 6 Font Data (Multiple Master)     */
    SRT_FONT_SUB1 = &H7      '   7 Font Data (SubsetFont 1)      */
    SRT_FONT_SUB2 = &H8      '   8 Font Data (SubsetFont 2)
    SRT_RESERVED_9 = &H9
    SRT_UNKNOWN = &H10       ' // int unknown...
    SRT_RESERVED_A = &HA
    SRT_RESERVED_B = &HB
    SRT_PAGE = &HC           ' 12  Enhanced Meta File (EMF)       */
    SRT_EOPAGE1 = &HD        ' 13  EndOfPage                      */
    SRT_EOPAGE2 = &HE        ' 14  EndOfPage                      */
    SRT_EXT_FONT = &HF       ' 15  Ext Font Data                  */
    SRT_EXT_FONT2 = &H10     ' 16  Ext Font Data                  */
    SRT_EXT_FONT_MM = &H11   ' 17  Ext Font Data (Multiple Master)
    SRT_EXT_FONT_SUB1 = &H12 ' 18  Ext Font Data (SubsetFont 1)   */
    SRT_EXT_FONT_SUB2 = &H13 '* 19  Ext Font Data (SubsetFont 2)  */
    SRT_EXT_PAGE = &H14      ' 20  Enhanced Meta File?
End Enum

Of these, the most important record types are:

SRT_PAGE

This record contains a Windows standard enhanced metafile, consisting of an EMF header and one or more EMF graphics record structures. The EMF header record gives you the dimensions of the boundary rectangle (the area inside the print margins), the number of graphics records that make up the page, and the file size of this single EMF page.

SRT_DEVMODE

This record contains the device settings that apply to the rest of the pages in the document (or until another DEVMODE record is encountered that overrides it). The DEVMODE structure holds details such as the number of copies, the page orientation (landscape versus portrait), the paper size and paper source, and so on.

SRT_EOF

This signifies the end of the spool file records.

Using the EMF Spoolfile Viewer

To view an EMF spool file, select the menu File -> Open. A dialog box will appear to allow you to browse to the spool file (extension .spl). These are typically held in your $winnt$\System32\spool\ directory. (I have included some samples with this application code as well.)

The viewer allows you to go to a particular page, zoom in and out, and even print the spool file using the following menu options:

  • File
    • Open - Brings up a dialog box to find and open EMF spool files
    • Print - Allows you to reprint the currently open EMF spool file
    • Properties - Brings up a dialog box listing the print file properties
    • Exit - Quits the application
  • Pages
    • First Page - Goes to the beginning of the document
    • Previous Page - Goes back one page
    • Next Page - Goes to the next page
    • Last Page - Goes to the end of the document
    • Goto - Goes directly to the selected page
    • Properties = Brings up a dialog with the properties of this page
  • View
    • Zoom in enlarges the preview
    • Zoom out reduces the size of the preview

Uses for EMF Spoolfiles

Since pretty much every application has a print function, the EMF spool file can serve as a quick and dirty portable document format (though much less featured than a PDF). Thus if you have an application and you want to send a file to someone who doesn't have that application to view, you simply use the application's print function and send them the spool file.

In addition, knowing the structure of the spool file means that it is possible to parse the file to extract information from it. You might want to extract just the text from a printed document for archival purposes, and you can do this by parsing the file and extracting the EMR_EXTTEXTOUTA and EMR_EXTTEXTOUTW records.

Acknowledgements

The source code in this application draws heavily on the work of Feng Yuan and Christophe Lindemann as well as numerous others on the various forums and news groups.

Portions of this article are based on www.undocprint.org/formats/winspool/spl. These portions are subject to the GNU Free Documentation License and are copyright © 2003-2005 Free Software Foundation, Inc.

History

  • 21st August, 2006: Code updated to .NET 2.0 and page navigation improved

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Ireland Ireland
C# / SQL Server developer
Microsoft MVP (Azure) 2017
Microsoft MVP (Visual Basic) 2006, 2007

Comments and Discussions

 
GeneralRe: Problem with GDI+ Pin
goyal mohit 3-Jun-14 22:41
goyal mohit 3-Jun-14 22:41 
GeneralRe: Problem with GDI+ Pin
goyal mohit 6-Jun-14 0:04
goyal mohit 6-Jun-14 0:04 
GeneralGET SPL Pin
Efrain Dominguez Goycochea9-Sep-08 9:10
Efrain Dominguez Goycochea9-Sep-08 9:10 
GeneralRe: GET SPL Pin
hsirc21-Sep-08 7:01
hsirc21-Sep-08 7:01 
QuestionDevMode Pin
JC_Denton10-Jul-08 3:59
JC_Denton10-Jul-08 3:59 
AnswerRe: DevMode Pin
Duncan Edwards Jones10-Jul-08 8:36
professionalDuncan Edwards Jones10-Jul-08 8:36 
GeneralRe: DevMode Pin
JC_Denton11-Jul-08 5:57
JC_Denton11-Jul-08 5:57 
GeneralRe: DevMode Pin
Duncan Edwards Jones11-Jul-08 9:03
professionalDuncan Edwards Jones11-Jul-08 9:03 
Something like:-

VB
'\\ --[DevMode]------------------------------------------------------------
'\\ Represnts a DEVMODE structure stored in a file (shadow or spool...)
'\\ -----------------------------------------------------------------------
Public Class DevMode

#Region "Private properties"
    Private dmDeviceName(64) As Char
    Private dmSpecVersion As Short
    Private dmDriverVersion As Short
    Private dmSize As Short
    Private dmDriverExtra As Short
    Private dmFields As Integer
    Private dmOrientation As Short
    Private dmPaperSize As Short
    Private dmPaperLength As Short
    Private dmPaperWidth As Short
    Private dmScale As Short
    Private dmCopies As Short
    Private dmDefaultSource As Short
    Private dmPrintQuality As Short
    Private dmColor As Short
    Private dmDuplex As Short
    Private dmYResolution As Short
    Private dmTTOption As Short
    Private dmCollate As Short
    Private dmFormName(32) As Char
    Private dmUnusedPadding As Short
    Private dmBitsPerPel As Integer
    Private dmPelsWidth As Integer
    Private dmPelsHeight As Integer
    Private dmDisplayFlags As Integer
    Private dmDisplayFrequency As Integer
    Private dmICMMethod As Integer
    Private dmICMIntent As Integer
    Private dmMediaType As Integer
    Private dmDitherType As Integer
    Private dmReserved1 As Integer
    Private dmReserved2 As Integer
    Private dmPanningWidth As Integer
    Private dmPanningHeight As Integer
#End Region

#Region "Public properties"
 #Region "Copies"
    Public ReadOnly Property Copies() As Short
        Get
            If dmCopies < 1 Then
                dmCopies = 1
            End If
            Return dmCopies
        End Get
    End Property
#End Region
#Region "Collate"
    Public ReadOnly Property Collate() As Boolean
        Get
            Return (dmCollate > 0)
        End Get
    End Property
#End Region
#End Region

#Region "Public constructors"
    Public Sub New(ByVal FileReader As System.IO.BinaryReader)
        dmDeviceName = FileReader.ReadChars(64)
        'FileReader.BaseStream.Seek(64, IO.SeekOrigin.Current)
        dmSpecVersion = FileReader.ReadInt16
        dmDriverVersion = FileReader.ReadInt16
        dmSize = FileReader.ReadInt16
        dmDriverExtra = FileReader.ReadInt16
        dmFields = FileReader.ReadInt32
        dmOrientation = FileReader.ReadInt16
        dmPaperSize = FileReader.ReadInt16
        dmPaperLength = FileReader.ReadInt16
        dmPaperWidth = FileReader.ReadInt16
        dmScale = FileReader.ReadInt16
        dmCopies = FileReader.ReadInt16
        dmDefaultSource = FileReader.ReadInt16
        dmPrintQuality = FileReader.ReadInt16
        dmColor = FileReader.ReadInt16
        dmDuplex = FileReader.ReadInt16
        dmYResolution = FileReader.ReadInt16
        dmTTOption = FileReader.ReadInt16
        dmCollate = FileReader.ReadInt16
        dmFormName = FileReader.ReadChars(32) '32 chars
        dmUnusedPadding = FileReader.ReadInt16
        dmBitsPerPel = FileReader.ReadInt32
        dmPelsWidth = FileReader.ReadInt32
        dmPelsHeight = FileReader.ReadInt32
        dmDisplayFlags = FileReader.ReadInt32
        dmDisplayFrequency = FileReader.ReadInt32
        dmICMMethod = FileReader.ReadInt32
        dmICMIntent = FileReader.ReadInt32
        dmMediaType = FileReader.ReadInt32
        dmDitherType = FileReader.ReadInt32
        dmReserved1 = FileReader.ReadInt32
        dmReserved2 = FileReader.ReadInt32
        dmPanningWidth = FileReader.ReadInt32
        dmPanningHeight = FileReader.ReadInt32
    End Sub
#End Region

End Class


wich you would populate thusly:-
VB
'--8<---------------------------
            ElseIf .iType = SpoolerRecordTypes.SRT_DEVMODE Then
                '\\ Spool job DEVMODE
                Dim _dmThis As New DevMode(SpoolBinaryReader)
                _Copies = _dmThis.Copies
                SpoolBinaryReader.BaseStream.Seek(.Seek + 8 + .nSize, SeekOrigin.Begin)
'--8<---------------------------


'--8<------------------------
Ex Datis:
Duncan Jones
Merrion Computing Ltd

AnswerRe: DevMode Pin
JC_Denton11-Jul-08 9:23
JC_Denton11-Jul-08 9:23 
GeneralRe: DevMode Pin
UmeshDrift8-Oct-08 3:46
UmeshDrift8-Oct-08 3:46 
GeneralRe: DevMode Pin
Duncan Edwards Jones6-Jan-09 8:58
professionalDuncan Edwards Jones6-Jan-09 8:58 
GeneralRe: DevMode Pin
royzhou198516-Jan-09 4:16
royzhou198516-Jan-09 4:16 
GeneralProblem with HP Laserjet Pin
ademian4421-May-08 11:29
ademian4421-May-08 11:29 
GeneralRe: Problem with HP Laserjet Pin
Duncan Edwards Jones21-May-08 11:50
professionalDuncan Edwards Jones21-May-08 11:50 
GeneralEMF Spoolfile documentation update Pin
Duncan Edwards Jones8-May-08 23:46
professionalDuncan Edwards Jones8-May-08 23:46 
GeneralPrint EMF spool File Pin
Efrain Dominguez Goycochea5-May-08 13:58
Efrain Dominguez Goycochea5-May-08 13:58 
GeneralRe: Print EMF spool File Pin
Duncan Edwards Jones9-May-08 1:35
professionalDuncan Edwards Jones9-May-08 1:35 
GeneralRe: Print EMF spool File Pin
Efrain Dominguez Goycochea9-May-08 4:48
Efrain Dominguez Goycochea9-May-08 4:48 
GeneralRe: Print EMF spool File Pin
Efrain Dominguez Goycochea12-May-08 7:25
Efrain Dominguez Goycochea12-May-08 7:25 
GeneralRe: Print EMF spool File Pin
Duncan Edwards Jones13-May-08 1:25
professionalDuncan Edwards Jones13-May-08 1:25 
GeneralRe: Print EMF spool File Pin
Efrain Dominguez Goycochea19-May-08 7:32
Efrain Dominguez Goycochea19-May-08 7:32 
QuestionPrinting? Pin
SkotePetoors1-Apr-08 4:33
SkotePetoors1-Apr-08 4:33 
AnswerRe: Printing? Pin
Duncan Edwards Jones9-May-08 1:32
professionalDuncan Edwards Jones9-May-08 1:32 
GeneralCan´t open the EMF spool file Pin
Mariano Capezzani10-Mar-08 14:18
Mariano Capezzani10-Mar-08 14:18 
GeneralRe: Can´t open the EMF spool file Pin
Duncan Edwards Jones11-Mar-08 18:33
professionalDuncan Edwards Jones11-Mar-08 18:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.