Zan Image Printer

[Home]  [What's New]  [Download] [Pricing & BuyNow]  [Tips] [Developer]  [FAQ] [Manual]  [Screenshots] [Contacts]

Print to image file - TIFF, GIF, JPEG, JPEG 2000, PDF, BMP, PNG


Developer>>

Developer


Printer friendly version of this page

This document contains information about Zan Image Printer's configuration options including how to modify options from your application. It also discusses how to print a document to Zan Image Printer from your application.

Zan Image Printer uses INI files to store the printer settings. When you alter your preferences within Zan Image Printer user interface, the INI files are automatically modified and saved. The sections, keywords, and values in each of the INI files used by Zan Image Printer are explained in detail in this document.

Two programming models are available to developers. You can directly access and modify the INI setting files (using the Win32 APIs or with INI components) or you can call the provided command line utilities directly from your application. This document includes numerous VBScript, VB, Delphi, C/C++, VC.NET/CLI, VB.NET, and C# code samples to help you get started quickly.

Many users have asked us how to print documents to Zan Image Printer within their applications. Therefore, we have also included many VB, Delphi, C/C++, VC.NET/CLI, VB.NET, and C# code examples, demonstrating how to automate printing Word documents, Excel spreadsheets, HTML files, and other shell printable documents from your application.

The provided command line utilities zvprtcfg and zvprtcfg_win32 also support some batch/script printing commands so you can automatically print your files (Excel, Word, HTML, PDF, and other shell printable documents). There are also examples of how to print entire subfolders of documents, which turns Zan Image Printer into a powerful batch document converter.

After you have installed Zan Image Printer, the main program files are copied into the installation folder (for example, C:\Program Files\zvprt50):


File Name Description
uninstall.exe run it to uninstall Zan Image Printer
zvprtcfg.exe console mode application, command line utility specifically designed for scripting and for use by system administrators.
zvprtcfg_win32.exe Win32 application, command line utility suitable for those who want to control Zan Image Printer with easy programming.
zvprthlp.chm HTML format help file
zvprtres.dll This resource file stores all dialog box templates and other resources
zvprtemail.exe Email sending application
configure.ini program configuration file: disable/enable event logging, maximum virtual printer ports, where to store the shared INI setting files that are visible to all users.
The following is a sample configure.ini file:
[portmon]
maxport=8

[debuglogging]
enable=0
logfile=

[allusersfolder]
policy=1
maxport: The maximum number of exported virtual printer ports, automatically updated by the Zan Image Printer installer. Do not change this setting.
enable, logfile: Zan Image Printer can create a detailed log file for troubleshooting purposes. Enable the debug logging by setting enable to 1 and specifying the full path to a log file.
policy: This is valid when Zan Image Printer was installed with the "All users share the same settings" option enabled. This integer value specifies where the common application data that can be read and written by all users is located:
  • policy=1 (default): Use CSIDL_COMMON_DOCUMENTS as the location if the operating system is Vista or newer; otherwise, use CSIDL_COMMON_APPDATA.
  • policy=2: Use CSIDL_COMMON_APPDATA as the location.
  • policy=3: Use CSIDL_COMMON_DOCUMENTS as the location.
  • zvprtsrv.exe The core program for Zan Image Printer is zvprtsrv.exe. This program runs in the background, communicates with the printer render driver, retrieves the in-memory bitmap from it, and saves the bitmap to an image file.
    Multiple instances of zvprtsrv.exe can be launched. Each instance of zvprtsrv.exe is responsible for capturing and saving images for one specific printer within the current user session.
    When one instance of zvprtsrv.exe starts, it is associated with both a printer name and a user session ID, which are passed to it by the Zan Image Printer plug-in:
    zvprtsrv.exe -p"printername" -dsessionid
    Example:
    zvprtsrv.exe -p"zan image printer(bw)" -d2

    Normally, zvprtsrv.exe runs using the currently logged on user's credentials. However, you can also run zvprtsrv.exe under the credentials of a different user or even the local system account. For example, if you first set zvprtsrvresident to 1 in general.ini for the printer "zan image printer(bw)", then run the following command from another user session (i.e. sessionid=3) to start zpvrtsrv.exe:
    zvprtsrv.exe -p"zan image printer(bw)" -d2
    If you print to "zan image printer(bw)" from session 2, your images will be redirected and processed by the instance of zvprtsrv.exe with the user credentials of session 3.

    As another example, if you first set zvprtsrvresident to 1 in general.ini for the printer "zan image printer(bw)", then use the psexec utility from Microsoft to start zpvrtsrv.exe from the local system account:
    psexec -d -s "c:\program files\zvprt50\zvprtsrv.exe" "zan image printer(bw)" -d2
    If you print to "zan image printer(bw)" from session 2, your images will be redirected and processed by the instance of zvprtsrv.exe with the credentials of the local system account.
    Note:
    By Windows design, the local system account doesn't have access to network resources, and if zvprtsrv.exe is started in the local system account, you cannot save the image to UNC paths or network drives.

    Zan Image Printer adds an uninstall registry entry under HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\zvprt50 after it is installed. Query this uninstall registry entry (e.g., value data is C:\Program Files\zvprt50\uninstall.exe) to determine directory where Zan Image Printer was installed. The function GetZanInstallDir in the "change save.ini and image.ini settings" code samples demonstrates how to query Zan Image Printer's installation folder.
    Tip: The easiest way to see where the program files are located on your computer is to go to the Program Information page and check the value of the Installation Directory item in the list.

    If Zan Image Printer was installed with the "all users share the same settings" option disabled, all Zan Image Printer specific settings are saved in INI setting files stored in CSIDL_APPDATA\zvprt50\[printername], where CSIDL_APPDATA(0x001a) identifies the file system directory that serves as a common repository for the current user's application-specific data. To access the INI file path for the specified printer independently of the operating system, applications should call the SHGetFolderPath Win32 API with CSIDL_APPDATA and then append zvprt50\[printername] to the returned path. For example, if the current user is administrator, and the printer name is Zan Image Printer(bw), a typical path to the INI setting files for this printer is C:\Documents and Settings\Administrator\Application Data\zvprt50\Zan Image Printer(bw).

    If Zan Image Printer was installed with the "all users share the same settings" option enabled, the policy property (integer) in the configure.ini file determines where the common application data that can be read and written by all users is located:
  • policy=1 (default): Use CSIDL_COMMON_DOCUMENTS as the location if the operating system is Vista or newer; otherwise, use CSIDL_COMMON_APPDATA.


  • policy=2: Use CSIDL_COMMON_APPDATA as the location. The Zan Image Printer installer creates the CSIDL_COMMON_APPDATA\zvprt50\[printername] folder during installation. Example:
    C:\Documents and Settings\All Users\Application Data\zvprt50\Zan Image Printer(bw)

  • policy=3: Use CSIDL_COMMON_DOCUMENTS as the location. The Zan Image Printer installer creates the CSIDL_COMMON_DOCUMENTS\zvprt50\[printername] folder during installation. Example:
    C:\Documents and Settings\All Users\Documents\zvprt50\Zan Image Printer(bw)

  • The function GetZanConfigurationDir in the "change save.ini and image.ini settings" code samples demonstrates how to determine Zan Image Printer's configuration directory programmatically.

    Tips:
  • The easiest way to see where the INI setting files are located on your computer is to go to the Program Information page and check the value of the Configuration Directory item in the list.
  • After installation, you can use Zan Image Printer command line utilities zvprtcfg and zvprtcfg_win32 to toggle the "All users share the same settings" option between 0 (false) and 1 (true):
    "All users share the same settings" = 0 (users have their own settings with the printer):
    C:\Program Files\zvprt50>zvprtcfg zan image printer(bw) configuration.allusers=0
    "All users share the same settings" = 1:
    C:\Program Files\zvprt50>zvprtcfg zan image printer(bw) configuration.allusers=1


  • Running the command line utility zvprtcfg with -show switch also displays the current INI setting files folder (Configuration Directory):
    C:\Program Files\zvprt50>zvprtcfg zan image printer(bw) -show
    
    Build Datetime=Nov 28 2009, 12:16:28
    File Version=5, 0, 9, 1
    OS Name=Microsoft Windows XP Professional x64 Edition
    OS Version=5.02.3790  Service Pack 1
    Windows Directory=C:\WINDOWS
    System Directory=C:\WINDOWS\system32
    Session ID=0
    Printer Driver Directory=C:\WINDOWS\system32\spool\DRIVERS\x64
    Configuration Directory=C:\Documents and Settings\Administrator\Application Data
    \zvprt50\zan image printer(bw)
    Printer GPD File=C:\WINDOWS\system32\spool\DRIVERS\x64\3\zvprt1.gpd
    Debug Logging=Disabled
    
    Windows environment variables:
    [%ALLUSERSPROFILE]=C:\Documents and Settings\All Users
    [%APPDATA]=C:\Documents and Settings\Administrator\Application Data
    [%TEMP]=C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp
    [%TMP]=C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp
    [%USERDOMAIN]=ZAN-PMLGRLABUJT
    [%USERNAME]=Administrator
    [%USERPROFILE]=C:\Documents and Settings\Administrator
    [%windir]=C:\WINDOWS
    
    Parameters(keyword-value pairs) for zan image printer(bw):
    save.folder=E:\test\
    save.basefilename=[%DocName]
    save.filenameindex=1
    save.filexistact=1
    save.popupdialog=2
    



    Return to top




    Debug Logging for troubleshooting
    Zan Image Printer offers the capability to create a detailed log file for troubleshooting purposes. For more details, see the Program Information page.

    Furthermore, Zan Image Printer has been built in with extra debug information, which allows us to quickly analyze and solve program crashes if the Windows memory dump or minidump file is provided to us.


    multi-threaded printing
    To achieve multi-threaded printing, you can load balance the print jobs across multiple Zan Image Printer instances (e.g., submit the print job to the printer with the least amount of pending documents). This is because we want to have every Windows Spooler queue printing actively and independently, if all the print jobs went to the same Zan Image Printer, only one job at a time would actually be printed before moving to the next print job in the printer queue.


    default ini setting files
    The installation program copies the ini setting files of the first selected printer to your hard disk (the default location is C:\Program Files\zvprt50\default). When a user accesses Zan Image Printer for the first time, Zan Image Printer copies an initial profile for this user from C:\Program Files\zvprt50\default.



    combine/merge multiple document types into a single TIFF/PDF file
    Zan Image Printer can combine or merge multiple document types into a single TIFF/PDF file.
    Use the following steps to accomplish this:
    1. On the Save page, specify a permanently fixed file name if you want to always append to the same file. Alternatively, you can specify a variable file name using macros. For example, if you specify a relatively fixed file name like "document[%date]", you can append to a different file each day. The images will append to the same file as long as you have not passed midnight. Only after midnight will a new file be created and the images for that day will be appended to the new file.

    2. On the Image->TIFF or Image->PDF page, set the "File Mode" to "Append to existing file":

    3. Print to Zan Image Printer to start appending documents into the specified file.


    create faxable TIFF files
    A faxable file is a monochrome image file in TIFF format.
    Zan Image Printer can be set up to create faxable TIFF files. With this capability, anything you can print can be converted into a fax compatible file.
    Use the following steps to create faxable TIFF:
    1. Review your faxing hardware and software's specification to determine the required TIFF parameters so that you can configure Zan Image Printer to match. If you have a sample TIFF file and wish to determine the values of the tags in the header, you can download AsTiffTagViewer, it is a free TIFF Tag Viewer for Windows.

    2. During the setup, configure the selected printer to only support 204 x 196 (204 x 98) DPI and A4 (or Letter) paper size, set the default Color to Black & White mode. The TIFF Class F suggests that the <98, 100>, <196, 200>, <200, 204> DPI resolution values may be treated as being equivalent, so you can also set the supported DPI to 200 x 200 (200 x 100) depending on your requirements.

    3. After Zan Image Printer is installed, on the Image->TIFF tab, set the "RowsPerStrip" to "Each page as a single strip". If your fax application requires LSB-to-MSB(FillOrder=2) bit order, check the "Reverse bit order" option. The vast majority of facsimile products store data LSB first (FillOrder=2, LSB-to-MSB).
    Use CCITT Group 4 compression whenever permitted by your faxing hardware and software, since CCITT Group 4 compression will usually offer a better compression ratio than CCITT Group 3.


    4. On the Advanced TIFF options dialog, specify the options to make a faxable TIFF with a preset width and height. Faxable TIFFs must have a 1728 pixel width. Some fax applications also require a specific height based on a specific number of lines such as 2200. Consult your fax application's documentation to determine what restrictions it has.
    Check the "Place Image File Directory (IFD) in front of image data" option if your fax application requires that the TIFF image file descriptor (IFD) header precede the actual TIFF data (e.g., Cisco fax-enabled routers).




    All of the Zan Image Printer specific options are grouped in several INI files, you can edit INI files manually with any plain text editor (e.g., Notepad), developers can also call Win32 APIs (GetPrivateProfileString, GetPrivateProfileInt, WritePrivateProfileString) to read or write these INI files directly to control the printer's behavior programmatically.

    ini files:
    File Name Description
    save.ini contains a set of rules for saving files and pop-up dialogs.
    image.ini contains options for image formats, color type, compression, and image quality.
    general.ini contains settings for the status dialog, sentinel file, and ZIP archiving.
    docuname.ini contains options to remove unwanted strings from document name.
    advimage.ini contains options for post generation image processing (trim, invert, crop, transpose, flip, rotate and scale).
    app.ini contains settings for running another application after printing is finished.
    text.ini contains options for text extraction.
    event.ini contains options for event notification.
    message.ini contains options for message notification.
    orientation.ini contains options for rotating landscape pages.
    email.ini contains options for sending Email.
    watermark.ini contains options for adding watermarks.
    printerredirection.ini contains options for printer redirection.
    ftp.ini contains options for sending printed output to an FTP server.



    Return to top




    Settings in save.ini
    The AppName specifies the name of the section containing the key name, AppName is the first parameter to be passed when calling the GetPrivateProfileString, GetPrivateProfileInt and WritePrivateProfileString Win32 APIs.

    KeyName specifies the name of the key whose associated string is to be retrieved. KeyName is the second parameter to be passed when calling the GetPrivateProfileString, GetPrivateProfileInt and WritePrivateProfileString Win32 APIs.

    All the data is stored either as a string or as a DWORD (32-bit integer).

    The fourth column "Command Line Utility KeyName" specifies the keyname used by the command line utilities zvprtcfg and zvprtcfg_win32.

    The table below lists all of the supported settings in save.ini.
    AppName KeyName Value Type Command Line Utility KeyName Description
    save folder string save.folder
    save.path
    save.directory
    Folder: specify where you want to save the output image files. You can insert macro commands to form the folder name dynamically
    save basefilename string save.basefilename
    save.filename
    File Name: specify the file name (Unicode supported) for the image to be created. You can also insert macro commands to form the file name dynamically
    save originaldocumentname string For every print job (printed document), the application (e.g., Word, Excel, Internet Explorer) provides a document name (displayed in the printer's document queue) to the printer driver. But the name of the original document may be different from the document name passed by the application (see the Save page for more details). If this is the case, Zan Image Printer has no direct way to know the full name of the original document.
    The originaldocumentname setting helps to circumvent this issue. By setting originaldocumentname to the full name of the original document (e.g., c:\mydocuments\plan.doc) before printing, you can save the generated images to the same folder where original file resides under the name of the original document (see "batch printing with zvprtcfg and zvprtcfg_win32" for the setup), regardless of what document name is passed by the application; you can use the following macros (if applicable) for file name, folder, application, Email, watermark, and sentinel file settings:
    [%ODocName]: the full name of the original document, example: c:\mydocuments\plan.doc

    [%srcfolder]: the path of the original document without a trailing backslash, example: c:\mydocuments

    [%ODocFileName]: the file name of the original document, example: plan.doc

    [%ODocFileNamenoext]: the file name of the original document without the extension, example: plan

    The Zan Image Printer command line utilities zvprtcfg and zvprtcfg_win32 always set originaldocumentname to the full name of the original document for each print job, so you can use the above macros when you print using zvprtcfg or zvprtcfg_win32.
    save filenameindex DWORD save.filenameindex
    save.fileindex
    Init File Number: specifies the initial count used in the File Number macro command
    save filexistact DWORD or string save.filexistact
    save.whenfileexist
    save.whenfileexists
    When File Exists:
    0 (Show warning dialog)
    1 (Auto pick a unique name to prevent collision)
    2 (Always overwrite)

    Zan Image Printer also accepts an equivalent mnemonic string for the filexistact value as mnemonic strings are easier to remember:
    the following mnemonic strings are equivalent to 1 (Auto pick a unique name to prevent collision):
    auto
    unique
    auto pick

    the mnemonic string "overwrite" is equivalent to 2 (Always overwrite)

    all other strings are converted to 0 (Show warning dialog)
    save popupdialog DWORD or string save.popupdialog
    save.dialog
    Before Printing Starts Show the:
    0 (Save As Dialog)
    1 (Image Printer Dialog)
    2 (No Dialogs)

    Zan Image Printer also accepts an equivalent mnemonic string for the popupdialog value:
    the following mnemonic strings are equivalent to 0 (Save As Dialog):
    save
    saveas

    the following mnemonic strings are equivalent to 1 (Image Printer Dialog):
    dialog
    image printer dialog

    the following mnemonic strings are equivalent to 2 (No Dialogs):
    none
    no dialog

    The following code samples explain how to retrieve the save folder and popup dialog option, as well as how to change the file name and when file exists option.
    The code samples also show how to set the file format to 2 (JPEG), the color type to 3 (true color), and then obtain the current compression method.

    VB code sample:
    Option Explicit
    
    Private Declare Sub Sleep Lib "kernel32" ( _
        ByVal dwMilliseconds As Long)
        
    Private Declare Function GetDefaultPrinter Lib "winspool.drv" _
    Alias "GetDefaultPrinterA" (ByVal pszBuffer As String, _
    pcchBuffer As Long) As Long
    
    Private Declare Function SetDefaultPrinter Lib "winspool.drv" _
    Alias "SetDefaultPrinterA" (ByVal pszPrinter As String) As Long
    
    Private Declare Function SHGetFolderPath Lib "shell32" _
    Alias "SHGetFolderPathA" _
    (ByVal hwndOwner As Long, ByVal nFolder As Long, _
    ByVal hToken As Long, ByVal dwFlags As Long, _
    ByVal pszPath As String) As Long
       
    Private Declare Function GetPrivateProfileString Lib "kernel32.dll" _
    Alias "GetPrivateProfileStringA" _
    (ByVal lpApplicationName As String, _
    ByVal lpKeyName As String, ByVal lpDefault As String, _
    ByVal lpReturnedString As String, _
    ByVal nSize As Integer, ByVal lpFileName As String) As Integer
    
    Private Declare Function GetPrivateProfileInt Lib "kernel32.dll" _
    Alias "GetPrivateProfileIntA" _
    (ByVal lpApplicationName As String, _
    ByVal lpKeyName As String, ByVal nDefault As Integer, _
    ByVal lpFileName As String) As Integer
    
    Private Declare Function WritePrivateProfileString Lib "kernel32.dll" _
    Alias "WritePrivateProfileStringA" _
    (ByVal lpApplicationName As String, _
    ByVal lpKeyName As String, ByVal lpString As String, _
    ByVal lpFileName As String) As Integer
    
    Private Declare Function WaitForSingleObject Lib "kernel32.dll" _
    (ByVal hHandle As Long, ByVal _
    dwMilliseconds As Long) As Long
    
    Private Declare Function RegCloseKey Lib "advapi32.dll" _
    (ByVal hKey As Long) As Long
    
    Private Declare Function RegOpenKeyEx Lib "advapi32.dll" _
       Alias "RegOpenKeyExA" _
      (ByVal hKey As Long, _
       ByVal lpSubKey As String, _
       ByVal ulOptions As Long, _
       ByVal samDesired As Long, _
       phkResult As Long) As Long
    
    Private Declare Function RegQueryValueEx Lib "advapi32.dll" _
    Alias "RegQueryValueExA" (ByVal hKey As Long, _
    ByVal lpValueName As String, ByVal lpReserved As Long, _
    lpType As Long, lpData As Any, lpcbData As Long) As Long
    
    
    Private Declare Function CreateEvent Lib "kernel32" _
    Alias "CreateEventA" (ByVal lpEventAttributes As Long, _
    ByVal bManualReset As Long, ByVal bInitialState As _
    Long, ByVal lpname As String) As Long
    
    Private Declare Function CloseHandle Lib "kernel32" _
    (ByVal hObject As Long) As Long
    
    
    Private Declare Function GetVersionEx Lib "kernel32" _
       Alias "GetVersionExA" _
      (lpVersionInformation As OSVERSIONINFO) As Long
    
    
    
    Private Const HKEY_LOCAL_MACHINE = &H80000002
    'Registry action types.
    Private Const ERROR_SUCCESS = 0
    Private Const STANDARD_RIGHTS_READ As Long = &H20000
    Private Const KEY_QUERY_VALUE As Long = &H1
    Private Const KEY_ENUMERATE_SUB_KEYS As Long = &H8
    Private Const KEY_NOTIFY As Long = &H10
    Private Const SYNCHRONIZE As Long = &H100000
    Private Const KEY_READ As Long = ((STANDARD_RIGHTS_READ Or _
                                       KEY_QUERY_VALUE Or _
                                       KEY_ENUMERATE_SUB_KEYS Or _
                                       KEY_NOTIFY) And _
                                       (Not SYNCHRONIZE))
    
    
    'Used CSIDL values.
    Private Const CSIDL_APPDATA As Long = &H1A
    Private Const CSIDL_PROGRAM_FILES  As Long = &H26
    Private Const CSIDL_COMMON_APPDATA As Long = &H23
    Private Const CSIDL_COMMON_DOCUMENTS As Long = &H2E
    
    Private Const SHGFP_TYPE_CURRENT = 0
    Private Const S_OK As Long = 0
    Private Const MAX_PATH = 260
    Private Const SW_SHOWNORMAL = 1
    Private Const INFINITE = &HFFFF
    
    'Windows-defined type OSVERSIONINFO
    Private Type OSVERSIONINFO
      OSVSize         As Long
      dwVerMajor      As Long 'dwVerMajor = 6: Vista or above
      dwVerMinor      As Long
      dwBuildNumber   As Long
                                     
      PlatformID      As Long
      szCSDVersion    As String * 128
                                     
    End Type
    
    
    
    'Determines whether the given path refers to an existing
    'directory
    Function DirExists(ByVal DName As String) As Boolean
    Dim sDummy As String
    On Error Resume Next
    
    If Right(DName, 1) <> "\" Then DName = DName & "\"
    sDummy = Dir$(DName & "*.*", vbDirectory)
    DirExists = Not (sDummy = "")
    End Function
    
    
    'Searches a path for a file name
    Function GetFilePath(FileName As String) As String
        Dim i As Long
        For i = Len(FileName) To 1 Step -1
            Select Case Mid$(FileName, i, 1)
                Case ":"
                    GetFilePath = Left$(FileName, i)
                    Exit For
                Case "\"
                    GetFilePath = Left$(FileName, i - 1)
                    Exit For
            End Select
        Next
    End Function
    
    
    'Determines Zan Image Printer installation directory
    Private Function GetZanInstallDir() As String
    
    Dim sPath As String
    Dim szTmp As String * MAX_PATH
    Dim lResult As Long
    Dim hKey, dwSize As Long
    
    
    dwSize = MAX_PATH
    
    'first check to see if the uninstall registry entry exists
    If RegOpenKeyEx(HKEY_LOCAL_MACHINE, _
    "\Software\Microsoft\Windows\CurrentVersion\Uninstall\zvprt50" _
          , 0&, KEY_READ, hKey) = ERROR_SUCCESS Then
          If RegQueryValueEx(hKey, "UninstallString", _
          0&, 0&, ByVal szTmp, dwSize) = ERROR_SUCCESS Then
          
          sPath = Left$(szTmp, _
                InStr(szTmp, vbNullChar) - 1)
    
          sPath = GetFilePath(sPath)
          
          If DirExists(sPath) Then
          GetZanInstallDir = sPath
          Exit Function
          End If
          
          End If
          
    End If
         
    'fallback to the \Program Files\zvprt50 folder:
    lResult = SHGetFolderPath(0, _
                       CSIDL_PROGRAM_FILES, _
                       0, _
                       SHGFP_TYPE_CURRENT, _
                       szTmp)
                       
    sPath = Left$(szTmp, _
                InStr(szTmp, vbNullChar) - 1)
                
    If Right$(sPath, 1) <> "\" Then
        sPath = sPath & "\"
     End If
     sPath = sPath & "zvprt50"
     GetZanInstallDir = sPath
    End Function
    
    
    
    'Determines Zan Image Printer
    'configuration directory for the ini setting files
    Private Function GetZanConfigurationDir(szPrinter As String) As String
       Dim sPath As String * MAX_PATH
       Dim lResult As Long
       Dim lPolicy As Long
       Dim csidl As Long
       Dim osv As OSVERSIONINFO
       Dim LRet As Long
       Dim sCfg As String
    
       'read the OS info
       osv.OSVSize = Len(osv)
       LRet = GetVersionEx(osv)
       
       'read configure.ini from
       'Zan Image Printer installation directory
       sCfg = GetZanInstallDir()
    
       If Right$(sCfg, 1) <> "\" Then
        sCfg = sCfg & "\"
       End If
       sCfg = sCfg & "configure.ini"
    
       
       'Read the all users (per-machine) folder policy
       'from configure.ini:
       
       'policy=1: auto detect, if Vista or newer,
       'use CSIDL_COMMON_DOCUMENTS as the
       'all users (per-machine) folder;
       'otherwise, use CSIDL_COMMON_APPDATA
       'policy=2: use CSIDL_COMMON_APPDATA
       'policy=3: use CSIDL_COMMON_DOCUMENTS
    
       lPolicy = GetPrivateProfileInt("allusersfolder", "policy", _
       1, sCfg)
       
       'handle the auto detect policy
       If lPolicy = 1 Then
         'Vista and 2008: dwVerMajor>=6
         If osv.dwVerMajor >= 6 Then
         lPolicy = 3
         Else
         lPolicy = 2
         End If
       End If
       
       If lPolicy = 2 Then
       csidl = CSIDL_COMMON_APPDATA
       Else
       csidl = CSIDL_COMMON_DOCUMENTS
       End If
        
       
       'get the all users (per-machine) folder
       lResult = SHGetFolderPath(0, _
                       csidl, _
                       0, _
                       SHGFP_TYPE_CURRENT, _
                       sPath)
                       
       sCfg = Left$(sPath, _
                InStr(sPath, vbNullChar) - 1)
                
       If Right$(sCfg, 1) <> "\" Then
        sCfg = sCfg & "\"
       End If
       sCfg = sCfg & "zvprt50\" & szPrinter
       
       'if the all users (per-machine) folder exists,
       'then this zan image printer was installed per-machine:
       'all users share the same settings
       If DirExists(sCfg) Then
       'all users will share the same
       'settings for the printer
       GetZanConfigurationDir = sCfg
       Exit Function
       End If
       
       'if the all users (per-machine) folder doesn't exist,
       'assume each user has his own settings
       'for the printer:
       lResult = SHGetFolderPath(0, _
                       CSIDL_APPDATA, _
                       0, _
                       SHGFP_TYPE_CURRENT, _
                       sPath)
                       
       sCfg = Left$(sPath, _
                InStr(sPath, vbNullChar) - 1)
                
       If Right$(sCfg, 1) <> "\" Then
        sCfg = sCfg & "\"
       End If
       sCfg = sCfg & "zvprt50\" & szPrinter
       
       GetZanConfigurationDir = sCfg
    End Function
    
    
    
    
    
    
    Public Sub Main()
    Dim IniFileFolder As String
    Dim SaveFolder As String * MAX_PATH
    Dim PopupDlgInd As Integer
    Dim SaveIniFileFolder As String
    Dim ImageIniFileFolder As String
    Dim Compress As Integer
    
    
    IniFileFolder = GetZanConfigurationDir("Zan Image Printer(bw)")
    If Right$(IniFileFolder, 1) <> "\" Then
        IniFileFolder = IniFileFolder & "\"
    End If
    
    'save.ini read/write:
    SaveIniFileFolder = IniFileFolder & "save.ini"
     
    GetPrivateProfileString "save", "folder", "", _
     SaveFolder, MAX_PATH, SaveIniFileFolder
     
    SaveFolder = Left$(SaveFolder, _
                InStr(SaveFolder, vbNullChar) - 1)
     
    WritePrivateProfileString "save", "basefilename", _
     "[%DocName]_[%Page]", SaveIniFileFolder
    
    PopupDlgInd = GetPrivateProfileInt("save", "popupdialog", _
      0, SaveIniFileFolder)
    
    WritePrivateProfileString "save", "filexistact", "1", _
      SaveIniFileFolder
      
      
    'image.ini read/write:
    ImageIniFileFolder = IniFileFolder & "image.ini"
    
    WritePrivateProfileString "image", "fileformat", "2", ImageIniFileFolder
    
    WritePrivateProfileString "image", "imagecolor", "3", ImageIniFileFolder
    
    Compress = GetPrivateProfileInt("image", "compression", _
     0, ImageIniFileFolder)
    
    
    End Sub
    
    

    Delphi code sample:
    unit zanprinter;
    
    interface
    
    uses
    Windows, Messages, SysUtils, ShlObj, ShellAPI, SHFolder, ComObj;
    
    function GetDefaultPrinter(prnName:PAnsiChar; var bufSize:DWORD):
    BOOL; stdcall; external 'winspool.drv' name 'GetDefaultPrinterA';
    
    function SetDefaultPrinter(prnName:PAnsiChar):
    BOOL; stdcall; external 'winspool.drv' name 'SetDefaultPrinterA';
    
    procedure GetZanInstallDir(var APath: String);
    procedure GetZanConfigurationDir(var szPrinter: String;
    var cfgdir: String);
    procedure readwriteini();
    
    
    implementation
    
    //Determines Zan Image Printer installation directory
    procedure GetZanInstallDir(var APath: String);
    var
      hkeyStartup: HKEY;
      dwSize: DWORD;
    begin
      dwSize := MAX_PATH;
      SetLength(APath, MAX_PATH);
    
      //first check to see if the uninstall registry entry exists
      if RegOpenKeyEx(HKEY_LOCAL_MACHINE,
       '\Software\Microsoft\Windows\CurrentVersion\Uninstall\zvprt50',
       0,
       KEY_READ,
       hkeyStartup) = ERROR_SUCCESS then
       begin
    
       if RegQueryValueEx(hkeyStartup,
                         'UninstallString', nil, nil,
                          PBYTE(Pchar(APath)),
                          @dwSize) = ERROR_SUCCESS then
       begin
          APath := String (PChar(APath));
          APath := ExtractFilePath(APath);
       end;
    
       //Close the Key, we won't be needing it anymore
       RegCloseKey(hkeyStartup);
    
       if DirectoryExists(APath) then Exit;
      end;
    
      //fallback to the \Program Files\zvprt50 folder:
      SHGetFolderPath(0, CSIDL_PROGRAM_FILES, 0, 0,
                      PChar(APath));
    
      APath := String (PChar (APath));
      if (APath[Length(APath)] <> '\')
      then APath := APath + '\';
    
      APath := APath + 'zvprt50';
    end;
    
    
    //Determines Zan Image Printer
    //configuration directory for the ini setting files
    procedure GetZanConfigurationDir(var szPrinter: String;
    var cfgdir: String);
    var
      osv: TOSVersionInfo;
      lPolicy, csidl: Integer;
    begin
      SetLength(cfgdir, MAX_PATH);
    
      //read the OS info
      FillChar(osv, SizeOf(osv), 0);
      osv.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
      GetVersionEx(osv);
    
      //read configure.ini from
      //Zan Image Printer installation directory
      GetZanInstallDir(cfgdir);
      if (cfgdir[Length(cfgdir)] <> '\') then cfgdir := cfgdir + '\';
      cfgdir := cfgdir + 'configure.ini';
    
      //read configure.ini from
      //Zan Image Printer installation directory.
      //Read the all users (per-machine) folder policy
      //from configure.ini:
    
      //policy=1: auto detect, if Vista or newer,
      //use CSIDL_COMMON_DOCUMENTS as the
      //all users (per-machine) folder;
      //otherwise, use CSIDL_COMMON_APPDATA
      //policy=2: use CSIDL_COMMON_APPDATA
      //policy=3: use CSIDL_COMMON_DOCUMENTS
      lPolicy := GetPrivateProfileInt('allusersfolder', 'policy',
       1, PChar(cfgdir));
    
      //handle the auto detect policy
      if lPolicy = 1 then
      begin
         //Vista and 2008: dwVerMajor>=6
         if osv.dwMajorVersion >= 6 then lPolicy := 3
         else  lPolicy := 2;
      end;
    
      if lPolicy = 2 then  csidl := CSIDL_COMMON_APPDATA
      else  csidl := CSIDL_COMMON_DOCUMENTS;
    
      //get the all users (per-machine) folder
      SetLength(cfgdir, MAX_PATH);
      SHGetFolderPath(0, csidl, 0, 0, PChar(cfgdir));
      cfgdir := String (PChar (cfgdir));
      if (cfgdir[Length(cfgdir)] <> '\') then cfgdir := cfgdir + '\';
      cfgdir := cfgdir + 'zvprt50\' + szPrinter;
    
      //if the all users (per-machine) folder exists,
      //then this zan image printer was installed per-machine:
      //all users share the same settings
      if DirectoryExists(cfgdir) then Exit;
    
      //if the all users (per-machine) folder doesn't exist,
      //assume each user has his own settings
      //for the printer:
      SHGetFolderPath(0, CSIDL_APPDATA, 0, 0, PChar(cfgdir));
      cfgdir := String (PChar (cfgdir));
      if (cfgdir[Length(cfgdir)] <> '\') then cfgdir := cfgdir + '\';
      cfgdir := cfgdir + 'zvprt50\' + szPrinter;
    end;
    
    
    
    procedure readwriteini();
    var
    inifilepath: String;
    saveinifilepath: String;
    imageinifilepath: String;
    SaveFolder: String;
    szPrinter: String;
    PopupDlgInd: Integer;
    dwCompress: Integer;
    begin
     szPrinter := 'Zan Image Printer(bw)';
     SetLength(SaveFolder, MAX_PATH);
    
     GetZanConfigurationDir(szPrinter, inifilepath);
     if (inifilepath[Length(inifilepath)] <> '\')
     then inifilepath := inifilepath + '\';
    
     //save.ini read/write:
     saveinifilepath := inifilepath + 'save.ini';
    
     GetPrivateProfileString('save','folder','',
       PChar(SaveFolder),MAX_PATH, PChar(saveinifilepath));
    
     WritePrivateProfileString('save', 'basefilename',
       '[%DocName]_[%Page]', PChar(saveinifilepath));
    
     PopupDlgInd := GetPrivateProfileInt('save','popupdialog',
       0, PChar(saveinifilepath));
    
     WritePrivateProfileString('save', 'filexistact', '1',
       PChar(saveinifilepath));
     //use SaveFolder, PopupDlgInd...
    
     //image.ini read/write:
     imageinifilepath := inifilepath + 'image.ini';
     WritePrivateProfileString('image', 'fileformat',
                               'jpeg', PChar(imageinifilepath));
     WritePrivateProfileString('image', 'imagecolor',
                               'True Color', PChar(imageinifilepath));
     dwCompress := GetPrivateProfileInt('image','compression',
                               0, PChar(imageinifilepath));
     //use dwCompress ...
    
    end;
    
    end.
    

    C code sample:
    
    #include <windows.h>
    #include <winspool.h>
    #include <shlobj.h>
    #include <shlwapi.h>
    #include <shellapi.h>
    
    #pragma comment(lib, "shlwapi.lib")
    
    
    //Determines whether the given path refers to 
    //an existing directory
    BOOL IsFolderExists(char *lpDirectoryName)
    {
    	if(0 == strlen(lpDirectoryName))
    	{
    		return FALSE;
    	}
    
    	DWORD dwFileAttr = GetFileAttributes(lpDirectoryName);
    
    	if((dwFileAttr != 0xFFFFFFFF) &&
    		(dwFileAttr & FILE_ATTRIBUTE_DIRECTORY))
    	{
    		return TRUE;
    	}
    	else
    	{
    		return FALSE;
    	}
    }
    
    
    
    //Determines Zan Image Printer installation directory
    void GetZanInstallDir(char *installfolder)
    {
    	HKEY hkeyStartup;
    
    	//first check to see if the uninstall registry entry exists
    	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
    		"\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\zvprt50",
    		0,          
    		KEY_READ,  
    		&hkeyStartup) == ERROR_SUCCESS)
    	{
    		DWORD dwSize = MAX_PATH;
    
    		if(RegQueryValueEx(hkeyStartup, 
    			"UninstallString", 
    			NULL,
    			NULL,
    			(LPBYTE)installfolder,
    			&dwSize) == ERROR_SUCCESS)
    		{
    			PathRemoveFileSpec(installfolder);
    			PathAddBackslash(installfolder);
    		}
    
    		/*Close the Key, we won't be needing it anymore*/
    		RegCloseKey(hkeyStartup);
    
    		if(IsFolderExists(installfolder))
    		{
    			return;
    		}
    	}
    
    	//fallback to the \Program Files\zvprt50 folder:
    	SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, 0, installfolder);
    	PathAddBackslash(installfolder);
    
    	strcat(installfolder,"zvprt50");
    }
    
    
    
    BOOL IsVistaOrAbove(void)
    {
    	OSVERSIONINFOEX osvi;
    	BOOL bOsVersionInfoEx;
    
    	ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
    
    	//Try calling GetVersionEx using the OSVERSIONINFOEX structure.
    	//If that fails, try using the OSVERSIONINFO structure.
    	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    	if(!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*)&osvi)))
    	{
    		osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    		if(!GetVersionEx((OSVERSIONINFO*)&osvi))
    			return FALSE;
    	}
    
    	//vista and 2008: 6
    	//2003: 5
    	//xp: 5
    	if(osvi.dwMajorVersion >= 6)
    	{
    		return TRUE;
    	}
    	else
    	{
    		return FALSE;
    	}
    }
    
    
    
    //Determines Zan Image Printer
    //configuration directory for the ini setting files
    void GetZanConfigurationDir(char *sPrinter, char *sCfg)
    {
    	DWORD lPolicy;
    	DWORD csidl;
    
    	//read configure.ini from
    	//Zan Image Printer installation directory
    	GetZanInstallDir(sCfg);
    	PathAddBackslash(sCfg);
    	strcat(sCfg,"configure.ini");
    
    	//Read the all users (per-machine) folder policy
    	//from configure.ini:
    
    	//policy=1: auto detect, if Vista or newer,
    	//use CSIDL_COMMON_DOCUMENTS as the
    	//all users (per-machine) folder;
    	//otherwise, use CSIDL_COMMON_APPDATA
    	//policy=2: use CSIDL_COMMON_APPDATA
    	//policy=3: use CSIDL_COMMON_DOCUMENTS
    
    	lPolicy = GetPrivateProfileInt("allusersfolder", 
    		"policy", 1, sCfg);
    
    	//handle the auto detect policy
    	if(1 == lPolicy)
    	{
    		if(IsVistaOrAbove())  lPolicy = 3;
    		else lPolicy = 2;
    	}
    
    
    	if(2 == lPolicy)
    	{
    		csidl = CSIDL_COMMON_APPDATA;
    	}
    	else
    	{
    		csidl = CSIDL_COMMON_DOCUMENTS;
    	}
    
    	//get the all users (per-machine) folder
    	SHGetFolderPath(NULL, csidl, NULL, 0, sCfg);
    	PathAddBackslash(sCfg);
    	strcat(sCfg, "zvprt50\\");
    	strcat(sCfg, sPrinter);
    		
    
    	//if the all users (per-machine) folder exists,
    	//then this zan image printer was installed per-machine: 
    	//all users share the same settings
    	if(IsFolderExists(sCfg)) return;
    
    
    	//if the all users (per-machine) folder doesn't exist,
    	//assume each user has his own settings
    	//for the printer:
    	SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, sCfg);
    	PathAddBackslash(sCfg);
    	strcat(sCfg, "zvprt50\\");
    	strcat(sCfg, sPrinter);
    }
    
    
    
    int main(int argc, char* argv[])
    {
    	char inifilepath[MAX_PATH];
    	char saveinifilepath[MAX_PATH];
    	char imageinifilepath[MAX_PATH];
    	char SaveFolder[MAX_PATH];
        DWORD dwPopupDlg;
    	DWORD dwCompress;
    
    	char *szPrinter = "zan image printer(bw)";
    
    	GetZanConfigurationDir(szPrinter, inifilepath);
    	PathAddBackslash(inifilepath);
    
    	//save.ini read/write:
    	strcpy(saveinifilepath, inifilepath);
    	strcat(saveinifilepath, "save.ini");
    
    	GetPrivateProfileString("save", "folder", "", SaveFolder, 
    		MAX_PATH, saveinifilepath);
    
    	WritePrivateProfileString("save", "basefilename", 
    		"[%DocName]_[%Page]", saveinifilepath);
    
    	dwPopupDlg = GetPrivateProfileInt("save", "popupdialog", 
    		0, saveinifilepath);
    
    	WritePrivateProfileString("save", "filexistact", "1", 
    		saveinifilepath);
    
    
    	//image.ini read/write:
    	strcpy(imageinifilepath, inifilepath);
    	strcat(imageinifilepath, "image.ini");
    
    	WritePrivateProfileString("image", "fileformat", "2", 
    		imageinifilepath);
    
    	WritePrivateProfileString("image", "imagecolor", "3", 
    		imageinifilepath);
    
    	dwCompress = GetPrivateProfileInt("image", "compression", 
    		0, imageinifilepath);
    
    	return 0;
    }
    

    VC.NET code sample:
    using namespace System;
    using namespace System::Text;
    using namespace System::Runtime::InteropServices;
    using namespace System::Threading;
    using namespace System::IO;
    using namespace System::Diagnostics;
    using namespace Microsoft::Win32;
    
    
    // Declare the function that is exported from unmanaged dll:
    [DllImport("winspool.drv")]
    extern "C" bool _cdecl GetDefaultPrinter(
    	 StringBuilder^ pszBuffer, int *size);
    
    [DllImport("winspool.drv")]
    extern "C" bool _cdecl SetDefaultPrinter(
    	 String^ pszPrinter);
    
    [DllImport("KERNEL32.DLL")]
    extern "C" int _cdecl GetPrivateProfileString(
       String^ lpAppName, 
       String^ lpKeyName,
       String^ lpDefault, 
       StringBuilder^ lpReturnedString, 
       int nSize,
       String^ lpFileName);
    
    [DllImport("KERNEL32.DLL")]
    extern "C" bool _cdecl WritePrivateProfileString(
       String^ lpAppName, 
       String^ lpKeyName,
       String^ lpString, 
       String^ lpFileName);
    
    [DllImport("KERNEL32.DLL")]
    extern "C" int _cdecl GetPrivateProfileInt(
       String^ lpAppName, 
       String^ lpKeyName,
       int nDefault, 
       String^ lpFileName);
    
    [DllImport("shell32.dll")]
    extern "C" bool _cdecl SHGetFolderPath(int hwndOwner,
    int nFolder, int hToken, int dwFlags, StringBuilder^ pszPath);
    const int CSIDL_COMMON_DOCUMENTS = 0x002e;
    
    
    
    //Determines Zan Image Printer installation directory
    String^ GetZanInstallDir(void)
    {
    	String^ installfolder = String::Empty;
    	RegistryKey ^ rkTest;
    
    	//first check to see if the uninstall registry entry exists
    	rkTest = Registry::LocalMachine->OpenSubKey(
    		L"\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\zvprt50");
    	if(rkTest)
    	{
    		installfolder = rkTest->GetValue(L"UninstallString")->ToString();
    		rkTest->Close();
    
    		if(installfolder->Length)
    		{
    			installfolder = Path::GetDirectoryName(installfolder);
    
    			DirectoryInfo^ installdir1=gcnew DirectoryInfo(installfolder);
    			if(installdir1->Exists)
    			{
    				return installfolder;
    			}
    		}
    	}
    
    	//fallback to the \Program Files\zvprt50 folder:
    	installfolder = Environment::GetFolderPath
    		(Environment::SpecialFolder::ProgramFiles);
    
    	if(!installfolder->EndsWith(L"\\")) 
    		installfolder = String::Concat(installfolder, L"\\");
    
    	installfolder=String::Concat(installfolder, L"zvprt50");
    
    	return installfolder;
    }
    
    
    //Determines Zan Image Printer
    //configuration directory for the ini setting files
    String^ GetZanConfigurationDir(String^ szPrinter)
    {
    	//read the OS info
    	OperatingSystem^ os = System::Environment::OSVersion;
    	String^ sCfg;
    	int lPolicy;
    	StringBuilder^ tmpstr = gcnew StringBuilder(256);
    
    	//read configure.ini from
    	//Zan Image Printer installation directory
    	sCfg = GetZanInstallDir();
    
    	if(!sCfg->EndsWith(L"\\")) 
    		sCfg = String::Concat(sCfg, L"\\");
    
    	sCfg = String::Concat(sCfg, L"configure.ini");
    
    
    	//Read the all users (per-machine) folder policy
    	//from configure.ini:
    
    	//policy=1: auto detect, if Vista or newer,
    	//use CSIDL_COMMON_DOCUMENTS as the
    	//all users (per-machine) folder;
    	//otherwise, use CSIDL_COMMON_APPDATA
    	//policy=2: use CSIDL_COMMON_APPDATA
    	//policy=3: use CSIDL_COMMON_DOCUMENTS
    
    	lPolicy = GetPrivateProfileInt(L"allusersfolder", L"policy",
    		1, sCfg);
    
    	//handle the auto detect policy
    	if(1 == lPolicy)
    	{
    		//Vista and 2008: dwVerMajor>=6
    		if(os->Version->Major >= 6)
    		{
    			lPolicy = 3;
    		}
    		else
    		{
    			lPolicy = 2;
    		}
    	}
    
    
    	//get the all users (per-machine) folder
    	//if the all users (per-machine) folder exists,
    	//then this zan image printer was installed per-machine: 
    	//all users share the same settings
    	if(2 == lPolicy)
    	{
    		//csidl = CSIDL_COMMON_APPDATA;
    		sCfg = Environment::GetFolderPath
    			(Environment::SpecialFolder::CommonApplicationData);
    
    	}
    	else
    	{
    		//csidl = CSIDL_COMMON_DOCUMENTS;
    		SHGetFolderPath(0, CSIDL_COMMON_DOCUMENTS, 0, 0, tmpstr);
    		sCfg = tmpstr->ToString();
    	}
    
    	if(!sCfg->EndsWith(L"\\")) sCfg = String::Concat(sCfg, L"\\");
    	sCfg = String::Concat(sCfg, L"zvprt50\\");
    	sCfg = String::Concat(sCfg, szPrinter);
    
    	//all users will share the same
    	//settings for the printer
    	DirectoryInfo^ tmpdir = gcnew DirectoryInfo(sCfg);
    	if(tmpdir->Exists)
    	{
    		return sCfg;
    	}
    
    	//if the all users (per-machine) folder doesn't exist,
    	//assume each user has his own settings
    	//for the printer:
    	sCfg = Environment::GetFolderPath
    		(Environment::SpecialFolder::ApplicationData);
    
    	if(!sCfg->EndsWith(L"\\")) sCfg = String::Concat(sCfg, L"\\");
    	sCfg = String::Concat(sCfg, L"zvprt50\\");
    	sCfg = String::Concat(sCfg, szPrinter);
    
    	return sCfg;
    }
    
    
    
    int main(array ^args)
    {
    	String^ inifilepath;
    	String^ saveinifilepath;
    	String^ imageinifilepath;
    	String^ szFolder;
    	StringBuilder^ tmpstr = gcnew StringBuilder(256);
    
    	inifilepath = GetZanConfigurationDir(L"zan image printer(bw)");
    	if(!inifilepath->EndsWith(L"\\")) inifilepath = String::Concat(inifilepath, L"\\");
    
    	//save.ini read/write:
    	saveinifilepath = String::Concat(inifilepath, L"save.ini");
    
    	GetPrivateProfileString(L"save", L"folder", L"", 
    		tmpstr, tmpstr->Capacity, saveinifilepath);
    	szFolder = tmpstr->ToString();
    
    	WritePrivateProfileString(L"save", L"basefilename", 
    		L"[%DocName]_[%Page]", saveinifilepath);
    
    	int dwPopupDlg = GetPrivateProfileInt(L"save", L"popupdialog",  
    		0, saveinifilepath);
    
    	WritePrivateProfileString(L"save", L"filexistact", L"1", saveinifilepath);
    
    	//image.ini read/write:
    	imageinifilepath = String::Concat(inifilepath, L"image.ini");
    	WritePrivateProfileString(L"image", L"fileformat", L"2", imageinifilepath);
    	WritePrivateProfileString(L"image", L"imagecolor", L"3", imageinifilepath);
    
    	int dwCompress = GetPrivateProfileInt(L"image", L"compression", 
    		0, imageinifilepath);
    
    	return 0;
    }
    

    VB.NET code sample:
    Imports System
    Imports System.Runtime.InteropServices
    Imports System.Text
    Imports System.IO
    Imports System.Diagnostics
    Imports System.Threading
    Imports Microsoft.Win32
    
    
    
    Module Module1
        Declare Function GetDefaultPrinter Lib "winspool.drv" Alias _
        "GetDefaultPrinterA" (ByVal pszBuffer As System.Text.StringBuilder, _
        ByRef size As Int32) As Boolean
    
        Declare Function SetDefaultPrinter Lib "winspool.drv" Alias _
        "SetDefaultPrinterA" (ByVal pszPrinter As String) As Boolean
    
        Private Declare Function GetPrivateProfileString Lib "kernel32" _
             Alias "GetPrivateProfileStringA" _
            (ByVal lpAppName As String, _
             ByVal lpKeyName As String, _
             ByVal lpDefault As String, _
             ByVal lpReturnedString As StringBuilder, _
             ByVal nSize As Integer, _
             ByVal lpFileName As String) As Integer
    
        Private Declare Function GetPrivateProfileInt Lib "kernel32.dll" _
                Alias "GetPrivateProfileIntA" _
               (ByVal lpApplicationName _
                As String, ByVal lpKeyName As String, ByVal nDefault As _
                Integer, ByVal lpFileName As String) As Integer
    
        Private Declare Function WritePrivateProfileString Lib "kernel32.dll" _
                Alias "WritePrivateProfileStringA" _
               (ByVal lpAppName As String, _
                ByVal lpKeyName As String, _
                ByVal lpString As String, _
                ByVal lpFileName As String) As Boolean
    
        Private Declare Function SHGetFolderPath Lib "shell32.dll" _
        Alias "SHGetFolderPathA" _
        (ByVal hwndOwner As Integer, _
        ByVal nFolder As Integer, _
        ByVal hToken As Integer, _
        ByVal dwFlags As Integer, _
        ByVal pszPath As StringBuilder) As Integer
    
        'All Users\Documents 
        Private Const CSIDL_COMMON_DOCUMENTS = &H2E
    
    
        'Determines Zan Image Printer installation directory
        Function GetZanInstallDir() As String
            Dim installfolder As String
            Dim rkTest As RegistryKey
    
            'first check to see if the uninstall registry entry exists
            rkTest = Registry.LocalMachine.OpenSubKey _
     ("SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\zvprt50")
    
            If Not (rkTest Is Nothing) Then
                installfolder = rkTest.GetValue _
                  ("UninstallString").ToString()
                rkTest.Close()
                If (installfolder.Length > 0) Then
                    installfolder = Path.GetDirectoryName(installfolder)
                    Dim installdir1 As DirectoryInfo = _
                       New DirectoryInfo(installfolder)
    
                    If installdir1.Exists Then
                        Return installfolder
                    End If
                End If
            End If
            'fallback to the \Program Files\zvprt50 folder:
            installfolder = Environment.GetFolderPath _
    (Environment.SpecialFolder.ProgramFiles)
    
            If Not installfolder.EndsWith("\") Then
                installfolder = String.Concat(installfolder, "\")
            End If
    
            installfolder = String.Concat(installfolder, "zvprt50")
            Return installfolder
        End Function
    
    
        'Determines Zan Image Printer
        'configuration directory for the ini setting files
        Function GetZanConfigurationDir(ByVal szPrinter As String) As String
            'read the OS info
            Dim os As OperatingSystem
            Dim sCfg As String
            Dim lPolicy As Integer
            Dim tmpstr As StringBuilder
    
            tmpstr = New StringBuilder(256)
    
            os = System.Environment.OSVersion
    
            'read configure.ini from
            'Zan Image Printer installation directory
            sCfg = GetZanInstallDir()
    
            If Not sCfg.EndsWith("\") Then
                sCfg = String.Concat(sCfg, "\")
            End If
    
            sCfg = String.Concat(sCfg, "configure.ini")
    
    
            'Read the all users (per-machine) folder policy
            'from configure.ini:
    
            'policy=1: auto detect, if Vista or newer,
            'use CSIDL_COMMON_DOCUMENTS as the
            'all users (per-machine) folder;
            'otherwise, use CSIDL_COMMON_APPDATA
            'policy=2: use CSIDL_COMMON_APPDATA
            'policy=3: use CSIDL_COMMON_DOCUMENTS
    
            lPolicy = GetPrivateProfileInt("allusersfolder", _
                "policy", 1, sCfg)
    
            'Vista and 2008: dwVerMajor>=6
            If lPolicy = 1 Then
                If os.Version.Major >= 6 Then
                    lPolicy = 3
                Else
                    lPolicy = 2
                End If
            End If
    
    
            'get the all users (per-machine) folder
            'if the all users (per-machine) folder exists,
            'then this zan image printer was installed per-machine: 
            'all users share the same settings
            If lPolicy = 2 Then
                'csidl = CSIDL_COMMON_APPDATA;
                sCfg = Environment.GetFolderPath( _
                Environment.SpecialFolder.CommonApplicationData)
            Else
                'csidl = CSIDL_COMMON_DOCUMENTS;
                SHGetFolderPath(0, CSIDL_COMMON_DOCUMENTS, 0, 0, tmpstr)
                sCfg = tmpstr.ToString()
            End If
    
    
            If Not sCfg.EndsWith("\") Then
                sCfg = String.Concat(sCfg, "\")
            End If
            sCfg = String.Concat(sCfg, "zvprt50\")
            sCfg = String.Concat(sCfg, szPrinter)
    
            'all users will share the same
            'settings for the printer
            Dim tmpdir As DirectoryInfo = _
                       New DirectoryInfo(sCfg)
    
            If tmpdir.Exists Then
                Return sCfg
            End If
    
            'if the all users (per-machine) folder doesn't exist,
            'assume each user has his own settings
            'for the printer:
            sCfg = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
    
            If Not sCfg.EndsWith("\") Then
                sCfg = String.Concat(sCfg, "\")
            End If
            sCfg = String.Concat(sCfg, "zvprt50\")
            sCfg = String.Concat(sCfg, szPrinter)
    
            Return sCfg
        End Function
    
    
    
        Sub Main()
            Dim inifilepath As String
            Dim saveinifilepath As String
            Dim imageinifilepath As String
            Dim szFolder As String
            Dim tmpstr As StringBuilder
    
            inifilepath = GetZanConfigurationDir("zan image printer(bw)")
    
            If Not inifilepath.EndsWith("\") Then
                inifilepath = String.Concat(inifilepath, "\")
            End If
    
            'save.ini read/write:
            saveinifilepath = String.Concat(inifilepath, "save.ini")
    
            tmpstr = New StringBuilder(256)
            GetPrivateProfileString("save", "folder", "", tmpstr, _
                tmpstr.Capacity, saveinifilepath)
            szFolder = tmpstr.ToString()
            
            WritePrivateProfileString("save", "basefilename", _
            "[%DocName]_[%Page]", saveinifilepath)
    
            Dim PopupDlgInd As Integer
    
            PopupDlgInd = GetPrivateProfileInt("save", "popupdialog", 0, _
             saveinifilepath)
    
            WritePrivateProfileString("save", "filexistact", "1", saveinifilepath)
    
            'image.ini read/write:
            imageinifilepath = String.Concat(inifilepath, "image.ini")
    
            Dim dwCompress As Integer
    
            WritePrivateProfileString("image", "fileformat", "2", imageinifilepath)
            WritePrivateProfileString("image", "imagecolor", "3", imageinifilepath)
            dwCompress = GetPrivateProfileInt("image", "compression", _
                        0, imageinifilepath)
    
        End Sub
    
    End Module
    
    

    C# code sample:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.IO;
    using Microsoft.Win32;
    
    
    namespace readwriteini_csharp
    {
        class Program
        {
            //Determines Zan Image Printer installation directory
            static string GetZanInstallDir()
            {
                string installfolder = string.Empty;
                RegistryKey rkTest;
    
                //first check to see if the uninstall registry entry exists
                rkTest = Registry.LocalMachine.OpenSubKey(
                "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\zvprt50");
    
                if (rkTest != null)
                {
                    installfolder = rkTest.GetValue("UninstallString").ToString();
                    rkTest.Close();
    
                    if (installfolder.Length > 0)
                    {
                        installfolder = Path.GetDirectoryName(installfolder);
    
                        DirectoryInfo installdir1 = new DirectoryInfo(installfolder);
                        if (installdir1.Exists)
                        {
                            return installfolder;
                        }
                    }
                }
    
                //fallback to the \Program Files\zvprt50 folder:
                installfolder = Environment.GetFolderPath
                    (Environment.SpecialFolder.ProgramFiles);
    
                if (!installfolder.EndsWith("\\"))
                    installfolder = string.Concat(installfolder, "\\");
    
                installfolder = string.Concat(installfolder, "zvprt50");
    
                return installfolder;
            }
    
    
    
            //Determines Zan Image Printer
            //configuration directory for the ini setting files
            static string GetZanConfigurationDir(string szPrinter)
            {
                //read the OS info
                OperatingSystem os = System.Environment.OSVersion;
                string sCfg;
                uint lPolicy;
                StringBuilder tmpstr = new StringBuilder(256);
    
                //read configure.ini from
                //Zan Image Printer installation directory
                sCfg = GetZanInstallDir();
    
                if (!sCfg.EndsWith("\\"))
                    sCfg = string.Concat(sCfg, "\\");
    
                sCfg = string.Concat(sCfg, "configure.ini");
    
    
                //Read the all users (per-machine) folder policy
                //from configure.ini:
    
                //policy=1: auto detect, if Vista or newer,
                //use CSIDL_COMMON_DOCUMENTS as the
                //all users (per-machine) folder;
                //otherwise, use CSIDL_COMMON_APPDATA
                //policy=2: use CSIDL_COMMON_APPDATA
                //policy=3: use CSIDL_COMMON_DOCUMENTS
    
                lPolicy = GetPrivateProfileInt("allusersfolder", "policy",
                    1, sCfg);
    
                //handle the auto detect policy
                if (1 == lPolicy)
                {
                    //Vista and 2008: dwVerMajor>=6
                    if (os.Version.Major >= 6)
                    {
                        lPolicy = 3;
                    }
                    else
                    {
                        lPolicy = 2;
                    }
                }
    
    
                //get the all users (per-machine) folder
                //if the all users (per-machine) folder exists,
                //then this zan image printer was installed per-machine: 
                //all users share the same settings
                if (2 == lPolicy)
                {
                    //csidl = CSIDL_COMMON_APPDATA;
                    sCfg = Environment.GetFolderPath
                        (Environment.SpecialFolder.CommonApplicationData);
    
                }
                else
                {
                    //csidl = CSIDL_COMMON_DOCUMENTS;
                    SHGetFolderPath(0, CSIDL_COMMON_DOCUMENTS, 0, 0, tmpstr);
                    sCfg = tmpstr.ToString();
                }
    
                if (!sCfg.EndsWith("\\")) sCfg = string.Concat(sCfg, "\\");
                sCfg = string.Concat(sCfg, "zvprt50\\");
                sCfg = string.Concat(sCfg, szPrinter);
    
                //all users will share the same
                //settings for the printer
                DirectoryInfo tmpdir = new DirectoryInfo(sCfg);
                if (tmpdir.Exists)
                {
                    return sCfg;
                }
    
                //if the all users (per-machine) folder doesn't exist,
                //assume each user has his own settings
                //for the printer:
                sCfg = Environment.GetFolderPath
                    (Environment.SpecialFolder.ApplicationData);
    
                if (!sCfg.EndsWith("\\")) sCfg = string.Concat(sCfg, "\\");
                sCfg = string.Concat(sCfg, "zvprt50\\");
                sCfg = string.Concat(sCfg, szPrinter);
    
                return sCfg;
            }
    
    
    
    
            static void Main(string[] args)
            {
                string inifilepath;
                string saveinifilepath;
                string imageinifilepath;
                string szFolder;
                string szPrinter;
                StringBuilder tmpstr = new StringBuilder(256);
    
                szPrinter = "zan image printer(bw)";
    
                inifilepath = GetZanConfigurationDir(szPrinter);
                if (!inifilepath.EndsWith("\\")) inifilepath =
                    String.Concat(inifilepath, "\\");
    
                //save.ini read/write:
                saveinifilepath = String.Concat(inifilepath, "save.ini");
    
                GetPrivateProfileString("save", "folder", "",
                    tmpstr, tmpstr.Capacity, saveinifilepath);
                szFolder = tmpstr.ToString();
    
                WritePrivateProfileString("save", "basefilename",
                    "[%DocName]_[%Page]", saveinifilepath);
    
                uint dwPopupDlg = GetPrivateProfileInt("save", "popupdialog",
                    0, saveinifilepath);
    
                WritePrivateProfileString("save", "filexistact", "1", saveinifilepath);
    
                //image.ini read/write:
                imageinifilepath = String.Concat(inifilepath, "image.ini");
    
                WritePrivateProfileString("image", "fileformat", "2", 
                    imageinifilepath);
    
                WritePrivateProfileString("image", "imagecolor", "3", 
                    imageinifilepath);
    
                uint dwCompress = GetPrivateProfileInt("image",
                    "compression", 0, imageinifilepath);
    
            }
    
            [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern bool GetDefaultPrinter(StringBuilder pszBuffer,
            ref int size);
    
            [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern bool SetDefaultPrinter(string Name);
    
            [DllImport("kernel32.dll")]
            static extern uint GetPrivateProfileString(string lpAppName,
                string lpKeyName, string lpDefault,
                StringBuilder lpReturnedString, int nSize, string lpFileName);
    
            [DllImport("kernel32.dll")]
            static extern bool WritePrivateProfileString(string lpAppName,
                                                         string lpKeyName,
                string lpString, string lpFileName);
    
            [DllImport("kernel32.dll")]
            static extern uint GetPrivateProfileInt(string lpAppName,
                string lpKeyName, int nDefault, string lpFileName);
    
    
            [DllImport("shell32.dll")]
            static extern bool SHGetFolderPath(int hwndOwner,
            int nFolder, int hToken, int dwFlags, StringBuilder pszPath);
            const int CSIDL_COMMON_DOCUMENTS = 0x002e;
    
        }
    }
    
    
    The command line syntax to set the basefilename to [%DocName]_[%Page] is:
    zvprtcfg Zan Image Printer(bw) save.basefilename=[%DocName]_[%Page]
    or:
    zvprtcfg_win32 Zan Image Printer(bw) save.basefilename=[%DocName]_[%Page]

    The equivalent command line syntax to set the when file exists option to 1(Auto pick a unique name to prevent collision):
    zvprtcfg Zan Image Printer(bw) save.filexistact=1
    or:
    zvprtcfg_win32 Zan Image Printer(bw) save.filexistact=1


    Return to top




    Settings in image.ini
    The table below lists all of the supported settings in image.ini.
    AppName KeyName Value Type Command Line Utility KeyName Description
    image fileformat DWORD or string image.fileformat
    image.format
    Output Image File Format:
    0 (BMP)
    1 (TIFF)
    2 (JPEG)
    3 (PNG)
    4 (PDF)
    5 (GIF)
    6 (JPEG 2000)

    Zan Image Printer also accepts an equivalent mnemonic string for the fileformat value as mnemonic strings are easier to remember:
    the following mnemonic strings are equivalent to 0 (BMP):
    bmp
    bitmap

    the following mnemonic strings are equivalent to 1 (TIFF):
    tif
    tiff

    the following mnemonic strings are equivalent to 2 (JPEG):
    jpg
    jpeg

    the mnemonic string "png" is equivalent to 3 (PNG)

    the mnemonic string "pdf" is equivalent to 4 (PDF)

    the mnemonic string "gif" is equivalent to 5 (gif)

    the following mnemonic strings are equivalent to 6 (JPEG 2000):
    jp2
    jpeg 2000
    image imagecolor DWORD or string image.imagecolor
    image.color
    Color:
    0 (Monochrome)
    1 or 256 (256)
    2 (Grayscale)
    3 or 24 (True Color)

    Zan Image Printer also accepts an equivalent mnemonic string for the imagecolor value:
    the following mnemonic strings are equivalent to 0 (Monochrome):
    bw
    monochrome

    the following mnemonic strings are equivalent to 2 (Grayscale):
    gray
    grayscale
    gray scale

    the following mnemonic strings are equivalent to 3 (True Color):
    color
    true color
    truecolor
    true
    24 bit
    24bit
    24-bit
    image compression DWORD or string image.compression Compression:
    0 (None)
    1 (CCITT G3)
    2 (CCITT G4)
    3 (Packbits)
    4 (Deflate/Zip)
    5 (JPEG)
    6 (LZW)
    20 (RLE8)

    Zan Image Printer also accepts an equivalent mnemonic string for the compression value:
    the mnemonic string "none" is converted to 0 (None)

    the following mnemonic strings are equivalent to 1 (CCITT G3):
    g3
    group 3
    group3

    the following mnemonic strings are equivalent to 2 (CCITT G4):
    g4
    group 4
    group4

    the following mnemonic strings are equivalent to 3 (Packbits):
    packbits
    packbit

    the following mnemonic strings are equivalent to 4 (Deflate/Zip):
    deflate
    zip

    the following mnemonic strings are equivalent to 5 (JPEG):
    jpeg
    jpg

    the mnemonic string "lzw" is converted to 6 (LZW)

    the mnemonic string "rle" is converted to 20 (RLE8)
    image pagetype DWORD or string image.pagetype
    image.mode
    File Mode (valid only for TIFF/PDF files):
    0 (One multi-page)
    1 (Serialized)
    2 (Append to existing file)

    Zan Image Printer also accepts an equivalent mnemonic string for the pagetype value:
    the following mnemonic strings are equivalent to 0 (One multi-page):
    one
    one multi page
    one multi-page
    multipage

    the following mnemonic strings are equivalent to 1 (Serialized):
    serialized
    singlepage

    the following mnemonic strings are equivalent to 2 (Append to existing file):
    appending
    append
    image pdftextlayer DWORD image.pdftextlayer Create PDF in image + searchable text format (valid only for PDF files):
    0 (no)
    1 (yes)
    image rowsperstrip DWORD or string image.rowsperstrip RowsPerStrip:
    0 (Default)
    1 (Each page as a single strip)
    2 (One row per strip)

    Zan Image Printer also accepts an equivalent mnemonic string for the rowsperstrip value:
    the mnemonic string "default" is equivalent to 0 (Default)

    the mnemonic string "single" is equivalent to 1 (Each page as a single strip):

    All other strings are equivalent to 2 (One row per strip)
    image qfactor DWORD image.qfactor Valid only for TIFF/JPEG/PDF files:
    between 0 (worst quality) and 100 (best quality).
    image color2bwthreshold DWORD image.color2bwthreshold Normally, you save to monochrome image files in Black & White mode using the printer's default halftoning algorithm. But in some cases, you can improve print quality by removing halftone screening artifacts thus making images appear more natural:

    First set Zan Image Printer into Color mode, and then save to a monochrome file.
    Doing this will cause Zan Image Printer to reduce the number of colors in the true color images to 2 (black & white) by a changeable Color Reduction Threshold.
    In the conversion, each pixel in the image is compared with this threshold,
    if it is higher than the threshold, the pixel is set to white. If it is less than the threshold, it is set to black.
    The threshold range is from 0 to 255 (default is 200).
    tiff-fax fillorder DWORD tiff-fax.fillorder Reverse bit order(FillOrder):
    1 (MSB-to-LSB)
    2 (LSB-to-MSB)
    tiff-fax adjustwidth DWORD tiff-fax.adjustwidth Automatically adjust the image width to create a faxable TIFF:
    0 (no)
    1 (yes)
    tiff-fax adjustheight DWORD tiff-fax.adjustheight Adjust the image height to create a faxable TIFF:
    0 (no)
    1 (yes)
    tiff-fax lineheight DWORD tiff-fax.lineheight Specify the height in lines to create a faxable TIFF
    tiff-fax t4options DWORD tiff-fax.t4options CCITT Group 3 T4Options:
    0 (1D MH)
    1 (2D MR)
    4 (1D MH, byte-aligned-EOLs)
    5 (2D MR, byte-aligned-EOLs)
    tiff-fax pagenumber DWORD tiff-fax.pagenumber Add PageNumber Tag:
    0 (no)
    1 (yes)
    tiff-fax datetime DWORD tiff-fax.datetime Add DateTime Tag:
    0 (no)
    1 (yes)
    tiff-fax ifdfirst DWORD tiff-fax.ifdfirst Place Image File Directory (IFD) in front of image data:
    0 (no)
    1 (yes)
    tiff-fax software string tiff-fax.software Software Tag:
    The name of the software that created the image.
    If this field is left blank, no software tag will be added.

    The command line syntax to set the fileformat to 2 (JPEG) is:
    zvprtcfg Zan Image Printer(bw) image.fileformat=2
    or:
    zvprtcfg_win32 Zan Image Printer(bw) image.fileformat=2

    The equivalent command line syntax to set the imagecolor to 3 (True Color):
    zvprtcfg Zan Image Printer(bw) image.imagecolor=3
    or:
    zvprtcfg_win32 Zan Image Printer(bw) image.imagecolor=3


    Return to top




    Settings in general.ini
    The table below lists all of the supported settings in general.ini.
    AppName KeyName Value Type Command Line Utility KeyName Description
    general hidestsdialog DWORD general.hidestsdialog Hide Status Dialog:
    0 (no)
    1 (yes)
    general hideui string general.hideui comma (,) delimited list of hideui options. Controls which property pages are hidden to the end user:
    save (hide the Save tab page)
    image (hide the Image tab page)
    settings (hide the Settings tab page)
    proginfo (hide the Program Information button on the About/Registration page)

    If this parameter is blank, all of the property pages are visible. Set hideui to following to hide the Save/Image/Settings tab pages and the Program Information button altogether:
    save, image, settings, proginfo
    general opacity DWORD general.opacity Status dialog opacity (30-100)
    30: partially transparent
    100: totally opaque
    general stsdialogpos DWORD general.stsdialogpos Status dialog position:
    0 (Top Left)
    1 (Top)
    2 (Top Right)
    3 (Left)
    4 (Center)
    5 (Right)
    6 (Bottom Left)
    7 (Bottom)
    8 (Bottom Right)
    x,y (custom position x, y in pixel coordinates relative to the top-left corner of the screen)
    general tipdlg DWORD general.tipdlg Show the tips dialog before each print job:
    0 (no)
    1 (yes)
    general sentinel DWORD general.sentinel Generate a sentinel file after printing finishes:
    0 (no)
    1 (yes)
    general sentinelfile string general.sentinelfile Sentinel filename (can include macros)
    general sentinel template is saved in a separate file sentineltemplate.txt string general.sentineltemplate Sentinel template
    general startdocfilename DWORD general.startdocfilename Enable/Disable controlling the output folder/file name via the StartDoc Win32 API:
    0 (disable)
    1 (enable)
    general zvprtsrvresident DWORD general.zvprtsrvresident Keep zvprtsrv.exe in memory (stay resident) until Windows is rebooted:
    0 (no)
    1 (yes)
    If 0, zvprtsrv.exe will exit after 25 seconds of inactivity.
    general pagerange string general.pagerange To specify the page range to print, enter the beginning and ending page numbers (for example, 1,2,5-10, 20-end) or choose a predefined option:
    First Page
    All Pages
    Odd Pages
    Even Pages

    To only print the first page of a document, set pagerange to 1:
    pagerange=1

    This function may not improve your printing speed. Only use it as a workaround when the printing application doesn't have native support for page range printing. The printing application will still process and generate all pages in the document and send them to Zan Image Printer, but Zan Image Printer will only output the specified pages. This is not optimal if you are printing a large document.

    If the printing application supports page range printing, it will only generate the required pages and send them to Zan Image Printer. This is much more efficient. Therefore, you should use native page range printing whenever possible.



    Return to top




    Settings in docuname.ini
    The table below lists all of the supported settings in docuname.ini.
    AppName KeyName Value Type Command Line Utility KeyName Description
    docuname removepath DWORD docuname.removepath Remove path:
    0 (no)
    1 (yes)
    docuname removewhitespace DWORD docuname.removewhitespace Remove whitespace:
    0 (no)
    1 (yes)
    docuname removestrings DWORD docuname.removestrings Remove unwanted strings from document name:
    0 (no)
    1 (yes)
    docuname unwantedstrings string docuname.unwantedstrings Unwanted strings that you want removed from the document name



    Return to top




    Settings in advimage.ini
    The table below lists all of the supported settings in advimage.ini.
    AppName KeyName Value Type Command Line Utility KeyName Description
    invert enable DWORD invert.enable Enable inverting:
    0 (no)
    1 (yes)
    trim enable DWORD trim.enable Enable border trimming:
    0 (no)
    1 (yes)
    trim left DWORD trim.left Enable left border trimming:
    0 (no)
    1 (yes)
    trim right DWORD trim.right Enable right border trimming:
    0 (no)
    1 (yes)
    trim top DWORD trim.top Enable top border trimming:
    0 (no)
    1 (yes)
    trim bottom DWORD trim.bottom Enable bottom border trimming:
    0 (no)
    1 (yes)
    crop enable DWORD crop.enable Enable cropping:
    0 (no)
    1 (yes)
    crop originx DWORD crop.originx Origin for the top left corner of the crop rectangle in pixels
    crop originy DWORD crop.originy Origin for the top left corner of the crop rectangle in pixels
    crop dimx DWORD crop.dimx Width of the crop rectangle in pixels
    crop dimy DWORD crop.dimy Height of the crop rectangle in pixels
    scale enable DWORD scaling.enable Enable scaling:
    0 (no)
    1 (yes)
    scale type DWORD scaling.type Scaling type:
    0: scale the image to the specified pixel size
    1: reduce the image by specifying the horizontal and vertical scaling factors
    scale horizontal numeric string scaling.horizontal If the scaling type is 0, this specifies the width in pixels of the desired image.
    If the scaling type is 1, this specifies the horizontal scaling factor (1.0-3.0)
    scale vertical numeric string scaling.vertical If the scaling type is 0, this specifies the height in pixels of the desired image.
    If the scaling type is 1, this specifies the vertical scaling factor (1.0-3.0)
    rotate enable DWORD rotate.enable Enable rotation:
    0 (no)
    1 (yes)
    rotate angle DWORD rotate.angle Sets the rotation angle (clockwise):
    0: no rotation
    90
    180
    270
    flip enable DWORD flip.enable Enable flipping:
    0 (no)
    1 (yes)
    flip type DWORD flip.type 0: mirror the image horizontally (left-right)
    1: mirror the image vertically (top-bottom)
    transpose enable DWORD transpose.enable Transpose the image:
    0 (no)
    1 (yes)



    Return to top




    Settings in app.ini
    The table below lists all of the supported settings in app.ini.
    AppName KeyName Value Type Command Line Utility KeyName Description
    application enableapp DWORD app.enableapp Run application after printing finishes:
    0 (no)
    1 (yes)
    application name string app.name User specified application(s)
    application parameters string app.parameters Command line parameters passed to the specified application
    application waitappcompletion DWORD app.waitappcompletion Wait for completion:
    0 (no)
    1 (yes)
    application apptimeoutinterval DWORD app.apptimeoutinterval Timeout intervals in seconds (0-3600)
    If the timeout interval is any value between 1 and 3600, the print job will return if the interval elapses, even if the launched application doesn't exit.
    If the Timeout is 0, the timeout interval never elapses so the print job will keep waiting until the launched application exits.
    application openfolder DWORD app.openfolder Open the save folder after printing finishes:
    0 (no)
    1 (yes)
    application rundefaultapp DWORD app.rundefaultapp Launch the default viewer for the generated image:
    0 (no)
    1 (yes)



    Return to top




    Settings in text.ini
    The table below lists all of the supported settings in text.ini.
    AppName KeyName Value Type Command Line Utility KeyName Description
    text enabletextout DWORD text.enabletextout
    text.enable
    Extract text to file:
    0 (no)
    1 (yes)
    text suppressimage DWORD text.suppressimage Suppress the creation of image files:
    0 (no)
    1 (yes)
    text file string text.file Output text file name (optional)
    text format DWORD text.format Format:
    0 (Plain text)
    1 (Formatted text)
    text appending DWORD text.appending Append text to existing file:
    0 (no)
    1 (yes)
    text prefixbom DWORD text.prefixbom Write Prefix Byte-Order Mask(BOM) to file:
    0 (no)
    1 (yes)
    text encoding DWORD text.encoding File encoding:
    0 (ANSI)
    1 (Unicode)
    2 (Unicode big endian)
    3 (UFT-8)
    text linebreaks DWORD text.linebreaks Insert line breaks:
    0 (Windows CR LF)
    1 (Unix LF)
    2 (None)
    text formfeed DWORD text.formfeed Formfeed after every page:
    0 (no)
    1 (yes)



    Return to top




    Settings in event.ini
    When the application wants printing to begin, it first calls the StartDoc function in the printer driver, which signals the beginning of a new document. The process ends when the application calls EndDoc. Each page itself is delimited by a call to StartPage to begin a page and EndPage to end the page.
    Zan Image Printer can be configured to send a notification to your application when these events occur during the printing process.
    All events must have unique name (e.g., "Zan Image Printer(bw) SignalPrintDone" or a GUID string such as "{66A568A9-EECE-4695-BE9F-0CF85135E702}"), so that their names won't conflict with any other Zan Image Printer or Windows application.
    The "Print files programmatically using the ShellExecute Print verb" section contains the VB, Delphi, C, VC.NET, VB.NET, and C# code samples on how to wait for the EndDoc event to make sure the print is finished before submitting the next print job.
    AppName KeyName Value Type Command Line Utility KeyName Description
    event enable DWORD event.enable Enable/disable event notification:
    0 (disable)
    1 (enable)
    event startdoc string event.startdoc Signals the start of printing. Leave blank to not receive a notification
    event enddoc string event.enddoc Signals the completion of the print job. Leave blank to not receive a notification
    event startpage string event.startpage Signals the start of a page. Leave blank to not receive a notification
    event endpage string event.endpage Signals when printing the page is complete. Leave blank to not receive a notification
    event cancelprint string event.cancelprint Signal this event in your application to tell Zan Image Printer to cancel current printing



    Return to top




    Settings in message.ini
    Zan Image Printer can be configured to send messages to your application when the following events occur during the printing process:
    StartDoc, EndDoc, StartPage, EndPage

    For a registered window message, the WPARAM value (or dwData in COPYDATASTRUCT structure of WM_COPYDATA message) tells you the printing process status:
    100: StartDoc
    101: EndDoc
    102: StartPage
    103: EndPage
    AppName KeyName Value Type Command Line Utility KeyName Description
    message enable DWORD message.enable Enable/disable message notification:
    0 (disable)
    1 (enable)
    message apptitle string message.apptitle Specifies the application window's title (or name) that the message will be sent to.
    If this parameter is blank, all window names match and the message (a.k.a. broadcast message) will be sent to every top-level window. Minimize the use of broadcast messages whenever possible, as these are very heavy on system resources and may crash certain applications.
    message msgtype DWORD message.msgtype Specifies the message type:
    0 (a registered window message)
    1 (WM_COPYDATA message)
    message msgname string message.msgname Registered window message name.
    message msgpost DWORD message.msgpost Specifies how to send the message to a window:
    0: SendMessage (waits for acknowledgement)
    1: PostMessage (without waiting)



    Return to top




    Settings in orientation.ini
    The table below lists all of the supported settings in orientation.ini.
    AppName KeyName Value Type Command Line Utility KeyName Description
    landscape enable DWORD landscape.autorotate Auto rotate landscape images:
    0 (no)
    1 (yes)
    landscape angle DWORD landscape.angle Sets the rotation angle (clockwise):
    90
    270



    Return to top




    Settings in email.ini
    The table below lists all of the supported settings in email.ini.
    AppName KeyName Value Type Command Line Utility KeyName Description
    email enable DWORD email.enable Enable Email:
    0 (no)
    1 (yes)
    email method DWORD email.method Method:
    0: Use DNS MX lookup to find Email server
    1: Send through MAPI compliant client
    2: Send through SMTP server
    email mapi DWORD email.mapi MAPI Method:
    0: Auto Detect. First check if Extended MAPI is supported on your computer. If it is, Zan Image Printer will use Extended MAPI to send the Email. If not, it will use Simple MAPI.
    1: Extended MAPI. Zan Image Printer will use Extended MAPI to send Emails. This prevents Outlook from displaying a security warning dialog when an Email is sent.
    2: Simple MAPI. Uses the Simple MAPI. A security warning dialog may be displayed when Emails are sent.
    email Email body is saved in a separate file emailbody.txt string email.body Email body. If the [%text] macro is specified, Zan Image Printer sends the extracted text as the Email body text rather than as an attachment.
    email port DWORD email.port Specifies the SMTP server port number to use
    email from string email.from Specifies Sender(From) Email address
    email to string email.to Destination Email address or list of addresses separated with semicolons (;). If the [%email] macro is specified as the Email address, Zan Image Printer will search the document being printed for an Email address, extract it from the text, and then automatically send the Email to that address.
    email cc string email.cc Carbon Copy Email address or a list of addresses separated with semicolons (;)
    email displayname string email.displayname The name that is sent to the Email recipient to tell them who it's from
    email servername string email.servername Specifies the SMTP server IP address or name
    email username string email.username SMTP authentication account (user) name
    email password string email.password Password for SMTP authentication or MAPI profile. The password is first encrypted then base64 encoded before saving.
    email profile string email.profile Specifies a profile that a MAPI compliant client uses to remember the Email accounts and settings
    email priority DWORD email.priority Indicate the priority/importance of the Email message:
    0: None
    1: Low
    2: Normal
    3: High
    email ssl DWORD email.ssl SMTP over SSL:
    0 (no)
    1 (yes)
    email auth DWORD email.auth Authentication Method:
    0: None
    1: CRAM MD5
    2: AUTH LOGIN
    3: AUTH PLAIN
    4: NTLM
    5: Auto Detect
    email encoding DWORD email.encoding Encoding for the Email message (headers and body):
    0: Arabic (Windows)
    1: Baltic (Windows)
    2: Central European (ISO)
    3: Central European (Windows)
    4: Chinese Simplified (GB2312)
    5: Chinese Simplified (HZ)
    6: Chinese Traditional (Big5)
    7: Cyrilic (KOI8-R)
    8: Cyrillic (Windows)
    9: Greek (Windows)
    10: Hebrew (Windows)
    11: Japanese (JIS)
    12: Korean
    13: Korean (EUC)
    14: Latin 9 (ISO)
    15: Thai (Windows)
    16: Turkish (Windows)
    17: Unicode (UTF-7)
    18: Unicode (UTF-8)
    19: Vietnamese (Windows)
    20: Turkish (Windows)
    21: Western European (ISO)
    22: Western European (Windows)
    email attach string email.attach Specify extra files to be sent as Email attachments in addition to the generated images. To attach multiple files, separate each file with semicolons ';'.
    email subject string email.subject The subject of the Email. You can insert save macro commands and file name macro commands to form the subject.
    email zip DWORD email.zip Create ZIP archive to send Email attachments:
    0 (no)
    1 (yes)
    email maxsize DWORD email.maxsize Maximum attachment size in MB (0-50)
    email deletefiles DWORD email.deletefiles Delete the original images after the Email is sent:
    0 (no)
    1 (yes)
    email sharedsession DWORD email.sharedsession Use the existing shared session:
    0 (no)
    1 (yes)



    Return to top




    Settings in watermark.ini
    The table below lists all of the supported settings in watermark.ini. In this table, N stands for a number from 1 to 10.
    AppName KeyName Value Type Command Line Utility KeyName Description
    watermark enable DWORD watermark.enable Enable Watermark function:
    0 (no)
    1 (yes)
    watermark batesnumber DWORD watermark.batesnumber Start bates numbering at: specifies the initial number used in the Bates Number macro command
    watermark_N enable DWORD watermark.watermark_N.enable Enable this watermark item:
    0 (no)
    1 (yes)
    watermark_N displayname string watermark.watermark_N.displayname The display name to identify the watermark item in the list.
    Note: Zan Image Printer ignores this watermark item if you leave the displayname empty
    watermark_N type DWORD watermark.watermark_N.type Watermark type:
    0: Text
    1: BMP
    watermark_N watermark string watermark.watermark_N.watermark If the type is BMP, this specifies the full path to the BMP file that you want to appear as watermark
    If the type is Text, this specifies the text string you want to appear as watermark. To use multi-line text, separate each line with the linefeed character \n.
    watermark_N drawtextformat string watermark.watermark_N.drawtextformat Alignment of multi-line text (separated by linefeed character '\n'), valid only for multiple line text watermark:
    DT_LEFT: Aligns text to the left
    DT_RIGHT: Aligns text to the right
    DT_CENTER: Centers text horizontally in the rectangle
    watermark_N pagerange string watermark.watermark_N.pagerange To specify the page range, enter the beginning and ending page numbers (for example, 1,2,5-10, 20-end) or specify a predefined option for applying the watermark:
    First Page
    All Pages
    Odd Pages
    Even Pages
    watermark_N font string watermark.watermark_N.font The font used for the text annotation
    watermark_N size DWORD watermark.watermark_N.size Font size in points for the text annotation
    watermark_N opacity DWORD watermark.watermark_N.opacity Specify a watermark opacity percentage (0-100).
    A value of 0 means the watermark appears behind the page content. A value of 100 means the watermark appears in front of the page content.
    watermark_N position DWORD watermark.watermark_N.position Use this to specify the position of the watermark:
    0 (Offset in pixels)
    1 (Offset in percentage)
    2 (Top Left)
    3 (Top)
    4 (Top Right)
    5 (Left)
    6 (Center)
    7 (Right)
    8 (Bottom Left)
    9 (Bottom)
    10 (Bottom Right)
    watermark_N style string watermark.watermark_N.style A list of font styles or BMP tiling options separated with commas (,)
    Font style:
    bold
    italic
    underline
    strikeout
    BMP tiling style:
    tile: the BMP graphic is repeated both horizontally and vertically
    tile-x: the BMP graphic is repeated horizontally
    tile-y: the BMP graphic is repeated vertically
    stretchedtowidth: stretched to fit the page width
    stretchedtoheight: stretched to fit the page height
    stretchedtofit: stretch the BMP graphic across the entire page
    writethru: don't use transparent color
    watermark_N color string watermark.watermark_N.color Text color or BMP watermark transparent color
    auto: Auto detect transparent color
    r g b: enter colors as RGB values separated by spaces like: 255 12 3
    watermark_N offsetx DWORD watermark.watermark_N.offsetx Horizontal offset (in pixels or percentage) of the watermark relative to the left side of the image
    watermark_N offsety DWORD watermark.watermark_N.offsety Vertical offset (in pixels or percentage) of the watermark relative to the top side of the image
    watermark_N angle DWORD watermark.watermark_N.angle Sets the rotation angle (counter-clockwise, 0-360)

    The command line syntax to add a watermark with the text "hello world" is as follows:
    zvprtcfg zan image printer(bw) watermark.enable=1
    zvprtcfg zan image printer(bw) watermark.watermark_1.enable=1
    zvprtcfg zan image printer(bw) watermark.watermark_1.displayname=watermark1
    zvprtcfg zan image printer(bw) watermark.watermark_1.type=0
    zvprtcfg zan image printer(bw) watermark.watermark_1.watermark=hello world
    zvprtcfg zan image printer(bw) watermark.watermark_1.size=24
    zvprtcfg zan image printer(bw) watermark.watermark_1.position=4



    Settings in printerredirection.ini
    The table below lists all of the supported settings in printerredirection.ini. In this table, N stands for a number from 1 to 10.
    AppName KeyName Value Type Command Line Utility KeyName Description
    printerredirection enable DWORD printerredirection.enable Enable printer redirection:
    0 (no)
    1 (yes)
    printerredirection copies DWORD printerredirection.copies Set the number of copies to print, from 1 to 50
    printerredirection fit DWORD printerredirection.fit Fit to page:
    0 (no)
    1 (yes)
    printer_N enable DWORD printerredirection.printer_N.enable Enable redirection for this printer
    printer_N name string printerredirection.printer_N.name Printer name
    printer_N tray string printerredirection.printer_N.tray Printer tray selector, in the format of first page tray name;first page range;other page tray name. For example:
    letterhead;First Page;letter



    Return to top




    Settings in ftp.ini
    The table below lists all of the supported settings in ftp.ini.
    AppName KeyName Value Type Command Line Utility KeyName Description
    ftp url string ftp.url The name of the FTP server/host (e.g., ftp.mycompany.com or an IP address such as 192.168.10.2) and optionally the name of the upload folder (can include the save macro commands) where the files should be placed. Example: ftp.mycompany.com/docs/[%Date]
    You do not need to include the ftp:// prefix, you can type \ instead of / in any URL and Zan Image Printer will substitute /. If the upload folder is left blank, the files will be stored in the default home folder for the ftp user.
    ftp username string ftp.username FTP user (account) name
    ftp password string ftp.password Password associated with the user name. The password is first encrypted then base64 encoded before saving
    ftp enable DWORD ftp.enable Determines whether you want to enable the FTP feature
    ftp passive DWORD ftp.passive Passive FTP (also referred to as PASV FTP) is a more secure form of data transfer in which the flow of data is initiated by the FTP client rather than by the FTP server. Check this option if your computer is behind a firewall. We recommend that you use passive (PASV) mode for most transfers.
    ftp port DWORD ftp.port Specifies the port that should be used to connect to the FTP server. The default is 21.



    Return to top




    change Paper Size and DPI
    In the past, we have observed the following problems:
    Some printing applications will include printer settings (DPI resolution, paper size, etc.) in the document itself and will ignore the current settings in Zan Image Printer; Some applications will always use the highest available DPI resolution for the selected printer, regardless of what is configured in Zan Image Printer; Some printing applications have their own printer settings function ("Page Setup", for example) and will ignore the settings you set in Zan Image Printer.
    These issues are all caused by the printing application and not by Zan Image Printer.
    One solution to these issues is to restrict the supported DPI/paper size to those that will actually be used by your printing application. You can then print to a printer with only your desired paper size/DPI available. For example, if you need to print at 300 x 300 DPI on Letter paper size, during the setup, you can configure the selected printer to only support 300 x 300 DPI and Letter paper size. In this way, the printing application is forced (restricted) to use 300 x 300 DPI and Letter paper size, i.e., the printing application will not be able to switch from 300 x 300 DPI to 600 x 600 DPI and you will no longer have to worry about the printing application overriding or ignoring Zan Image Printer settings.

    After Zan Image Printer is installed, you can execute the gpd command provided by the command line utilities zvprtcfg and zvprtcfg_win32 to change the supported DPI and paper size settings.


    Return to top




    Command line utilities zvprtcfg and zvprtcfg_win32
    Although you can call the GetPrivateProfileString, GetPrivateProfileInt and WritePrivateProfileString Win32 APIs to directly access the ini setting files to programmatically control all of the Zan Image Printer specific settings, if you want even easier programmatic control, you can choose to call the command line utilities in your application or script.

    zvprtcfg is a console mode application, zvprtcfg_win32 is a Win 32 application, but both of them have exactly the same command line syntax and same functionality. The only difference is that zvprtcfg_win32 produces no output and executes the command silently without any windows appearing. If you want to programmatically control Zan Image Printer in your own application seamlessly, use zvprtcfg_win32. For automatic scripting, use zvprtcfg instead.

    Command line parameters and explanations:
    C:\Program Files\zvprt50>zvprtcfg
    
    Syntax: zvprtcfg  printer  keyword=value [-silent]
    	Or: zvprtcfg  -help
    	Or: zvprtcfg  -examples
    	Or: zvprtcfg   printer -show
    	Or: zvprtcfg   printer -setdefault
    	Or: zvprtcfg  -listprinters
    Where:
    printer: printer name
    silent: do not print out any message on screen
    show: show the current parameters(keyword-value pairs) for the specified printer
    examples: show usage examples
    listprinters: show all installed printer instances
    setdefault: set the specified printer as the default printer
    
    All options on the command line must use keywords, the command line utilities can only handle one keyword-value argument per invocation.
    All the keywords supported by the command line utilities can be found in the fourth column "Command Line Utility KeyName" in the above ini file tables. For example, if you want to change the save folder for Zan Image Printer, from the save.ini table, you find the save.folder in the column "Command Line Utility KeyName", the command line to set the folder to c:\temp will therefore be (assume printer name is Zan Image Printer(bw)):

    zvprtcfg Zan Image Printer(bw) save.folder=c:\temp
    or:
    zvprtcfg_win32 Zan Image Printer(bw) save.folder=c:\temp

    To run zvprtcfg_win32 programmatically, call the CreateProcess Win32 API with the corresponding command line parameters. The following code samples illustrate how to set the save folder to c:\temp:

    VB code sample:
    Option Explicit
    Private Type PROCESS_INFORMATION
             hProcess As Long
             hThread As Long
             dwProcessId As Long
             dwThreadId As Long
    End Type
    
    Private Type STARTUPINFO
             cb As Long
             lpReserved As String
             lpDesktop As String
             lpTitle As String
             dwX As Long
             dwY As Long
             dwXSize As Long
             dwYSize As Long
             dwXCountChars As Long
             dwYCountChars As Long
             dwFillAttribute As Long
             dwFlags As Long
             wShowWindow As Integer
             cbReserved2 As Integer
             lpReserved2 As Long
             hStdInput As Long
             hStdOutput As Long
             hStdError As Long
    End Type
    
    Private Declare Function CreateProcess Lib "kernel32" _
             Alias "CreateProcessA" _
             (ByVal lpApplicationName As String, _
             ByVal lpCommandLine As String, _
             lpProcessAttributes As Any, _
             lpThreadAttributes As Any, _
             ByVal bInheritHandles As Long, _
             ByVal dwCreationFlags As Long, _
             lpEnvironment As Any, _
             ByVal lpCurrentDriectory As String, _
             lpStartupInfo As STARTUPINFO, _
             lpProcessInformation As PROCESS_INFORMATION) As Long
    
    Private Const INFINITE = &HFFFF
    Public Declare Function WaitForSingleObject Lib "kernel32" _
    (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
    
    Private Declare Function CloseHandle Lib "kernel32" _
             (ByVal hObject As Long) As Long
    
    Private Declare Function SHGetFolderPath Lib "shell32" _
    Alias "SHGetFolderPathA" _
    (ByVal hwndOwner As Long, ByVal nFolder As Long, _
    ByVal hToken As Long, ByVal dwFlags As Long, _
    ByVal pszPath As String) As Long
    
    
    Private Const HKEY_LOCAL_MACHINE = &H80000002
    'Registry action types.
    Private Const ERROR_SUCCESS = 0
    Private Const STANDARD_RIGHTS_READ As Long = &H20000
    Private Const KEY_QUERY_VALUE As Long = &H1
    Private Const KEY_ENUMERATE_SUB_KEYS As Long = &H8
    Private Const KEY_NOTIFY As Long = &H10
    Private Const SYNCHRONIZE As Long = &H100000
    Private Const KEY_READ As Long = ((STANDARD_RIGHTS_READ Or _
                                       KEY_QUERY_VALUE Or _
                                       KEY_ENUMERATE_SUB_KEYS Or _
                                       KEY_NOTIFY) And _
                                       (Not SYNCHRONIZE))
    
    Private Declare Function RegCloseKey Lib "advapi32.dll" _
    (ByVal hKey As Long) As Long
    
    Private Declare Function RegOpenKeyEx Lib "advapi32.dll" _
       Alias "RegOpenKeyExA" _
      (ByVal hKey As Long, _
       ByVal lpSubKey As String, _
       ByVal ulOptions As Long, _
       ByVal samDesired As Long, _
       phkResult As Long) As Long
      
    
    Private Declare Function RegQueryValueEx Lib "advapi32.dll" _
    Alias "RegQueryValueExA" (ByVal hKey As Long, _
    ByVal lpValueName As String, ByVal lpReserved As Long, _
    lpType As Long, lpData As Any, lpcbData As Long) As Long
     
    
    'Used CSIDL values
    Private Const CSIDL_APPDATA As Long = &H1A
    Private Const CSIDL_PROGRAM_FILES  As Long = &H26
    Private Const CSIDL_COMMON_APPDATA As Long = &H23
    
    Private Const SHGFP_TYPE_CURRENT = 0
    Private Const S_OK As Long = 0
    Const NORMAL_PRIORITY_CLASS = &H20
    
    
    Private Const MAX_PATH = 260
    
    'Determines whether the given path refers to an existing
    'directory
    Function DirExists(ByVal DName As String) As Boolean
    Dim sDummy As String
    On Error Resume Next
    
    If Right(DName, 1) <> "\" Then DName = DName & "\"
    sDummy = Dir$(DName & "*.*", vbDirectory)
    DirExists = Not (sDummy = "")
    End Function
    
    
    'Searches a path for a file name
    Function GetFilePath(FileName As String) As String
        Dim i As Long
        For i = Len(FileName) To 1 Step -1
            Select Case Mid$(FileName, i, 1)
                Case ":"
                    GetFilePath = Left$(FileName, i)
                    Exit For
                Case "\"
                    GetFilePath = Left$(FileName, i - 1)
                    Exit For
            End Select
        Next
    End Function
    
    
    'Determines Zan Image Printer installation directory
    Private Function GetZanInstallDir() As String
    
    Dim sPath As String
    Dim szTmp As String * MAX_PATH
    Dim lResult As Long
    Dim hKey, dwSize As Long
    
    
    dwSize = MAX_PATH
    
    'first check to see if the uninstall registry entry exists
    If RegOpenKeyEx(HKEY_LOCAL_MACHINE, _
    "\Software\Microsoft\Windows\CurrentVersion\Uninstall\zvprt50" _
          , 0&, KEY_READ, hKey) = ERROR_SUCCESS Then
          If RegQueryValueEx(hKey, "UninstallString", _
          0&, 0&, ByVal szTmp, dwSize) = ERROR_SUCCESS Then
          
          sPath = Left$(szTmp, _
                InStr(szTmp, vbNullChar) - 1)
    
          sPath = GetFilePath(sPath)
          
          If DirExists(sPath) Then
          GetZanInstallDir = sPath
          Exit Function
          End If
          
          End If
          
    End If
         
    'fallback to the \Program Files\zvprt50 folder:
    lResult = SHGetFolderPath(0, _
                       CSIDL_PROGRAM_FILES, _
                       0, _
                       SHGFP_TYPE_CURRENT, _
                       szTmp)
                       
    sPath = Left$(szTmp, _
                InStr(szTmp, vbNullChar) - 1)
                
    If Right$(sPath, 1) <> "\" Then
        sPath = sPath & "\"
     End If
     sPath = sPath & "zvprt50"
     GetZanInstallDir = sPath
    End Function
    
    
    'run application with given parameters
    Private Sub util_CreateProcess(command_line As String)
            Dim pInfo As PROCESS_INFORMATION
            Dim sInfo As STARTUPINFO
            Dim sNull As String
            Dim lSuccess As Long
            Dim lRetValue As Long
    
            sInfo.cb = Len(sInfo)
            lSuccess = CreateProcess(sNull, _
                                     command_line, _
                                     ByVal 0&, _
                                     ByVal 0&, _
                                     1&, _
                                     NORMAL_PRIORITY_CLASS, _
                                     ByVal 0&, _
                                     sNull, _
                                     sInfo, _
                                     pInfo)
    
             'lRetValue = WaitForSingleObject(pInfo.hProcess, INFINITE)
    
             lRetValue = CloseHandle(pInfo.hThread)
             lRetValue = CloseHandle(pInfo.hProcess)
    End Sub
    
    
    Public Sub Main()
    Dim cmdline As String
    
     cmdline = GetZanInstallDir()
     If Right$(cmdline, 1) <> "\" Then
        cmdline = cmdline & "\"
     End If
    
     cmdline = cmdline & _
     "zvprtcfg_win32 Zan Image Printer(bw) save.folder=c:\temp"
     
     util_CreateProcess cmdline
    End Sub
    


    Delphi code sample:
    unit zanprinter;
    
    interface
    uses
    Windows, Messages, SysUtils, ShlObj,
    ShellAPI, SHFolder, Registry;
    
    procedure util_CreateProcess(ProgramName:String);
    procedure GetZanInstallDir(var APath: String);
    procedure zvprtvfg_test();
    implementation
    
    //run application with given parameters
    procedure util_CreateProcess(ProgramName:String);
    var
      StartInfo : TStartupInfo;
      ProcInfo : TProcessInformation;
      CreateOK : Boolean;
    begin
      FillChar(StartInfo,SizeOf(TStartupInfo),#0);
      FillChar(ProcInfo,SizeOf(TProcessInformation),#0);
      StartInfo.cb := SizeOf(TStartupInfo);
      CreateOK := CreateProcess(nil,PChar(ProgramName),nil,nil,False,
                  CREATE_NEW_PROCESS_GROUP+NORMAL_PRIORITY_CLASS,
                  nil, nil, StartInfo, ProcInfo);
      if CreateOK then
        begin
        //WaitForSingleObject(ProcInfo.hProcess, INFINITE);
        CloseHandle(ProcInfo.hProcess);
        CloseHandle(ProcInfo.hThread);
        end
    end;
    
    
    //Determines Zan Image Printer installation directory
    procedure GetZanInstallDir(var APath: String);
    var
      hkeyStartup: HKEY;
      dwSize: DWORD;
    begin
      dwSize := MAX_PATH;
      SetLength(APath, MAX_PATH);
    
      //first check to see if the uninstall registry entry exists
      if RegOpenKeyEx(HKEY_LOCAL_MACHINE,
       '\Software\Microsoft\Windows\CurrentVersion\Uninstall\zvprt50',
       0,
       KEY_READ,
       hkeyStartup) = ERROR_SUCCESS then
       begin
    
       if RegQueryValueEx(hkeyStartup,
                         'UninstallString', nil, nil,
                          PBYTE(Pchar(APath)),
                          @dwSize) = ERROR_SUCCESS then
       begin
          APath := String (PChar(APath));
          APath := ExtractFilePath(APath);
       end;
    
       //Close the Key, we won't be needing it anymore
       RegCloseKey(hkeyStartup);
    
       if DirectoryExists(APath) then Exit;
      end;
    
      //fallback to the \Program Files\zvprt50 folder:
      SHGetFolderPath(0, CSIDL_PROGRAM_FILES, 0, 0,
                      PChar(APath));
    
      APath := String (PChar (APath));
      if (APath[Length(APath)] <> '\')
      then APath := APath + '\';
    
      APath := APath + 'zvprt50';
    end;
    
    
    
    procedure zvprtvfg_test();
    var
    szCmdLine: String;
    begin
    GetZanInstallDir(szCmdLine);
    
    if (szCmdLine[Length(szCmdLine)] <> '\')
    then szCmdLine := szCmdLine + '\';
    
    szCmdLine := szCmdLine +
    'zvprtcfg_win32 Zan Image Printer(bw) save.folder=c:\temp';
    
    util_CreateProcess(szCmdLine);
    end;
    
    
    end.
    

    C code sample:
    #include <windows.h>
    #include <winspool.h>
    #include <shlobj.h>
    #include <shlwapi.h>
    #include <shellapi.h>
    
    #pragma comment(lib, "shlwapi.lib")
    
    
    //Determines whether the given path refers to 
    //an existing directory
    BOOL IsFolderExists(char *lpDirectoryName)
    {
    	if(0 == strlen(lpDirectoryName))
    	{
    		return FALSE;
    	}
    
    	DWORD dwFileAttr = GetFileAttributes(lpDirectoryName);
    
    	if((dwFileAttr != 0xFFFFFFFF) &&
    		(dwFileAttr & FILE_ATTRIBUTE_DIRECTORY))
    	{
    		return TRUE;
    	}
    	else
    	{
    		return FALSE;
    	}
    }
    
    
    
    //Determines Zan Image Printer installation directory
    void GetZanInstallDir(char *installfolder)
    {
    	HKEY hkeyStartup;
    
    	//first check to see if the uninstall registry entry exists
    	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
    		"\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\zvprt50",
    		0,          
    		KEY_READ,  
    		&hkeyStartup) == ERROR_SUCCESS)
    	{
    		DWORD dwSize = MAX_PATH;
    
    		if(RegQueryValueEx(hkeyStartup, 
    			"UninstallString", 
    			NULL,
    			NULL,
    			(LPBYTE)installfolder,
    			&dwSize) == ERROR_SUCCESS)
    		{
    			PathRemoveFileSpec(installfolder);
    			PathAddBackslash(installfolder);
    		}
    
    		/*Close the Key, we won't be needing it anymore*/
    		RegCloseKey(hkeyStartup);
    
    		if(IsFolderExists(installfolder))
    		{
    			return;
    		}
    	}
    
    	//fallback to the \Program Files\zvprt50 folder:
    	SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, 0, installfolder);
    	PathAddBackslash(installfolder);
    
    	strcat(installfolder,"zvprt50");
    }
    
    
    BOOL util_CreateProcess(char* command_line)
    {
    	PROCESS_INFORMATION pInfo;
    	STARTUPINFO sInfo;
    
    	ZeroMemory(&sInfo, sizeof(STARTUPINFO));
    	sInfo.cb = sizeof(STARTUPINFO);
    	sInfo.lpReserved = NULL;
    	sInfo.lpReserved2 = NULL;
    	sInfo.cbReserved2 = 0;
    	sInfo.lpDesktop = NULL;
    	sInfo.lpTitle = NULL;
    	sInfo.dwFlags = 0;
    	sInfo.dwX = 0;
    	sInfo.dwY = 0;
    	sInfo.dwFillAttribute = 0;
    	sInfo.wShowWindow = SW_SHOW;
    
    	BOOL bret = CreateProcess(NULL, command_line, NULL, NULL, 
    		FALSE, 0, NULL, NULL, &sInfo, &pInfo);
    
    	//WaitForSingleObject(pInfo.hProcess, INFINITE);
    
    	CloseHandle(pInfo.hProcess);
    	CloseHandle(pInfo.hThread);
    
    	return bret;
    }
    
    
    int main(int argc, char* argv[])
    {
    	char szCmdLine[MAX_PATH];
    
    	GetZanInstallDir(szCmdLine);
    	PathAddBackslash(szCmdLine);
    
    	strcat(szCmdLine,"zvprtcfg_win32 Zan Image Printer(bw) save.folder=c:\\temp");
    
    	util_CreateProcess(szCmdLine);
    
    	return 0;
    }
    

    VC.NET code sample:
    using namespace System;
    using namespace Microsoft::Win32;
    using namespace System::IO;
    using namespace System::Diagnostics;
    
    
    //Determines Zan Image Printer installation directory
    String^ GetZanInstallDir(void)
    {
    	String^ installfolder = String::Empty;
    	RegistryKey ^ rkTest;
    
    	//first check to see if the uninstall registry entry exists
    	rkTest = Registry::LocalMachine->OpenSubKey(
    		L"\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\zvprt50");
    	if(rkTest)
    	{
    		installfolder = rkTest->GetValue(L"UninstallString")->ToString();
    		rkTest->Close();
    
    		if(installfolder->Length)
    		{
    			installfolder = Path::GetDirectoryName(installfolder);
    
    			DirectoryInfo^ installdir1=gcnew DirectoryInfo(installfolder);
    			if(installdir1->Exists)
    			{
    				return installfolder;
    			}
    		}
    	}
    
    	//fallback to the \Program Files\zvprt50 folder:
    	installfolder = Environment::GetFolderPath
    		(Environment::SpecialFolder::ProgramFiles);
    
    	if(!installfolder->EndsWith(L"\\")) 
    		installfolder = String::Concat(installfolder, L"\\");
    
    	installfolder=String::Concat(installfolder, L"zvprt50");
    
    	return installfolder;
    }
    
    
    
    int main(array ^args)
    {
    	String^ apppath;
    	Process^  p;
    
    	apppath = GetZanInstallDir();
    
    	if(!apppath->EndsWith(L"\\")) 
    		apppath = String::Concat(apppath, L"\\");
    
    	apppath=String::Concat(apppath, L"zvprtcfg_win32");
    
    	p = Process::Start(apppath, 
    		L" Zan Image Printer(bw) save.folder=c:\\temp");
    
    	//p->WaitForExit();
    
    
    	return 0;
    }
    

    VB.NET code sample:
    Imports System
    Imports Microsoft.Win32
    Imports System.IO
    Imports System.Diagnostics
    
    Module Module1
        'Determines Zan Image Printer installation directory
        Function GetZanInstallDir() As String
            Dim installfolder As String
            Dim rkTest As RegistryKey
    
            'first check to see if the uninstall registry entry exists
            rkTest = Registry.LocalMachine.OpenSubKey _
     ("SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\zvprt50")
    
            If Not (rkTest Is Nothing) Then
                installfolder = rkTest.GetValue _
                  ("UninstallString").ToString()
                rkTest.Close()
                If (installfolder.Length > 0) Then
                    installfolder = Path.GetDirectoryName(installfolder)
                    Dim installdir1 As DirectoryInfo = _
                       New DirectoryInfo(installfolder)
    
                    If installdir1.Exists Then
                        Return installfolder
                    End If
                End If
            End If
            'fallback to the \Program Files\zvprt50 folder:
            installfolder = Environment.GetFolderPath _
    (Environment.SpecialFolder.ProgramFiles)
    
            If Not installfolder.EndsWith("\") Then
                installfolder = String.Concat(installfolder, "\")
            End If
    
            installfolder = String.Concat(installfolder, "zvprt50")
            Return installfolder
        End Function
    
    
        Sub Main()
            Dim apppath As String
            Dim p As Process
    
            apppath = GetZanInstallDir()
    
            If Not apppath.EndsWith("\") Then
                apppath = String.Concat(apppath, "\")
            End If
    
            apppath = String.Concat(apppath, "zvprtcfg_win32")
            p = Process.Start(apppath, _
           " Zan Image Printer(bw) save.folder=c:\temp")
    
            'p.WaitForExit()
    
        End Sub
    End Module
    
    

    C# code sample:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Diagnostics;
    using Microsoft.Win32;
    using System.IO;
    
    
    namespace callzvprtcfg_csharp
    {
        class Program
        {
            //Determines Zan Image Printer installation directory
            static string GetZanInstallDir()
            {
                string installfolder = string.Empty;
                RegistryKey rkTest;
    
                //first check to see if the uninstall registry entry exists
                rkTest = Registry.LocalMachine.OpenSubKey(
                "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\zvprt50");
    
                if (rkTest != null)
                {
                    installfolder = rkTest.GetValue("UninstallString").ToString();
                    rkTest.Close();
    
                    if (installfolder.Length > 0)
                    {
                        installfolder = Path.GetDirectoryName(installfolder);
    
                        DirectoryInfo installdir1 = new DirectoryInfo(installfolder);
                        if (installdir1.Exists)
                        {
                            return installfolder;
                        }
                    }
                }
    
                //fallback to the \Program Files\zvprt50 folder:
                installfolder = Environment.GetFolderPath
                    (Environment.SpecialFolder.ProgramFiles);
    
                if (!installfolder.EndsWith("\\"))
                    installfolder = string.Concat(installfolder, "\\");
    
                installfolder = string.Concat(installfolder, "zvprt50");
    
                return installfolder;
            }
    
            static void Main(string[] args)
            {
                string apppath;
                Process p;
    
                apppath = GetZanInstallDir();
    
                if (!apppath.EndsWith("\\"))
                    apppath = String.Concat(apppath, "\\");
    
                apppath = String.Concat(apppath, "zvprtcfg_win32");
    
                p = Process.Start(apppath,
                    " Zan Image Printer(bw) save.folder=c:\\temp");
    
                //p.WaitForExit();
            }
        }
    }
    


    The command line utilities also allow you to change the standard printer settings (paper size, DPI resolution/print quality, orientation, color, and so on) in the associated printer GPD (Generic Printer Description) file. You can open the associated GPD file by double clicking the Printer GPD File item in the Program Information dialog.

    Zan Image Printer is Microsoft Unidrv (Universal printer driver / Unidriver) based. Unidrv allows the creation of a printer-specific minidriver in the form of a GPD file. A GPD file is a text-based file that contains information about the printer features (supported paper size, dpi, orientation, color, etc.) that Unidrv will present in the user interface to allow the user to configure the printer.

    You can execute the gpd command provided by the command line utilities zvprtcfg and zvprtcfg_win32 to manipulate the printer GPD file.
    Note that you cannot have a vendor defined paper size (A0, A1, B0(ISO), B0(JIS), B1(ISO), B1(JIS), B2(ISO), B2(JIS), B3(ISO), B3(JIS), B4(JIS), B5(JIS), B6(ISO), F Sheet, Square, etc.) as the only paper size in the GPD file. You need to specify at least one standard paper size such as Letter, A4, Legal, etc. You also need to set the standard paper size as the default.
    Command Line Utility KeyName Value Type Description
    gpd.papersize string Paper size or a list of paper sizes with commas (,)
    All: all paper sizes
    9X11
    10X11
    10X14
    11X17
    12X11
    15X11
    A0
    A1
    A2
    A3
    A3_EXTRA
    A3_ROTATED
    A4
    A4_EXTRA
    A4_PLUS
    A4_ROTATED
    A5
    A5_EXTRA
    A5_ROTATED
    A6
    A6_ROTATED
    B0(ISO)
    B0(JIS)
    B1(ISO)
    B1(JIS)
    B2(ISO)
    B2(JIS)
    B3(ISO)
    B3(JIS)
    B4
    B4(JIS)
    B4_JIS_ROTATED
    B5(ISO)
    B5(JIS)
    B5_JIS_ROTATED
    B6(ISO)
    B6_JIS
    B6_JIS_ROTATED
    CSHEET
    DSHEET
    ESHEET
    ENV_9
    ENV_10
    ENV_11
    ENV_12
    ENV_14
    ENV_DL
    ENV_C3
    ENV_C4
    ENV_C5
    ENV_C6
    ENV_C65
    ENV_B4
    ENV_B5
    ENV_B6
    ENV_ITALY
    ENV_MONARCH
    ENV_PERSONAL
    ENV_INVITE
    EXECUTIVE
    F sheet
    FOLIO
    FANFOLD_STD_GERMAN
    FANFOLD_LGL_GERMAN
    JAPANESE_POSTCARD
    DBL_JAPANESE_POSTCARD
    LEDGER
    LEGAL
    LEGAL_EXTRA
    LETTER
    LETTER_PLUS
    LETTER_EXTRA
    NOTE
    QUARTO
    Square(64x64)
    Square(128x128)
    Square(256x256)
    Square(512x512)
    A_PLUS
    B_PLUS
    STATEMENT
    TABLOID
    TABLOID_EXTRA
    FANFOLD_INVITE
    FANFOLD_US
    CUSTOMSIZE

    Default: all paper sizes except B5(ISO), EXECUTIVE, and FANFOLD_INVITE
    You can set the default paper size by following the list of allowable paper sizes with a colon (:) and then the default paper size.
    gpd.dpi string DPI resolution or a list of DPI resolutions with commas (,).
    default: 50 x 50, 60 x 60, 75 x 75, 100 x 100, 120 x 120, 150 x 150, 200 x 100, 200 x 200, 240 x 240, 300 x 300, 360 x 360, 400 x 400, 600 x 600
    group1: 50 x 50, 60 x 60, 75 x 75, 100 x 100, 120 x 120, 150 x 150, 200 x 100, 200 x 200, 240 x 240, 300 x 300, 360 x 360, 400 x 400, 600 x 600, 720 x 720, 1200 x 1200, 2400 x 2400
    group2: 204 x 98, 204 x 196
    group3: 72 x 72, 96 x 96, 144 x 144, 288 x 144, 288 x 288
    group4: 240 x 144, 240 x 288
    group5: 240 x 216
    group6: 800 x 600, 1200 x 600, 2400 x 600
    group7: 203 x 305
    group8: 600 x 540
    group9: 254 x 254
    group10: 250 x 250, 500 x 500
    To specify custom DPIs, enter DPI values separated by commas (e.g., 80, 500, 200 x 100).
    If the horizontal and vertical resolutions are the same, enter a single number to specify the resolution (e.g., 300 x 300 can be abbreviated to 300).
    gpd.orientation string Orientation:
    Portrait
    Landscape
    gpd.color string Color mode:
    bw
    color

    Some gpd command usage examples:
    Restrict the supported paper size to Letter and A4, and set the default paper size to Letter:
    zvprtcfg "Zan Image Printer(bw)" gpd.papersize=Letter,A4:Letter

    Use default paper size list, and set the default paper size to A4:
    zvprtcfg "Zan Image Printer(bw)" gpd.papersize=default:A4

    Restrict the supported DPI to 200 x 200 and 200 x 100, and set the default DPI to 200 x 200:
    zvprtcfg Zan Image Printer(bw) gpd.dpi=200,200x100:200

    Use all group 1 DPI resolutions, and set the default DPI to 300 x 300:
    zvprtcfg Zan Image Printer(bw) gpd.dpi=group1:300x300



    Return to top



    User interface customization, private labeling
    The dialog box templates and other resources (bitmap, string table, etc.) used by Zan Image Printer are stored in zvprtres.dll. By modifying this resource dll, developers can customize the appearance of Zan Image Printer.

    Developers can customize the user interface by following the steps below:

    1.  Open the Printers folder (Start > Printers and Faxes), right click on the printer, and click Properties.

    2.  On the General tab, change the text in the Location/Comment box to your desired text.

    3.  Download a free resource editor called Resource Hacker. It is only a few hundred kilobytes and does not require installation.
    Start Resource Hacker by running the ResHacker.exe file, use the File menu to open zvprtres.dll.
    Select the resources you want to edit from the tree control on the left listing, and edit/view all the text, icons, dialogs and all of the other resources on the right panel. When you are done, Resource Hacker should ask if you want to compile this script (save your changes), answer yes. After you are finished, click Save from the File menu and quit Resource Hacker.

    If you have installed Microsoft Visual Studio, you can also open zvprtres.dll as a resource file and then edit it:
    From Visual Studio, choose File/Open, select zvprtres.dll, choose "Open as: Resources" before clicking Open.



    Extract text from PDF files
    Zan Image Printer is able to extract text from most documents, but the extracted text from PDF documents will usually be just long strings of '?' instead of the textual data. This may be caused by the following possible reasons:
  • Zan Image Printer receives the glyphs instead of character strings from the PDF viewer during printing.
  • The PDF viewer will render the PDF by itself.

  • One possible solution is using pdftotext from the xpdf package to directly extract the text from your PDF documents. pdftotext is a command line program that can convert entire PDF documents or individual pages to plain text while maintaining layout. The extracted text can be converted to a wide choice of standard encodings including UTF-8 and ASCII.
    To install pdftotext:
    1. Make a folder on your computer, for example c:\xpdf
    2. Go to http://www.foolabs.com/xpdf/download.html, scroll down to "Precompiled binaries" and you will see a paragraph starting with "x86, DOS/Win32", click the Win32 download link in that paragraph and download the file to c:\xpdf, then unzip all the files.

    Examples (read the accompanying pdftotext.txt file for more usage information):
    pdftotext filename.pdf, this usage produces a text file (filename.txt) with the same name as the input file.
    pdftotext filename.pdf -layout layout.txt, this usage produces a text file layout.txt and maintains original physical layout.
    pdftotext filename.pdf -enc UTF-8, this usage produces a text file in UTF-8 encoding format.



    Generate a sentinel file after printing finishes
    The "Generate a sentinel file after printing finishes" option on the Settings->General tab specifies whether or not a sentinel file should be generated. The sentinel file is deleted at the start of each print session, and is recreated in the same folder as the image file after printing is finished. The sentinel file is generated according to the template. The purpose of the sentinel file is to give a printing done (finished) signal to other applications or scripts. This feature is useful for batch processing, a user application can choose to delete the sentinel file before calling Zan Image Printer, then wait for the sentinel file to be generated before starting the next print.

    Due to the inherent issues with Windows file system refreshes, we recommend that you use the newly added event or message notification interface instead if your application needs to monitor the printing process.


    Return to top




    Send Email from command line
    You can send Emails directly from the command line by using the email.send command provided by the command line utilities zvprtcfg and zvprtcfg_win32. This is a wrapper around Zan Image Printer's Email sending program zvprtemail.exe. You can even copy zvprtemail.exe and zvprtcfg.exe/zvprtcfg_win32.exe to another computer and use them together as standalone utilities for sending Emails without a full installation of Zan Image Printer.

    email.send command syntax (all options start with a single hyphen '-'):
    zvprtcfg [printername] email.send=[-option value] ...
    zvprtcfg_win32 [printername] email.send=[-option value] ...

    For a list of options and values you can use in the email.send command, see the email.ini table. In the table, the KeyName column represents the option and the Description column lists what values (string or DWORD) are allowed for the option.

    In addition to the options listed in the email.ini table, the email.send command also supports the following options:
    -cfg: read the Email options from a configuration file. The configuration file uses the email.ini format.
    -file: read from a file. The value of the previous option is taken from the specified file rather than the command line. Can be used after the following options:
    -body, -subject, -cc, -to, -attach
    For example, if a single line body is all that required, it can be specified on the command line using the -body option. However if a larger Email body is required, the body can be read from a file by specifying the -file option after the -body option.
    -dump: dump all Email sending options and values on screen when sending Emails.

    If the printername option is specified, Zan Image Printer will use the configuration file for that printer, the configuration file can also be specified by the -cfg option. Zan Image Printer will use the options in the configuration file by default. If an option is specified in both the configuration file and the command line, the command line value will override the configuration file. If you don't have or want a configuration file, you will need to specify all applicable options on the command line.

    The following examples show the use of the email.send command.
    Sample configuration files used in the examples:
    C:\email\smtpgmail.ini:
    [email]
    method=2
    port=465
    from=me@gmail.com
    to=me@example.com
    cc=
    displayname=John Smith
    servername=smtp.gmail.com
    username=me
    password=
    priority=0
    ssl=1
    auth=5
    encoding=21
    subject=Hello
    zip=0
    maxsize=20
    

    C:\email\mapi.ini:
    [email]
    method=1
    mapi=0
    to=me@example.com
    cc=
    subject=Hello
    maxsize=20
    

    C:\email\attach.txt:
    C:\attach\attach1.pdf
    C:\attach\attach2.pdf
    C:\attach\text1.txt,text2.txt,image.jpg
    
    C:\email\manual.pdf,document.doc,report.xls,data.txt
    

    C:\email\to.txt:
    john@example.com
    smith@recipients.com
    david@mail.com
    admin@isp.net
    

    Send an Email using the configuration file email.ini for the printer "zan image printer(bw)". The email.ini file is automatically modified and saved by Zan Image Printer when you configure the Email settings on the Settings->Email page.
    C:\Program Files\zvprt50>zvprtcfg "zan image printer(bw)" email.send=1
    

    Send Email using Google's Gmail service:
    C:\Program Files\zvprt50>zvprtcfg email.send=-cfg "c:\email\smtpgmail.ini" 
    -to -file "c:\email\to.txt" -attach -file "c:\email\attach.txt" -body 
    -file "c:\email\body.txt" -password xxxxx -username john
    

    Send Email through a MAPI compliant client like Outlook, Outlook Express, Mozilla Thunderbird, or Eudora:
    C:\Program Files\zvprt50>zvprtcfg email.send=-cfg "c:\email\mapi.ini" 
    -to "info@isp.net, john@example.com, david@mail.com" -body 
    "Hi, this is a test email" -subject "test" -dump 1 
    -attach "c:\attach\report.pdf;manual.doc;c:\help\manual.pdf"
    



    back up, restore, and copy a Zan Image Printer configuration
    Back up, restore, and copy Zan Image Printer configuration by using the command line utilities zvprtcfg and zvprtcfg_win32.

    Command Line Utility KeyName Value Type Description
    configuration.backup string Package the printer GPD file and *.ini setting files to a backup ZIP file for quick reload or use it to clone other printers.

    Examples:
    Create the printercfg.zip backup file and store it in Zan Image Printer(bw)'s "Configuration Directory" folder:
    zvprtcfg zan image printer(bw) configuration.backup=printercfg.zip

    Create the printercfg.zip backup file and store it in the c:\cfg folder:
    zvprtcfg zan image printer(bw) configuration.backup=c:\cfg\printercfg.zip
    configuration.restore string Restore the configuration from a backup ZIP file and overwrite the configuration of the destination printer.

    Examples:
    Restore the configuration from the printercfg.zip backup file stored in Zan Image Printer(bw)'s "Configuration Directory" folder:
    zvprtcfg zan image printer(bw) configuration.restore=printercfg.zip

    Restore the configuration from the printercfg.zip backup file stored in the c:\cfg folder:
    zvprtcfg zan image printer(bw) configuration.restore=c:\cfg\printercfg.zip
    configuration.copyto string Syntax:
    zvprtcfg srcprinter configuration.copyto=dstprinter
    zvprtcfg_win32 srcprinter configuration.copyto=dstprinter
    Copy scrprinter's configuration to dstprinter.

    Example:
    Copy Zan Image Printer(bw1)'s configuration to Zan Image Printer(bw2):
    zvprtcfg zan image printer(bw1) configuration.copyto=zan image printer(bw2)
    configuration.copyfrom string Syntax:
    zvprtcfg dstprinter configuration.copyfrom=srcprinter
    zvprtcfg_win32 dstprinter configuration.copyfrom=srcprinter
    Copy scrprinter's configuration to dstprinter.

    Example:
    Copy Zan Image Printer(bw1)'s configuration to Zan Image Printer(bw2):
    zvprtcfg zan image printer(bw2) configuration.copyfrom=zan image printer(bw1)


    Return to top



    add and delete printers from the command line
    Add and delete printers by using the command line utilities zvprtcfg and zvprtcfg_win32.
    Command Line Utility KeyName Value Type Description
    printer.add string Syntax:
    zvprtcfg installedprinter printer.add=newprinter;paper size;dpi;color;orientation;all users share the same settings
    zvprtcfg_win32 installedprinter printer.add=newprinter;paper size;dpi;color;orientation;all users share the same settings

    Add a printer from the command line.
    installedprinter: String; optional. This represents an installed printer name. If specified, the configuration of the installed printer is copied to the new printer and you only need to specify the newprinter parameter; all other parameters will be ignored.
    newprinter: String; required. This is the new printer you want to add to your computer.
    paper size: String; optional. Paper size or a list of paper sizes with commas (,).
    Set the default paper size by following the list of allowable paper sizes with a colon (:) and then the default paper size. See the gpd command for the list of paper sizes.
    dpi: String; optional. DPI resolution or a list of DPI resolutions with commas (,).
    To specify custom DPIs, enter DPI values separated by commas (e.g., 80, 500, 200 x 100). If the horizontal and vertical resolutions are the same, enter a single number to specify the resolution (e.g., 300 x 300 can be abbreviated to 300).
    See the gpd command for the list of dpi groups.
    color: String; optional. The color of the printer (bw or color).
    orientation: String; optional. The orientation of the printer (Portrait or Landscape).
    all users share the same settings: Integer; optional. Whether or not all users should share the same settings (0 = false, 1 = true); default is 1.

    Examples:
    Create a new printer zan image printer(bw2) that is identical to the installed printer zan image printer(bw1), except for the printer name:
    zvprtcfg zan image printer(bw1) printer.add=zan image printer(bw2)

    Create a new printer zan image printer(bw):
    zvprtcfg printer.add=zan image printer(bw)

    Create a new printer zan image printer:
    Restrict the supported DPI to 200 x 200 and 300 x 300, and set the default DPI to 200 x 200.
    Restrict the supported paper size to Letter and A4, and set the default paper size to Letter.
    Set the default color mode to color.
    Set "All users share the same setting" to 0 (false).
    zvprtcfg printer.add=zan image printer;200x200,300:200;A4,Letter:Letter;color,bw:color;0

    Create a new printer zan image printer:
    Use all group1 DPI resolutions and set the default DPI to 300 x 300.
    Use default paper size list and set the default paper size to Letter.
    zvprtcfg printer.add=zan image printer, group1:300x300,default:Letter
    printer.addfromfile string Add the printer(s) from a configuration file.
    For details about the configuration file, read the OEM page.

    Example:
    zvprtcfg printer.addfromfile=c:\addprinters\setup.ini
    This loads c:\addprinters\setup.ini and installs all printers specified in it.
    The following is a sample setup.ini file:
    [setup]
    custompaper_1=
    custompaper_2=
    custompaper_3=
    custompaper_4=
    
    [printer_1]
    install = 1
    printername = Zan Image Printer1
    location=
    comment=
    dpi = default
    defaultdpi = 300x300
    paper=default
    defaultpaper=
    color=default
    defaultcolor=bw
    orientation=default
    defaultorientation=
    allusers = 1
    autostart = 0
    
    
    [printer_2]
    install = 1
    printername = Zan Image Printer2
    location=
    comment=
    dpi = default
    defaultdpi =200x200
    paper=default
    defaultpaper=Letter
    color=default
    defaultcolor=color
    orientation=default
    defaultorientation=
    allusers = 1
    autostart = 0
    copyinifiles_1=save.ini, image_color.ini, general.ini
    copyinifiles_2=app.ini, advimage.ini, text.ini
    copyinifiles_3=docuname.ini, paper.ini, histdb_docuname.ini
    copyinifiles_4=event.ini, message.ini, watermark.ini, ftp.ini
    copyinifiles_5=email.ini, printerredirection.ini,sentineltemplate.txt
    copyinifiles_6=histdb_emailserver.ini,orientation.ini, histdb_ftpusername.ini
    
    printer.delete string Delete an installed printer from your computer.

    Example:
    Delete the printer named "zan image printer" from your computer:
    zvprtcfg printer.delete=zan image printer


    Return to top



    Batch document conversion, command line printing, programmatically print files
    To perform batch document conversion with Zan Image Printer:
    1. Set Zan Image Printer as the default printer:
    Open the Printers folder (Start > Printers and Faxes), right-click the printer, and click Set as Default Printer.

    2. Configure Zan Image Printer to operate in silent mode:
    On the Save page, set the "Before Printing Starts Show the:" to "No Dialogs" and set "Before Printing Starts Show the:" to "Auto pick a unique name to prevent collision" or "Always overwrite":

    To configure Zan Image Printer to operate in silent mode and hide the status dialog using the command line utilities:
    zvprtcfg Zan Image Printer(bw) save.silentmode=1
    zvprtcfg_win32 Zan Image Printer(bw) save.silentmode=1

    To configure Zan Image Printer to operate in silent mode and show the status dialog using the command line utilities:
    zvprtcfg Zan Image Printer(bw) save.silentmode=0
    zvprtcfg_win32 Zan Image Printer(bw) save.silentmode=0

    3. Open Windows Explorer, select all the files that you want to convert, right click and choose Print from the context menu to start the batch conversion.

    Many Windows programs can accept a command line argument to print. For example, the Kodak Imaging Preview program on Windows 2000 can be used to print an image to the default printer: C:\Program files\WindowsNT\Accessories\ImageVue\KodakPrv.exe /p test.bmp
    This is essentially what happens when you select a bmp file in Windows Explorer with a right click and then choose Print from the context menu. There is no difference between command line printing in a batch file and [right-click]-[Print].
    If you want to programmatically print using this method, just call CreateProcess with the required command line parameters or call the ShellExecute Win32 API with the Print verb in your application, you may need to pass a full application path to CreateProcess when calling it (for example, "C:\Program files\WindowsNT\Accessories\ImageVue\KodakPrv.exe /p test.bmp").

    You can use the Explorer file types dialog to view the syntax of the context menu Print command for your specific file type:
    1. Open Windows Explorer
    2. Select the Tools menu
    3. Select Folder Options
    4. Click the File Types tab
    5. Click the file type whose association you want to view, and then click Advanced
    6. Click Print
    7. Press the Edit button to view

    The command line utilities zvprtcfg and zvprtcfg_win32, provided by Zan Image Printer, support several batch printing commands. Use these commands to batch print Excel, Word, HTML, PDF, images, and other file types to Zan Image Printer. Specify the -recursive switch to print the files in a folder recursively. Use ';' as the separator to specify multiple files. (The '*' and '?' wildcard characters are allowed.)
    Specify the -watchfolder switch to monitor a folder and automate printing as files get copied to this folder.


    Command Line Utility KeyName Value Type Description
    print.shellexecute string Batch print files using the ShellExecute Print verb. Examples:
    print file c:\testfiles\a.doc to the printer zan image printer(bw):
    zvprtcfg_win32 zan image printer(bw) print.shellexecute=c:\testfiles\a.doc

    print all .pdf and .xls files in the folder c:\testfiles\ to the printer zan image printer(bw):
    zvprtcfg zan image printer(bw) print.shellexecute=c:\testfiles\*.pdf;*.xls

    print all .xls, .doc and .txt files in the folder c:\testfiles\ and its subfolders (recursively) to the printer zan image printer(bw):
    zvprtcfg zan image printer(bw) print.shellexecute=c:\testfiles\*.xls;*.doc;*.txt -recursive

    Continuously monitor c:\testfiles\ and its subfolders (recursively) for new .pdf and .doc files, and print them to the printer zan image printer(bw) when new files are added to the folder:
    zvprtcfg zan image printer(bw) print.shellexecute=c:\testfiles\*.pdf;*.doc -recursive -watchfolder

    Continuously monitor c:\testfiles\ and its subfolders (recursively) for new .pdf and .doc files, print them to the printer zan image printer(bw) when new files are added to the folder, save the generated images to the same folder where original file resides under the name of the original document (use the [%srcfolder] macro), also save the generated images at the same time to a remote server \\myserver\doc\ (use the copyfile command), then delete the original .pdf and .doc files (use the deletefile command and [%ODocName] macro):
    1. On the Save page, set Folder to [%srcfolder]\


    2. On the Application page, set Application to copyfile [%allfiles], \\myserver\doc\; deletefile [%ODocName]


    3. Run the following command from command prompt:
    zvprtcfg zan image printer(bw) print.shellexecute=c:\testfiles\*.pdf;*.doc -recursive -watchfolder
    print.html string Tip: Microsoft Internet Explorer truncates long directory and file names. Make sure your HTML file name is short or copy the HTML file you want to print into a folder with short name.

    Batch print files via Internet Explorer automation. Examples:
    print file c:\testfiles\a.htm to the printer zan image printer(bw):
    zvprtcfg zan image printer(bw) print.html=c:\testfiles\a.htm

    print all .htm files in the folder c:\testfiles\ to the printer zan image printer(bw):
    zvprtcfg_win32 zan image printer(bw) print.html=c:\testfiles\*.htm

    print the Google homepage to the printer zan image printer(bw):
    zvprtcfg zan image printer(bw) print.html=www.google.com

    print all .htm, .jpg and .gif files in the folder c:\testfiles\ and its subfolders (recursively) to the printer zan image printer(bw):
    zvprtcfg zan image printer(bw) print.html=c:\testfiles\*.htm;*.jpg;*.gif -recursive


    The command line utilities zvprtcfg and zvprtcfg_win32 provided by Zan Image Printer also support the print.script command which allows you to automate the batch printing with a script file. A script is a sequence of commands for which you have a repeated use. This sequence is executed by entering the name of the script on the command line:
    zvprtcfg zan image printer(color) print.script=your script file
    Example:
    zvprtcfg zan image printer(color) print.script=c:\batchscript\batchprint.txt
    This loads c:\batchscript\batchprint.txt and executes all commands in it one by one. To create a script, open a new empty file in your editor (Notepad for example). Put Zan Image Printer zvprtcfg and zvprtcfg_win32 commands in the new empty file, like you would enter them on the command line with zvprtcfg and zvprtcfg_win32.

    Here is a sample script file:
    ;; Zan Image Printer batch print script
    
    save.folder=c:\image
    save.basefilename=[%DocName]_[04d%Page]
    save.filenameindex=1
    save.filexistact=auto pick
    save.popupdialog=none
    docuname.removestrings=1
    docuname.removepath=1
    image.pagetype=serialized
    general.hidestsdialog=0
    general.opacity=40
    
    
    for imageformat in ['gif','tiff','jpeg', 'bmp', "pdf', 'jp2", "png']
    image.fileformat=$imageformat
    for imagecolor in ['bw','256','grayscale', 'true']
    image.imagecolor=$imagecolor
    for dpi in {'100', "150", "200", "240", "300"}
    gpd.dpi=$dpi
    print.html=c:\mydocs\*.htm
    print.shellexecute=c:\mydocs\*.doc
    end
    end
    end
    

    This scrip iterates over the items in a string sequence using the for-end loop statement, in the order that they appear in the sequence, where it's described as:
    for variable in {"value1", "value2", ...}
    commands to do something
    end
    
    You can specify the shell script variables along with the for-end loop statement in the script to hold a string of characters. To access the value (contents) of a variable, prefix it with a dollar sign '$' ($imageformat and $dpi in the above example).
    In the script file, all lines beginning with two semi-colons ';' are considered comments and do not have any effect.





    The table below lists some common applications and the command line parameters needed to start a print.
    File Type Command Line Examples Typical or Example Application Path
    RTF wordpad.exe /p filename.rtf C:\Program Files\Windows NT\Accessories
    TXT zvprtcfg zan image printer(bw) print.shellexecute=c:\testfiles\abc.txt
    notepad.exe /p filename.txt
    C:\WINNT
    PDF zvprtcfg zan image printer(bw) print.shellexecute=c:\testfiles\abc.pdf
    zvprtcfg zan image printer(bw) print.shellexecute=c:\testfiles\*.pdf

    acrord32.exe /t filename.pdf printername
    acrobat.exe /t filename.pdf printername
    C:\Program Files\Adobe\Acrobat 5.0\Acrobat
    MS Outlook outlook.exe /p filename.msg C:\Program Files\Microsoft Office
    HTML or HTM zvprtcfg zan image printer(bw) print.html=c:\testfiles\abc.htm
    zvprtcfg zan image printer(bw) print.html=c:\testfiles\*.htm

    printhtml c:\abc.htm
    printhtml is a VBScript that will print HTML files without displaying any dialogs (such as the PageSetup dialog), but you need to specify the full path to the file location. Please read the comments included with the printhtml VBScript (open it in Notepad to do that) before using it. Note that you need to insert some delay (navigationdelayinms) after the call to navigate to make sure the page is fully loaded before trying to print it. You also need to put some delay in (quitdelayinms) before destroying Internet Explorer, otherwise the WebBrowser control may raise an exception.
    For the equivalent VB/Delphi/C/VC.NET/VB.NET/C# code of printhtml, read the "Internet Explorer automation VB, Delphi, C, VC.NET, VB.NET and C# code samples: print HTML files programmatically" section.
    C:\WINNT\system32
    MS PowerPoint powerpnt.exe /p filename.ppt C:\Program Files\Microsoft Office
    MS Word zvprtcfg zan image printer(bw) print.shellexecute=c:\testfiles\abc.doc
    zvprtcfg zan image printer(bw) print.shellexecute=c:\testfiles\*.doc -recursive

    printdoc c:\abc.doc
    printdoc is a VBScript that will print Microsoft Word DOC files, you need to specify the full path to the file location. Please read the comments included with the printdoc VBScript (open it in Notepad to do that) before using it.
    For the equivalent VB/Delphi/C/VC.NET/VB.NET/C# code of printdoc, read the "Microsoft Word automation VB, Delphi, C, VC.NET, VB.NET and C# code samples: print Word DOC files programmatically" section.
    C:\Program Files\Microsoft Office
    MS Excel zvprtcfg zan image printer(bw) print.shellexecute=c:\testfiles\abc.xls
    zvprtcfg zan image printer(bw) print.shellexecute=c:\testfiles\*.xls
    zvprtcfg zan image printer(bw) print.shellexecute=c:\testfiles\*.xls -recursive

    printxls c:\abc.xls
    printxls is a VBScript that will print Microsoft Excel XLS files, you need to specify the full path to the file location. Please read the comments included with the printxls VBScript (open it in Notepad to do that) before using it. printxls will print all sheets in the workbook, it also contains commented out code showing how to print the selected sheet (such as the first sheet) only, you can uncomment it and put it back if needed.
    For the equivalent VB/Delphi/C/VC.NET/VB.NET/C# code of printxls, read the "Microsoft Excel automation VB, Delphi, C, VC.NET, VB.NET and C# code samples: print Excel XLS files programmatically" section.
    C:\Program Files\Microsoft Office
    TIFF, BMP, JPEG, AWD fax zvprtcfg zan image printer(bw) print.html=c:\testfiles\c:\abc.jpg
    kodakprv.exe /p filename
    C:\Program Files\Windows NT\Accessories\ImageVue



    Return to top




    Silent install and uninstall, installing multiple printers, full version, create a custom install
    For OEM/developer features such as silent install/uninstall, installing multiple printers, and custom printer names, click here!
    For OEM partners, we can provide a special version which does not require registration after installation.


    Dynamically remove unwanted string from the document name via regular expression
    Create images named by a field value within the document via regular expression
    If the document name passed in by the printing application contains unwanted strings in addition to the original document name, you can use regular expressions to eliminate the unwanted strings.
    Image files can also be custom named based on a field value within the document via regular expression. For more details, read the Document Name page.


    Return to top




    TIFF compatibility, TIFF Tag Viewer
    For the TIFF compatibility issue, see the Image->TIFF page.

    Return to top




    Set folder and file name programmatically via the StartDoc Win32 API
    If you are a software developer and are writing applications that will print to Zan Image Printer, you can control the output folder and file name on the fly. Just set lpszDocName field of the DOCINFO structure to the fully qualified path name of the file, then pass the DOCINFO structure to the StartDoc Win32 API.
    But by default, this feature is disabled, you need to enable it first by setting startdocfilename to 1 in general.ini. Also, please set the file name to [%DocName] on the Save tab.
    For the examples below, the printer name Zan Image Printer(bw) is assumed for illustration purposes only, replace this name with your own printer name if it is different.

    Using the command line utilities:
    zvprtcfg Zan Image Printer(bw) general.startdocfilename=1
    zvprtcfg Zan Image Printer(bw) save.basefilename=[%DocName]
    Or
    zvprtcfg_win32 Zan Image Printer(bw) general.startdocfilename=1
    zvprtcfg_win32 Zan Image Printer(bw) save.basefilename=[%DocName]


    The code samples below demonstrate how to get the name of the default printer and then send text output to it. If you have set startdocfilename to 1 in file general.ini, the generated output files are saved to e:\app folder as specified in the DOCINFO structure.

    VB code sample:
    Option Explicit
    
    Private Declare Function GetDefaultPrinter Lib "winspool.drv" Alias _
    "GetDefaultPrinterA" (ByVal pszBuffer As String, pcchBuffer As Long) As Long
    
    Private Declare Function CreateDC Lib "gdi32" Alias _
    "CreateDCA" (ByVal lpDriverName As String, ByVal lpDeviceName As String, _
    ByVal lpOutput As String, lpInitData As Any) As Long
    
    Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
    
    Private Declare Function TextOut Lib "gdi32" Alias "TextOutA" _
    (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, _
    ByVal lpString As String, ByVal nCount As Long) As Long ' or Boolean
    
    Private Declare Function StartDoc Lib "gdi32" Alias "StartDocA" _
    (ByVal hdc As Long, lpdi As DOCINFO) As Long
    
    Private Declare Function EndDoc Lib "gdi32" (ByVal hdc As Long) _
    As Long
    
    Private Declare Function StartPage Lib "gdi32" (ByVal hdc As Long) _
    As Long
    
    Private Declare Function EndPage Lib "gdi32" (ByVal hdc As Long) _
    As Long
    
    Private Type DOCINFO
    cbSize As Long
    lpszDocName As String
    lpszOutput As String
    lpszDatatype As String
    fwType As Long
    End Type
    
    Public Sub Main()
    Dim sPrinterName As String
    Dim sNameBuff As String, lLen As Long
    Dim OutString As String
    Dim result As Long
    Dim hPrintDc As Long 'Handle to printer dc
    Dim di As DOCINFO 'Structure for Print Document info
    Dim i As Integer
    
    GetDefaultPrinter vbNullChar, lLen
    sNameBuff = Space$(lLen)
    GetDefaultPrinter sNameBuff, lLen
    
    sPrinterName = Left$(sNameBuff, _
                InStr(sNameBuff, vbNullChar) - 1)
    
    di.cbSize = Len(di)
    di.lpszDocName = "e:\app\test.doc"
    
    'Create a printer device context
    hPrintDc=CreateDC(vbNullString,sPrinterName,vbNullString,ByVal 0&)
    
    result = StartDoc(hPrintDc, di) 'Start a new print document
    
    For i = 1 To 5
    result = StartPage(hPrintDc) 'Start a new page
    'Send text to printer
    OutString = _
        "Message from default printer " & sPrinterName & " page #" & i
    
    result=TextOut(hPrintDc, 20, 20, OutString, Len(OutString))
    result = EndPage(hPrintDc) 'End the page
    Next
    
    result = EndDoc(hPrintDc) 'End the print job
    result = DeleteDC(hPrintDc) 'Delete the device context
    End Sub
    

    Delphi code sample:
    uses
    Windows, SysUtils, ShlObj, ShellAPI, SHFolder,
    Graphics, WinSpool;
    
    function GetDefaultPrinterA(prnName:PAnsiChar; var bufSize:DWORD):
    BOOL; stdcall; external 'winspool.drv' name 'GetDefaultPrinterA';
    
    procedure test_defprinter();
    
    implementation
    
    function getDefaultPrinterName:string;
    var
      lprnName: PAnsiChar;
      lBufSize: DWord;
    begin
      GetMem(lprnName, MAX_PATH);
      try
         lBufSize := MAX_PATH;
         GetDefaultPrinterA(lprnName, lBufSize);
         Result := lprnName;
      finally
         FreeMem(lprnName);
      end;
    end;
    
    
    procedure test_defprinter();
    var
      stPrinter: String;
      msg: String;
      PrinterDC: HDC;
      DocInfo: TDocInfo;
      i: Integer;
    begin
    stPrinter := getDefaultPrinterName();
    PrinterDC := CreateDC(nil, PChar(stPrinter), nil, nil);
    //Fill Out the DocInfo structure for the spooler
    FillChar(DocInfo, sizeof(DocInfo), #0);
    GetMem(DocInfo.lpszDocName, 64);
    DocInfo.cbSize := SizeOf(DocInfo);
    StrPCopy(DocInfo.lpszDocName, 'e:\app\test.doc');
    StartDoc(PrinterDC, DocInfo);
    
    for i := 1 to 4 do begin
    StartPage(PrinterDC);
    msg := 'Message from default printer ' + stPrinter + ' page #' + IntToStr(i);
    TextOut(PrinterDC, 20, 20, PChar(msg), Length(msg));
    EndPage(PrinterDC);
    end;
    
    FreeMem(DocInfo.lpszDocName);
    EndDoc(PrinterDC);
    DeleteDC(PrinterDC);
    end;
    


    C code sample:
    BOOL PrintTest(void)
    {
       DWORD  size;
       HDC    hdcPrint;
    	
       //get the size of the default printer name
       GetDefaultPrinter(NULL, &size);
    	
       char *buffer = new char[size + 32];
    	
       if(buffer == NULL)
       {
         return FALSE;
       }
    	
       //buffer contains the printer name
       if(!GetDefaultPrinter(buffer, &size))
       {
    	delete[] buffer;
    	return FALSE;
       }
    	
    	
       hdcPrint = CreateDC(NULL, buffer, NULL, NULL);
       if(hdcPrint == NULL)
       {
          delete[] buffer;
          return FALSE;
       }
    
       DOCINFO di;
    	
       memset( &di, 0, sizeof(DOCINFO));
       di.cbSize = sizeof(DOCINFO); 
       di.lpszDocName = "e:\\app\\test.doc"; 
       di.lpszOutput = (LPTSTR) NULL; 
       di.fwType = 0; 
    	
    	
       int nError = StartDoc(hdcPrint, &di);
       if(nError == SP_ERROR) 
       { 
    	delete[] buffer;
            return FALSE;
       } 
    	
       char tmpstr[MAX_PATH];
    	
       //print 5 pages
       for(int i = 1; i < 5; i++)
       {
    	StartPage(hdcPrint);
    		
    	wsprintf(tmpstr,
              "Message from default printer %s, page #%d", buffer, i);
    		
    	TextOut(hdcPrint, 20, 20, tmpstr, strlen(tmpstr));
    		
    	EndPage(hdcPrint);
        }
    	
        EndDoc(hdcPrint);
        DeleteDC(hdcPrint);
    	
        delete[] buffer;
    	
        return TRUE;
    }
    



    Return to top




    VB, Delphi, C, VC.NET, VB.NET and C# code samples: print files programmatically using the ShellExecute Print verb
    The ShellExecute Win32 API lets you print all shell printable documents (e.g., PDF files, Microsoft Office documents, text files and many other files) to Zan Image Printer as long as the associated default programs have been installed on your computer. If you simply have a document you wish to print, and aren't too fussy about controlling the process, then you can use the ShellExecute approach. However, there are also several issues associated with ShellExecute print approach:
  • ShellExecute only prints to the default printer. To change printers, you have to change the default printer to the one which you want to print on, start printing, then restore the original default printer.


  • ShellExecute gives you no control. For example, if you use ShellExecute to print HTML files, Internet Explorer will prompt the user for the printer dialog, which is not desired when you need to automate the printing without any user intervention. Another example, when you use ShellExecute to print PDF files through Acrobat Reader, the Acrobat Reader may not close after it finishes printing the file.


  • ShellExecute returns immediately and does not wait until the print is finished. If you need to know when the associated application has completed printing, you can use the event notification interface provided by Zan Image Printer: wait for the EndDoc event to be sure that the submitted print job has indeed completed.


  • The code samples below demonstrate how to print to Zan Image Printer using the ShellExecute function. It also demonstrates how to change the default printer and wait for the EndDoc event to make sure the print is finished. The code samples below simply use the "SignalPrintDone" as the EndDoc event name. However, in a real application, for uniqueness, we recommend using an event name such as "Zan Image Printer(bw) SignalPrintDone" or a GUID string such as "{66A568A9-EECE-4695-BE9F-0CF85135E702}", so that it won't conflict with any other Zan Image Printer and Windows application.


    VB code sample:
    Option Explicit
    
    Private Declare Function GetDefaultPrinter Lib "winspool.drv" Alias _
    "GetDefaultPrinterA" (ByVal pszBuffer As String, pcchBuffer As Long) As Long
    
    Private Declare Function SetDefaultPrinter Lib "winspool.drv" _
       Alias "SetDefaultPrinterA" _
      (ByVal pszPrinter As String) As Long
    
    Private Declare Function SHGetFolderPath Lib "shell32" _
    Alias "SHGetFolderPathA" _
    (ByVal hwndOwner As Long, ByVal nFolder As Long, _
    ByVal hToken As Long, ByVal dwFlags As Long, _
    ByVal pszPath As String) As Long
       
    Private Declare Function WritePrivateProfileString Lib "kernel32.dll" _
    Alias "WritePrivateProfileStringA" _
    (ByVal lpApplicationName As String, _
    ByVal lpKeyName As String, ByVal lpString As String, _
    ByVal lpFileName As String) As Integer
    
    Private Declare Function GetPrivateProfileInt Lib "kernel32.dll" _
    Alias "GetPrivateProfileIntA" _
    (ByVal lpApplicationName As String, _
    ByVal lpKeyName As String, ByVal nDefault As Integer, _
    ByVal lpFileName As String) As Integer
    
       
    Private Declare Function ShellExecute Lib "shell32.dll" _
    Alias "ShellExecuteA" _
    (ByVal hWnd As Long, ByVal lpOperation As String, _
    ByVal lpFile As String, ByVal lpParameters As String, _
    ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
    
    Private Declare Function WaitForSingleObject Lib "kernel32.dll" _
    (ByVal hHandle As Long, ByVal _
    dwMilliseconds As Long) As Long
    
    Private Declare Function CreateEvent Lib "kernel32" _
    Alias "CreateEventA" (ByVal lpEventAttributes As Long, _
    ByVal bManualReset As Long, ByVal bInitialState As _
    Long, ByVal lpname As String) As Long
    
    Private Declare Function CloseHandle Lib "kernel32" _
    (ByVal hObject As Long) As Long
    
    Private Declare Function RegCloseKey Lib "advapi32.dll" _
    (ByVal hKey As Long) As Long
    
    Private Declare Function RegOpenKeyEx Lib "advapi32.dll" _
       Alias "RegOpenKeyExA" _
      (ByVal hKey As Long, _
       ByVal lpSubKey As String, _
       ByVal ulOptions As Long, _
       ByVal samDesired As Long, _
       phkResult As Long) As Long
    
    Private Declare Function RegQueryValueEx Lib "advapi32.dll" _
    Alias "RegQueryValueExA" (ByVal hKey As Long, _
    ByVal lpValueName As String, ByVal lpReserved As Long, _
    lpType As Long, lpData As Any, lpcbData As Long) As Long
    
    
    Private Declare Function GetVersionEx Lib "kernel32" _
       Alias "GetVersionExA" _
      (lpVersionInformation As OSVERSIONINFO) As Long
    
    
    
    Private Const HKEY_LOCAL_MACHINE = &H80000002
    'Registry action types.
    Private Const ERROR_SUCCESS = 0
    Private Const STANDARD_RIGHTS_READ As Long = &H20000
    Private Const KEY_QUERY_VALUE As Long = &H1
    Private Const KEY_ENUMERATE_SUB_KEYS As Long = &H8
    Private Const KEY_NOTIFY As Long = &H10
    Private Const SYNCHRONIZE As Long = &H100000
    Private Const KEY_READ As Long = ((STANDARD_RIGHTS_READ Or _
                                       KEY_QUERY_VALUE Or _
                                       KEY_ENUMERATE_SUB_KEYS Or _
                                       KEY_NOTIFY) And _
                                       (Not SYNCHRONIZE))
    
    
    'Used CSIDL values.
    Private Const CSIDL_APPDATA As Long = &H1A
    Private Const CSIDL_PROGRAM_FILES  As Long = &H26
    Private Const CSIDL_COMMON_APPDATA As Long = &H23
    Private Const CSIDL_COMMON_DOCUMENTS As Long = &H2E
    
    Private Const SHGFP_TYPE_CURRENT = 0
    Private Const S_OK As Long = 0
    Private Const MAX_PATH = 260
    Private Const SW_SHOWNORMAL = 1
    Private Const INFINITE = &HFFFF
    
    'Windows-defined type OSVERSIONINFO
    Private Type OSVERSIONINFO
      OSVSize         As Long
      dwVerMajor      As Long 'dwVerMajor = 6: Vista or above
      dwVerMinor      As Long
      dwBuildNumber   As Long
                                     
      PlatformID      As Long
      szCSDVersion    As String * 128
                                     
    End Type
    
    
    
    'Determines whether the given path refers to an existing
    'directory
    Function DirExists(ByVal DName As String) As Boolean
    Dim sDummy As String
    On Error Resume Next
    
    If Right(DName, 1) <> "\" Then DName = DName & "\"
    sDummy = Dir$(DName & "*.*", vbDirectory)
    DirExists = Not (sDummy = "")
    End Function
    
    
    'Searches a path for a file name
    Function GetFilePath(FileName As String) As String
        Dim i As Long
        For i = Len(FileName) To 1 Step -1
            Select Case Mid$(FileName, i, 1)
                Case ":"
                    GetFilePath = Left$(FileName, i)
                    Exit For
                Case "\"
                    GetFilePath = Left$(FileName, i - 1)
                    Exit For
            End Select
        Next
    End Function
    
    
    'Determines Zan Image Printer installation directory
    Private Function GetZanInstallDir() As String
    
    Dim sPath As String
    Dim szTmp As String * MAX_PATH
    Dim lResult As Long
    Dim hKey, dwSize As Long
    
    
    dwSize = MAX_PATH
    
    'first check to see if the uninstall registry entry exists
    If RegOpenKeyEx(HKEY_LOCAL_MACHINE, _
    "\Software\Microsoft\Windows\CurrentVersion\Uninstall\zvprt50" _
          , 0&, KEY_READ, hKey) = ERROR_SUCCESS Then
          If RegQueryValueEx(hKey, "UninstallString", _
          0&, 0&, ByVal szTmp, dwSize) = ERROR_SUCCESS Then
          
          sPath = Left$(szTmp, _
                InStr(szTmp, vbNullChar) - 1)
    
          sPath = GetFilePath(sPath)
          
          If DirExists(sPath) Then
          GetZanInstallDir = sPath
          Exit Function
          End If
          
          End If
          
    End If
         
    'fallback to the \Program Files\zvprt50 folder:
    lResult = SHGetFolderPath(0, _
                       CSIDL_PROGRAM_FILES, _
                       0, _
                       SHGFP_TYPE_CURRENT, _
                       szTmp)
                       
    sPath = Left$(szTmp, _
                InStr(szTmp, vbNullChar) - 1)
                
    If Right$(sPath, 1) <> "\" Then
        sPath = sPath & "\"
     End If
     sPath = sPath & "zvprt50"
     GetZanInstallDir = sPath
    End Function
    
    
    
    'Determines Zan Image Printer
    'configuration directory for the ini setting files
    Private Function GetZanConfigurationDir(ByVal szPrinter As String) As String
       Dim sPath As String * MAX_PATH
       Dim lResult As Long
       Dim lPolicy As Long
       Dim csidl As Long
       Dim osv As OSVERSIONINFO
       Dim LRet As Long
       Dim sCfg As String
    
       'read the OS info
       osv.OSVSize = Len(osv)
       LRet = GetVersionEx(osv)
       
       'read configure.ini from
       'Zan Image Printer installation directory
       sCfg = GetZanInstallDir()
    
       If Right$(sCfg, 1) <> "\" Then
        sCfg = sCfg & "\"
       End If
       sCfg = sCfg & "configure.ini"
    
       
       'Read the all users (per-machine) folder policy
       'from configure.ini:
       
       'policy=1: auto detect, if Vista or newer,
       'use CSIDL_COMMON_DOCUMENTS as the
       'all users (per-machine) folder;
       'otherwise, use CSIDL_COMMON_APPDATA
       'policy=2: use CSIDL_COMMON_APPDATA
       'policy=3: use CSIDL_COMMON_DOCUMENTS
    
       lPolicy = GetPrivateProfileInt("allusersfolder", "policy", _
       1, sCfg)
       
       'handle the auto detect policy
       If lPolicy = 1 Then
         'Vista and 2008: dwVerMajor>=6
         If osv.dwVerMajor >= 6 Then
         lPolicy = 3
         Else
         lPolicy = 2
         End If
       End If
       
       If lPolicy = 2 Then
       csidl = CSIDL_COMMON_APPDATA
       Else
       csidl = CSIDL_COMMON_DOCUMENTS
       End If
        
       
       'get the all users (per-machine) folder
       lResult = SHGetFolderPath(0, _
                       csidl, _
                       0, _
                       SHGFP_TYPE_CURRENT, _
                       sPath)
                       
       sCfg = Left$(sPath, _
                InStr(sPath, vbNullChar) - 1)
                
       If Right$(sCfg, 1) <> "\" Then
        sCfg = sCfg & "\"
       End If
       sCfg = sCfg & "zvprt50\" & szPrinter
       
       'if the all users (per-machine) folder exists,
       'then this zan image printer was installed per-machine:
       'all users share the same settings
       If DirExists(sCfg) Then
       'all users will share the same
       'settings for the printer
       GetZanConfigurationDir = sCfg
       Exit Function
       End If
       
       'if the all users (per-machine) folder doesn't exist,
       'assume each user has his own settings
       'for the printer:
       lResult = SHGetFolderPath(0, _
                       CSIDL_APPDATA, _
                       0, _
                       SHGFP_TYPE_CURRENT, _
                       sPath)
                       
       sCfg = Left$(sPath, _
                InStr(sPath, vbNullChar) - 1)
                
       If Right$(sCfg, 1) <> "\" Then
        sCfg = sCfg & "\"
       End If
       sCfg = sCfg & "zvprt50\" & szPrinter
       
       GetZanConfigurationDir = sCfg
    End Function
    
    
    Private Sub ShellExecutePrint(myDocument As String)
    ShellExecute 0, "print", myDocument, _
        vbNullString, vbNullString, SW_SHOWNORMAL
    
    End Sub
    
    
    
     Public Sub ShellExecutePrintTest()
     Dim szPrinter, szEnddocEvent, strPath, szDefPrinter As String
     Dim hEndDoc As Long
     Dim i As Long
     Dim sNameBuff As String, lLen As Long
    
     szPrinter = "Zan Image Printer(bw)"
     szEnddocEvent = "SignalPrintDone"
     
     hEndDoc = CreateEvent(ByVal 0&, False, False, szEnddocEvent)
     
     GetDefaultPrinter vbNullChar, lLen
     sNameBuff = Space$(lLen)
     GetDefaultPrinter sNameBuff, lLen
    
     szDefPrinter = Left$(sNameBuff, InStr(sNameBuff, vbNullChar) - 1)
     szDefPrinter = LCase(szDefPrinter)
     szPrinter = LCase(szPrinter)
    
     If szPrinter <> szDefPrinter Then
     SetDefaultPrinter szPrinter
     End If
    
     
     strPath = GetZanConfigurationDir(szPrinter)
     If Right$(strPath, 1) <> "\" Then
        strPath = strPath & "\"
     End If
    
     strPath = strPath & "event.ini"
     
     'enable event notification
     WritePrivateProfileString "event", "enable", _
       "1", strPath
    
     'set enddoc event name
     WritePrivateProfileString "event", "enddoc", szEnddocEvent, strPath
     
     ShellExecutePrint "c:\abc\1.doc"
    
     i = WaitForSingleObject(hEndDoc, INFINITE)
    
     ShellExecutePrint "c:\abc\1.pdf"
    
     i = WaitForSingleObject(hEndDoc, INFINITE)
    
     If szPrinter <> szDefPrinter Then
     SetDefaultPrinter szDefPrinter
     End If
    
     CloseHandle (hEndDoc)
    End Sub
    
    
    
    Public Sub Main()
    ShellExecutePrintTest
    
    End Sub
    
    

    Delphi code sample:
    unit zanprinter;
    
    interface
    uses
    Windows, Messages, SysUtils, ShlObj, ShellAPI, SHFolder;
    
    function GetDefaultPrinter(prnName:PAnsiChar; var bufSize:DWORD):
    BOOL; stdcall; external 'winspool.drv' name 'GetDefaultPrinterA';
    
    function SetDefaultPrinter(prnName:PAnsiChar):
    BOOL; stdcall; external 'winspool.drv' name 'SetDefaultPrinterA';
    
    procedure ShellExecutePrint(myDocument:String);
    procedure ShellExecutePrintTest();
    procedure GetZanInstallDir(var APath: String);
    procedure GetZanConfigurationDir(var szPrinter: String;
    var cfgdir: String);
    
    implementation
    
    //Determines Zan Image Printer installation directory
    procedure GetZanInstallDir(var APath: String);
    var
      hkeyStartup: HKEY;
      dwSize: DWORD;
    begin
      dwSize := MAX_PATH;
      SetLength(APath, MAX_PATH);
    
      //first check to see if the uninstall registry entry exists
      if RegOpenKeyEx(HKEY_LOCAL_MACHINE,
       '\Software\Microsoft\Windows\CurrentVersion\Uninstall\zvprt50',
       0,
       KEY_READ,
       hkeyStartup) = ERROR_SUCCESS then
       begin
    
       if RegQueryValueEx(hkeyStartup,
                         'UninstallString', nil, nil,
                          PBYTE(Pchar(APath)),
                          @dwSize) = ERROR_SUCCESS then
       begin
          APath := String (PChar(APath));
          APath := ExtractFilePath(APath);
       end;
    
       //Close the Key, we won't be needing it anymore
       RegCloseKey(hkeyStartup);
    
       if DirectoryExists(APath) then Exit;
      end;
    
      //fallback to the \Program Files\zvprt50 folder:
      SHGetFolderPath(0, CSIDL_PROGRAM_FILES, 0, 0,
                      PChar(APath));
    
      APath := String (PChar (APath));
      if (APath[Length(APath)] <> '\')
      then APath := APath + '\';
    
      APath := APath + 'zvprt50';
    end;
    
    
    //Determines Zan Image Printer
    //configuration directory for the ini setting files
    procedure GetZanConfigurationDir(var szPrinter: String;
    var cfgdir: String);
    var
      osv: TOSVersionInfo;
      lPolicy, csidl: Integer;
    begin
      SetLength(cfgdir, MAX_PATH);
    
      //read the OS info
      FillChar(osv, SizeOf(osv), 0);
      osv.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
      GetVersionEx(osv);
    
      //read configure.ini from
      //Zan Image Printer installation directory
      GetZanInstallDir(cfgdir);
      if (cfgdir[Length(cfgdir)] <> '\') then cfgdir := cfgdir + '\';
      cfgdir := cfgdir + 'configure.ini';
    
      //read configure.ini from
      //Zan Image Printer installation directory.
      //Read the all users (per-machine) folder policy
      //rom configure.ini:
    
      //policy=1: auto detect, if Vista or newer,
      //use CSIDL_COMMON_DOCUMENTS as the
      //all users (per-machine) folder;
      //otherwise, use CSIDL_COMMON_APPDATA
      //policy=2: use CSIDL_COMMON_APPDATA
      //policy=3: use CSIDL_COMMON_DOCUMENTS
      lPolicy := GetPrivateProfileInt('allusersfolder', 'policy',
       1, PChar(cfgdir));
    
      //handle the auto detect policy
      if lPolicy = 1 then
      begin
         //Vista and 2008: dwVerMajor>=6
         if osv.dwMajorVersion >= 6 then lPolicy := 3
         else  lPolicy := 2;
      end;
    
      if lPolicy = 2 then  csidl := CSIDL_COMMON_APPDATA
      else  csidl := CSIDL_COMMON_DOCUMENTS;
    
      //get the all users (per-machine) folder
      SetLength(cfgdir, MAX_PATH);
      SHGetFolderPath(0, csidl, 0, 0, PChar(cfgdir));
      cfgdir := String (PChar (cfgdir));
      if (cfgdir[Length(cfgdir)] <> '\') then cfgdir := cfgdir + '\';
      cfgdir := cfgdir + 'zvprt50\' + szPrinter;
    
      //if the all users (per-machine) folder exists,
      //then this zan image printer was installed per-machine:
      //all users share the same settings
      if DirectoryExists(cfgdir) then Exit;
    
      //if the all users (per-machine) folder doesn't exist,
      //assume each user has his own settings
      //for the printer:
      SHGetFolderPath(0, CSIDL_APPDATA, 0, 0, PChar(cfgdir));
      cfgdir := String (PChar (cfgdir));
      if (cfgdir[Length(cfgdir)] <> '\') then cfgdir := cfgdir + '\';
      cfgdir := cfgdir + 'zvprt50\' + szPrinter;
    end;
    
    procedure ShellExecutePrint(myDocument:String);
    begin
    ShellExecute(0, 'print', PChar(myDocument), nil, nil, SW_SHOW);
    end;
    
    procedure ShellExecutePrintTest();
      var
      szPrinter, szEnddocEvent, strPath, szDefPrinter: String;
      lBufSize: DWord;
      hEndDoc: THandle;
      begin
      szPrinter := 'Zan Image Printer(bw)';
      szEnddocEvent := 'SignalPrintDone';
    
      hEndDoc := CreateEvent(nil,False,False,Pchar(szEnddocEvent));
    
      SetLength(szDefPrinter, MAX_PATH);
      lBufSize := MAX_PATH;
      GetDefaultPrinter(Pchar(szDefPrinter), lBufSize);
      szDefPrinter := String (PChar(szDefPrinter));
      szDefPrinter := LowerCase(szDefPrinter);
      szPrinter := LowerCase(szPrinter);
    
      //change the default printer prior to calling the
      //ShellExecutePrint function.
      if(szPrinter <> szDefPrinter)
      then SetDefaultPrinter(PChar(szPrinter));
    
      GetZanConfigurationDir(szPrinter, strPath);
      if (strPath[Length(strPath)] <> '\')
      then  strPath := strPath + '\';
      strPath :=strPath + 'event.ini';
    
      //enable event notification
      WritePrivateProfileString('event',
      'enable', '1', Pchar(strPath));
      //set enddoc event name
      WritePrivateProfileString('event',
      'enddoc', Pchar(szEnddocEvent), Pchar(strPath));
    
      //The print job status is "sent to printer" when
      //ShellExecutePrint returns.
      ShellExecutePrint('c:\abc\1.doc');
      //wait for the EndDoc event to be received,
      //an indication that the submitted print
      //job has indeed completed
      WaitForSingleObject(hEndDoc, INFINITE);
    
      //The print job status is "sent to printer" when
      //ShellExecutePrint returns.
      ShellExecutePrint('c:\abc\1.pdf');
      //wait for the EndDoc event to be received,
      //an indication that the submitted print
      //job has indeed completed
      WaitForSingleObject(hEndDoc, INFINITE);
    
      //set default printer back to original
      if(szPrinter <> szDefPrinter)
      then SetDefaultPrinter(PChar(szDefPrinter));
    
      CloseHandle(hEndDoc);
    end;
    
    end.
    

    C code sample:
    #include <windows.h>
    #include <winspool.h>
    #include <shlobj.h>
    #include <shlwapi.h>
    #include <shellapi.h>
    
    /*#import statement and smart pointers*/
    #import  <shdocvw.dll>
    
    #pragma comment(lib, "shlwapi.lib")
    
    
    //Determines whether the given path refers to 
    //an existing directory
    BOOL IsFolderExists(char *lpDirectoryName)
    {
    	if(0 == strlen(lpDirectoryName))
    	{
    		return FALSE;
    	}
    
    	DWORD dwFileAttr = GetFileAttributes(lpDirectoryName);
    
    	if((dwFileAttr != 0xFFFFFFFF) &&
    		(dwFileAttr & FILE_ATTRIBUTE_DIRECTORY))
    	{
    		return TRUE;
    	}
    	else
    	{
    		return FALSE;
    	}
    }
    
    
    
    //Determines Zan Image Printer installation directory
    void GetZanInstallDir(char *installfolder)
    {
    	HKEY hkeyStartup;
    
    	//first check to see if the uninstall registry entry exists
    	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
    		"\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\zvprt50",
    		0,          
    		KEY_READ,  
    		&hkeyStartup) == ERROR_SUCCESS)
    	{
    		DWORD dwSize = MAX_PATH;
    
    		if(RegQueryValueEx(hkeyStartup, 
    			"UninstallString", 
    			NULL,
    			NULL,
    			(LPBYTE)installfolder,
    			&dwSize) == ERROR_SUCCESS)
    		{
    			PathRemoveFileSpec(installfolder);
    			PathAddBackslash(installfolder);
    		}
    
    		/*Close the Key, we won't be needing it anymore*/
    		RegCloseKey(hkeyStartup);
    
    		if(IsFolderExists(installfolder))
    		{
    			return;
    		}
    	}
    
    	//fallback to the \Program Files\zvprt50 folder:
    	SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, 0, installfolder);
    	PathAddBackslash(installfolder);
    
    	strcat(installfolder,"zvprt50");
    }
    
    
    
    BOOL IsVistaOrAbove(void)
    {
    	OSVERSIONINFOEX osvi;
    	BOOL bOsVersionInfoEx;
    
    	ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
    
    	//Try calling GetVersionEx using the OSVERSIONINFOEX structure.
    	//If that fails, try using the OSVERSIONINFO structure.
    	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    	if(!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*)&osvi)))
    	{
    		osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    		if(!GetVersionEx((OSVERSIONINFO*)&osvi))
    			return FALSE;
    	}
    
    	//vista and 2008: 6
    	//2003: 5
    	//xp: 5
    	if(osvi.dwMajorVersion >= 6)
    	{
    		return TRUE;
    	}
    	else
    	{
    		return FALSE;
    	}
    }
    
    
    
    //Determines Zan Image Printer
    //configuration directory for the ini setting files
    void GetZanConfigurationDir(char *sPrinter, char *sCfg)
    {
    	DWORD lPolicy;
    	DWORD csidl;
    
    	//read configure.ini from
    	//Zan Image Printer installation directory
    	GetZanInstallDir(sCfg);
    	PathAddBackslash(sCfg);
    	strcat(sCfg,"configure.ini");
    
    	//Read the all users (per-machine) folder policy
    	//from configure.ini:
    
    	//policy=1: auto detect, if Vista or newer,
    	//use CSIDL_COMMON_DOCUMENTS as the
    	//all users (per-machine) folder;
    	//otherwise, use CSIDL_COMMON_APPDATA
    	//policy=2: use CSIDL_COMMON_APPDATA
    	//policy=3: use CSIDL_COMMON_DOCUMENTS
    
    	lPolicy = GetPrivateProfileInt("allusersfolder", 
    		"policy", 1, sCfg);
    
    	//handle the auto detect policy
    	if(1 == lPolicy)
    	{
    		if(IsVistaOrAbove())  lPolicy = 3;
    		else lPolicy = 2;
    	}
    
    
    	if(2 == lPolicy)
    	{
    		csidl = CSIDL_COMMON_APPDATA;
    	}
    	else
    	{
    		csidl = CSIDL_COMMON_DOCUMENTS;
    	}
    
    	//get the all users (per-machine) folder
    	SHGetFolderPath(NULL, csidl, NULL, 0, sCfg);
    	PathAddBackslash(sCfg);
    	strcat(sCfg, "zvprt50\\");
    	strcat(sCfg, sPrinter);
    		
    
    	//if the all users (per-machine) folder exists,
    	//then this zan image printer was installed per-machine: 
    	//all users share the same settings
    	if(IsFolderExists(sCfg)) return;
    
    
    	//if the all users (per-machine) folder doesn't exist,
    	//assume each user has his own settings
    	//for the printer:
    	SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, sCfg);
    	PathAddBackslash(sCfg);
    	strcat(sCfg, "zvprt50\\");
    	strcat(sCfg, sPrinter);
    }
    
    
    void ShellExecutePrint(char *myDocument)
    {
       ShellExecute(NULL, "print", myDocument, 
        NULL, NULL, SW_SHOWNORMAL);
    }
    
    
    int main(int argc, char* argv[])
    {
    	char* szPrinter = "Zan Image Printer(bw)";
    	char* szEnddocEvent = "SignalPrintDone";
    	char  strPath[MAX_PATH];
    	char  szDefPrinter[MAX_PATH];
    	HANDLE hEndDoc;
    
    	hEndDoc = CreateEvent(NULL, FALSE, FALSE, szEnddocEvent);
    	if(hEndDoc == NULL)
    	{
    		return -1;
    	}
    
    	DWORD dwBufSize = MAX_PATH;
    	GetDefaultPrinter(szDefPrinter, &dwBufSize);
    
    	/*
    	change the default printer prior to calling the
    	ShellExecutePrint function.
    	*/
    	if(strcmpi(szPrinter, szDefPrinter))
    	{
    		SetDefaultPrinter(szPrinter);
    	}
    
        GetZanConfigurationDir(szPrinter, strPath);
    	PathAddBackslash(strPath);
    	strcat(strPath,"event.ini");
    
    	//enable event notification
    	WritePrivateProfileString("event", "enable", "1", strPath);
    	//set enddoc event name
    	WritePrivateProfileString("event", "enddoc", 
    		szEnddocEvent, strPath);
    
    	//The print job status is "sent to printer" when
    	//ShellExecutePrint returns.
    	ShellExecutePrint("c:\\abc\\1.doc");
    	//wait for the EndDoc event to be received,
    	//an indication that the submitted print job has 
    	//indeed completed
    	WaitForSingleObject(hEndDoc, INFINITE);
    
    	//The print job status is "sent to printer" when
    	//ShellExecutePrint returns.
    	ShellExecutePrint("c:\\abc\\1.pdf");
    	//wait for the EndDoc event to be received,
    	//an indication that the submitted print job has 
    	//indeed completed
    	WaitForSingleObject(hEndDoc, INFINITE);
    
    	/*set default printer back to original*/
    	if(strcmpi(szPrinter, szDefPrinter))
    	{
    		SetDefaultPrinter(szDefPrinter);
    	}
    
    	return 0;
    }
    
    

    VC.NET code sample:
    using namespace System;
    using namespace System::Text;
    using namespace System::IO;
    using namespace System::Runtime::InteropServices;
    using namespace System::Diagnostics;
    using namespace System::Threading;
    using namespace Microsoft::Win32;
    
    
    // Declare the function that is exported from unmanaged dll:
    [DllImport("KERNEL32.DLL")]
    extern "C" int _cdecl GetPrivateProfileString(
       String^ lpAppName, 
       String^ lpKeyName,
       String^ lpDefault, 
       StringBuilder^ lpReturnedString, 
       int nSize,
       String^ lpFileName);
    
    [DllImport("KERNEL32.DLL")]
    extern "C" bool _cdecl WritePrivateProfileString(
       String^ lpAppName, 
       String^ lpKeyName,
       String^ lpString, 
       String^ lpFileName);
    
    [DllImport("KERNEL32.DLL")]
    extern "C" int _cdecl GetPrivateProfileInt(
       String^ lpAppName, 
       String^ lpKeyName,
       int nDefault, 
       String^ lpFileName);
    
    [DllImport("shell32.dll")]
    extern "C" bool _cdecl SHGetFolderPath(int hwndOwner,
    int nFolder, int hToken, int dwFlags, StringBuilder^ pszPath);
    const int CSIDL_COMMON_DOCUMENTS = 0x002e;
    
    
    [DllImport("winspool.drv")]
    extern "C" bool _cdecl GetDefaultPrinter(
    	 StringBuilder^ pszBuffer, int *size);
    
    [DllImport("winspool.drv")]
    extern "C" bool _cdecl SetDefaultPrinter(
    	 String^ pszPrinter);
    
    
    //Determines Zan Image Printer installation directory
    String^ GetZanInstallDir(void)
    {
    	String^ installfolder = String::Empty;
    	RegistryKey ^ rkTest;
    
    	//first check to see if the uninstall registry entry exists
    	rkTest = Registry::LocalMachine->OpenSubKey(
    		L"\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\zvprt50");
    	if(rkTest)
    	{
    		installfolder = rkTest->GetValue(L"UninstallString")->ToString();
    		rkTest->Close();
    
    		if(installfolder->Length)
    		{
    			installfolder = Path::GetDirectoryName(installfolder);
    
    			DirectoryInfo^ installdir1=gcnew DirectoryInfo(installfolder);
    			if(installdir1->Exists)
    			{
    				return installfolder;
    			}
    		}
    	}
    
    	//fallback to the \Program Files\zvprt50 folder:
    	installfolder = Environment::GetFolderPath
    		(Environment::SpecialFolder::ProgramFiles);
    
    	if(!installfolder->EndsWith(L"\\")) 
    		installfolder = String::Concat(installfolder, L"\\");
    
    	installfolder=String::Concat(installfolder, L"zvprt50");
    
    	return installfolder;
    }
    
    
    //Determines Zan Image Printer
    //configuration directory for the ini setting files
    String^ GetZanConfigurationDir(String^ szPrinter)
    {
    	//read the OS info
    	OperatingSystem^ os = System::Environment::OSVersion;
    	String^ sCfg;
    	int lPolicy;
    	StringBuilder^ tmpstr = gcnew StringBuilder(256);
    
    	//read configure.ini from
    	//Zan Image Printer installation directory
    	sCfg = GetZanInstallDir();
    
    	if(!sCfg->EndsWith(L"\\")) 
    		sCfg = String::Concat(sCfg, L"\\");
    
    	sCfg = String::Concat(sCfg, L"configure.ini");
    
    
    	//Read the all users (per-machine) folder policy
    	//from configure.ini:
    
    	//policy=1: auto detect, if Vista or newer,
    	//use CSIDL_COMMON_DOCUMENTS as the
    	//all users (per-machine) folder;
    	//otherwise, use CSIDL_COMMON_APPDATA
    	//policy=2: use CSIDL_COMMON_APPDATA
    	//policy=3: use CSIDL_COMMON_DOCUMENTS
    
    	lPolicy = GetPrivateProfileInt(L"allusersfolder", L"policy",
    		1, sCfg);
    
    	//handle the auto detect policy
    	if(1 == lPolicy)
    	{
    		//Vista and 2008: dwVerMajor>=6
    		if(os->Version->Major >= 6)
    		{
    			lPolicy = 3;
    		}
    		else
    		{
    			lPolicy = 2;
    		}
    	}
    
    
    	//get the all users (per-machine) folder
    	//if the all users (per-machine) folder exists,
    	//then this zan image printer was installed per-machine: 
    	//all users share the same settings
    	if(2 == lPolicy)
    	{
    		//csidl = CSIDL_COMMON_APPDATA;
    		sCfg = Environment::GetFolderPath
    			(Environment::SpecialFolder::CommonApplicationData);
    
    	}
    	else
    	{
    		//csidl = CSIDL_COMMON_DOCUMENTS;
    		SHGetFolderPath(0, CSIDL_COMMON_DOCUMENTS, 0, 0, tmpstr);
    		sCfg = tmpstr->ToString();
    	}
    
    	if(!sCfg->EndsWith(L"\\")) sCfg = String::Concat(sCfg, L"\\");
    	sCfg = String::Concat(sCfg, L"zvprt50\\");
    	sCfg = String::Concat(sCfg, szPrinter);
    
    	//all users will share the same
    	//settings for the printer
    	DirectoryInfo^ tmpdir = gcnew DirectoryInfo(sCfg);
    	if(tmpdir->Exists)
    	{
    		return sCfg;
    	}
    
    	//if the all users (per-machine) folder doesn't exist,
    	//assume each user has his own settings
    	//for the printer:
    	sCfg = Environment::GetFolderPath
    		(Environment::SpecialFolder::ApplicationData);
    
    	if(!sCfg->EndsWith(L"\\")) sCfg = String::Concat(sCfg, L"\\");
    	sCfg = String::Concat(sCfg, L"zvprt50\\");
    	sCfg = String::Concat(sCfg, szPrinter);
    
    	return sCfg;
    }
    
    
    
    void ShellExecutePrint(String ^myDocument)
    {
      Process^ myProcess = gcnew Process;
    
      myProcess->StartInfo->FileName = myDocument;
      myProcess->StartInfo->Verb = L"Print";
      myProcess->StartInfo->CreateNoWindow = true;
      myProcess->Start();
    }
    
    
    int main(array ^args)
    {
     String^ szPrinter = L"Zan Image Printer(bw)";
     String^ szEnddocEvent = L"SignalPrintDone";
     String^ strPath;
    
     StringBuilder^ tempstr = gcnew StringBuilder(256);
     String^ szDefPrinter;
     int dwBufSize = tempstr->Capacity;
    
     GetDefaultPrinter(tempstr, &dwBufSize);
     szDefPrinter = tempstr->ToString();
    
     /*
     change the default printer prior to calling the
     ShellExecutePrint function.
     */
     if(String::Compare(szPrinter, szDefPrinter, true) != 0)
     {
       SetDefaultPrinter(szPrinter);
     }
    
     strPath = GetZanConfigurationDir(szPrinter);
    
     if(!strPath->EndsWith(L"\\")) strPath=String::Concat(strPath,L"\\");
     strPath = String::Concat(strPath, 
     	L"event.ini");
    
     //enable event notification
     WritePrivateProfileString(L"event", L"enable", L"1", strPath);
     //set enddoc event name
     WritePrivateProfileString(L"event", L"enddoc", szEnddocEvent, strPath);
    
     EventWaitHandle^ ewh;
     ewh=gcnew EventWaitHandle(false,EventResetMode::AutoReset,szEnddocEvent);
    
     //The print job status is "sent to printer" when
     //ShellExecutePrint returns.
     ShellExecutePrint(L"c:\\abc\\1.doc");
     //wait for the EndDoc event to be received,
     //an indication that the submitted print job has indeed completed
      ewh->WaitOne();
    
     //The print job status is "sent to printer" when
     //ShellExecutePrint returns.
     ShellExecutePrint(L"c:\\abc\\1.pdf");
     //wait for the EndDoc event to be received,
     //an indication that the submitted print job has indeed completed
     ewh->WaitOne();
    
     /*set default printer back to original*/
     if(String::Compare(szPrinter, szDefPrinter, true) != 0)
     {
       SetDefaultPrinter(szDefPrinter);
     }
    
     return 0;
    }
    
    

    VB.NET code sample:
    Imports System
    Imports System.Runtime.InteropServices
    Imports System.Text
    Imports System.Diagnostics
    Imports System.Threading
    Imports System.IO
    Imports Microsoft.Win32
    
    
    Module Module1
        Declare Function GetDefaultPrinter Lib "winspool.drv" _
        Alias "GetDefaultPrinterA" _
        (ByVal pszBuffer As System.Text.StringBuilder, _
        ByRef size As Int32) As Boolean
    
        Declare Function SetDefaultPrinter Lib "winspool.drv" _
        Alias "SetDefaultPrinterA" _
        (ByVal pszPrinter As String) As Boolean
    
        Private Declare Function GetPrivateProfileString Lib "kernel32" _
         Alias "GetPrivateProfileStringW" _
        (ByVal lpAppName As String, _
         ByVal lpKeyName As String, _
         ByVal lpDefault As String, _
         ByVal lpReturnedString As StringBuilder, _
         ByVal nSize As Integer, _
         ByVal lpFileName As String) As Integer
    
        Private Declare Function GetPrivateProfileInt Lib "kernel32.dll" _
                Alias "GetPrivateProfileIntA" _
               (ByVal lpApplicationName _
                As String, ByVal lpKeyName As String, ByVal nDefault As _
                Integer, ByVal lpFileName As String) As Integer
    
        Private Declare Function WritePrivateProfileString Lib "kernel32.dll" _
                Alias "WritePrivateProfileStringA" _
               (ByVal lpAppName As String, _
                ByVal lpKeyName As String, _
                ByVal lpString As String, _
                ByVal lpFileName As String) As Boolean
    
        Private Declare Function SHGetFolderPath Lib "shell32.dll" _
        Alias "SHGetFolderPathA" _
        (ByVal hwndOwner As Integer, _
        ByVal nFolder As Integer, _
        ByVal hToken As Integer, _
        ByVal dwFlags As Integer, _
        ByVal pszPath As StringBuilder) As Integer
    
        'All Users\Documents 
        Private Const CSIDL_COMMON_DOCUMENTS = &H2E
    
    
        'Determines Zan Image Printer installation directory
        Function GetZanInstallDir() As String
            Dim installfolder As String
            Dim rkTest As RegistryKey
    
            'first check to see if the uninstall registry entry exists
            rkTest = Registry.LocalMachine.OpenSubKey _
     ("SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\zvprt50")
    
            If Not (rkTest Is Nothing) Then
                installfolder = rkTest.GetValue _
                  ("UninstallString").ToString()
                rkTest.Close()
                If (installfolder.Length > 0) Then
                    installfolder = Path.GetDirectoryName(installfolder)
                    Dim installdir1 As DirectoryInfo = _
                       New DirectoryInfo(installfolder)
    
                    If installdir1.Exists Then
                        Return installfolder
                    End If
                End If
            End If
            'fallback to the \Program Files\zvprt50 folder:
            installfolder = Environment.GetFolderPath _
    (Environment.SpecialFolder.ProgramFiles)
    
            If Not installfolder.EndsWith("\") Then
                installfolder = String.Concat(installfolder, "\")
            End If
    
            installfolder = String.Concat(installfolder, "zvprt50")
            Return installfolder
        End Function
    
    
        'Determines Zan Image Printer
        'configuration directory for the ini setting files
        Function GetZanConfigurationDir(ByVal szPrinter As String) As String
            'read the OS info
            Dim os As OperatingSystem
            Dim sCfg As String
            Dim lPolicy As Integer
            Dim tmpstr As StringBuilder
    
            tmpstr = New StringBuilder(256)
    
            os = System.Environment.OSVersion
    
            'read configure.ini from
            'Zan Image Printer installation directory
            sCfg = GetZanInstallDir()
    
            If Not sCfg.EndsWith("\") Then
                sCfg = String.Concat(sCfg, "\")
            End If
    
            sCfg = String.Concat(sCfg, "configure.ini")
    
    
            'Read the all users (per-machine) folder policy
            'from configure.ini:
    
            'policy=1: auto detect, if Vista or newer,
            'use CSIDL_COMMON_DOCUMENTS as the
            'all users (per-machine) folder;
            'otherwise, use CSIDL_COMMON_APPDATA
            'policy=2: use CSIDL_COMMON_APPDATA
            'policy=3: use CSIDL_COMMON_DOCUMENTS
    
            lPolicy = GetPrivateProfileInt("allusersfolder", _
                "policy", 1, sCfg)
    
            'Vista and 2008: dwVerMajor>=6
            If lPolicy = 1 Then
                If os.Version.Major >= 6 Then
                    lPolicy = 3
                Else
                    lPolicy = 2
                End If
            End If
    
    
            'get the all users (per-machine) folder
            'if the all users (per-machine) folder exists,
            'then this zan image printer was installed per-machine: 
            'all users share the same settings
            If lPolicy = 2 Then
                'csidl = CSIDL_COMMON_APPDATA;
                sCfg = Environment.GetFolderPath( _
                Environment.SpecialFolder.CommonApplicationData)
            Else
                'csidl = CSIDL_COMMON_DOCUMENTS;
                SHGetFolderPath(0, CSIDL_COMMON_DOCUMENTS, 0, 0, tmpstr)
                sCfg = tmpstr.ToString()
            End If
    
    
            If Not sCfg.EndsWith("\") Then
                sCfg = String.Concat(sCfg, "\")
            End If
            sCfg = String.Concat(sCfg, "zvprt50\")
            sCfg = String.Concat(sCfg, szPrinter)
    
            'all users will share the same
            'settings for the printer
            Dim tmpdir As DirectoryInfo = _
                       New DirectoryInfo(sCfg)
    
            If tmpdir.Exists Then
                Return sCfg
            End If
    
            'if the all users (per-machine) folder doesn't exist,
            'assume each user has his own settings
            'for the printer:
            sCfg = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
    
            If Not sCfg.EndsWith("\") Then
                sCfg = String.Concat(sCfg, "\")
            End If
            sCfg = String.Concat(sCfg, "zvprt50\")
            sCfg = String.Concat(sCfg, szPrinter)
    
            Return sCfg
        End Function
    
    
    
        Private Sub ShellExecutePrint(ByVal myDocument As String)
            Dim myProcess As Process = New Process
    
            myProcess.StartInfo.FileName = myDocument
            myProcess.StartInfo.Verb = "Print"
            myProcess.StartInfo.CreateNoWindow = True
            myProcess.Start()
        End Sub
    
    
        Sub Main()
            Dim szPrinter As String = "Zan Image Printer(bw)"
            Dim szEnddocEvent As String = "SignalPrintDone"
            Dim strPath As String
            Dim tempstr As StringBuilder
    
            tempstr = New StringBuilder(256)
    
            Dim szDefPrinter As String
            Dim dwBufSize As Integer
            dwBufSize = tempstr.Capacity
    
            GetDefaultPrinter(tempstr, dwBufSize)
            szDefPrinter = tempstr.ToString()
    
            'change the default printer prior to calling the
            'ShellExecutePrint function.
            If String.Compare(szPrinter, szDefPrinter, True) <> 0 Then
                SetDefaultPrinter(szPrinter)
            End If
    
            strPath = GetZanConfigurationDir(szPrinter)
    
            If Not strPath.EndsWith("\") Then
                strPath = String.Concat(strPath, "\")
            End If
    
            strPath = String.Concat(strPath, "event.ini")
    
            'enable event notification
            WritePrivateProfileString("event", "enable", "1", strPath)
            'set enddoc event name
            WritePrivateProfileString("event", "enddoc", szEnddocEvent, strPath)
    
            Dim ewh As EventWaitHandle
            ewh = New EventWaitHandle(False, _
            EventResetMode.AutoReset, szEnddocEvent)
    
            'The print job status is "sent to printer" when
            'ShellExecutePrint returns.
            ShellExecutePrint("c:\abc\1.doc")
            'wait for the EndDoc event to be received,
            'an indication that the submitted print job has indeed completed
            ewh.WaitOne()
    
            'The print job status is "sent to printer" when
            'ShellExecutePrint returns.
            ShellExecutePrint("c:\abc\1.pdf")
            'wait for the EndDoc event to be received,
            'an indication that the submitted print job has indeed completed
            ewh.WaitOne()
    
            'set default printer back to original
            If String.Compare(szPrinter, szDefPrinter, True) <> 0 Then
                SetDefaultPrinter(szDefPrinter)
            End If
        End Sub
    End Module
    
    

    C# code sample:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.Threading;
    using System.IO;
    using Microsoft.Win32;
    
    
    namespace shellexec_csharp
    {
        class Program
        {
            //Determines Zan Image Printer installation directory
            static string GetZanInstallDir()
            {
                string installfolder = string.Empty;
                RegistryKey rkTest;
    
                //first check to see if the uninstall registry entry exists
                rkTest = Registry.LocalMachine.OpenSubKey(
                "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\zvprt50");
    
                if (rkTest != null)
                {
                    installfolder = rkTest.GetValue("UninstallString").ToString();
                    rkTest.Close();
    
                    if (installfolder.Length > 0)
                    {
                        installfolder = Path.GetDirectoryName(installfolder);
    
                        DirectoryInfo installdir1 = new DirectoryInfo(installfolder);
                        if (installdir1.Exists)
                        {
                            return installfolder;
                        }
                    }
                }
    
                //fallback to the \Program Files\zvprt50 folder:
                installfolder = Environment.GetFolderPath
                    (Environment.SpecialFolder.ProgramFiles);
    
                if (!installfolder.EndsWith("\\"))
                    installfolder = string.Concat(installfolder, "\\");
    
                installfolder = string.Concat(installfolder, "zvprt50");
    
                return installfolder;
            }
    
    
    
            //Determines Zan Image Printer
            //configuration directory for the ini setting files
            static string GetZanConfigurationDir(string szPrinter)
            {
                //read the OS info
                OperatingSystem os = System.Environment.OSVersion;
                string sCfg;
                uint lPolicy;
                StringBuilder tmpstr = new StringBuilder(256);
    
                //read configure.ini from
                //Zan Image Printer installation directory
                sCfg = GetZanInstallDir();
    
                if (!sCfg.EndsWith("\\"))
                    sCfg = string.Concat(sCfg, "\\");
    
                sCfg = string.Concat(sCfg, "configure.ini");
    
    
                //Read the all users (per-machine) folder policy
                //from configure.ini:
    
                //policy=1: auto detect, if Vista or newer,
                //use CSIDL_COMMON_DOCUMENTS as the
                //all users (per-machine) folder;
                //otherwise, use CSIDL_COMMON_APPDATA
                //policy=2: use CSIDL_COMMON_APPDATA
                //policy=3: use CSIDL_COMMON_DOCUMENTS
    
                lPolicy = GetPrivateProfileInt("allusersfolder", "policy",
                    1, sCfg);
    
                //handle the auto detect policy
                if (1 == lPolicy)
                {
                    //Vista and 2008: dwVerMajor>=6
                    if (os.Version.Major >= 6)
                    {
                        lPolicy = 3;
                    }
                    else
                    {
                        lPolicy = 2;
                    }
                }
    
    
                //get the all users (per-machine) folder
                //if the all users (per-machine) folder exists,
                //then this zan image printer was installed per-machine: 
                //all users share the same settings
                if (2 == lPolicy)
                {
                    //csidl = CSIDL_COMMON_APPDATA;
                    sCfg = Environment.GetFolderPath
                        (Environment.SpecialFolder.CommonApplicationData);
    
                }
                else
                {
                    //csidl = CSIDL_COMMON_DOCUMENTS;
                    SHGetFolderPath(0, CSIDL_COMMON_DOCUMENTS, 0, 0, tmpstr);
                    sCfg = tmpstr.ToString();
                }
    
                if (!sCfg.EndsWith("\\")) sCfg = string.Concat(sCfg, "\\");
                sCfg = string.Concat(sCfg, "zvprt50\\");
                sCfg = string.Concat(sCfg, szPrinter);
    
                //all users will share the same
                //settings for the printer
                DirectoryInfo tmpdir = new DirectoryInfo(sCfg);
                if (tmpdir.Exists)
                {
                    return sCfg;
                }
    
                //if the all users (per-machine) folder doesn't exist,
                //assume each user has his own settings
                //for the printer:
                sCfg = Environment.GetFolderPath
                    (Environment.SpecialFolder.ApplicationData);
    
                if (!sCfg.EndsWith("\\")) sCfg = string.Concat(sCfg, "\\");
                sCfg = string.Concat(sCfg, "zvprt50\\");
                sCfg = string.Concat(sCfg, szPrinter);
    
                return sCfg;
            }
    
    
            static void ShellExecutePrint(string myDocument)
            {
                Process myProcess = new Process();
    
                myProcess.StartInfo.FileName = myDocument;
                myProcess.StartInfo.Verb = "Print";
                myProcess.StartInfo.CreateNoWindow = true;
                myProcess.Start();
            }
    
    
            static void Main(string[] args)
            {
                string szPrinter = "Zan Image Printer(bw)";
                string szEnddocEvent = "SignalPrintDone";
                string strPath;
    
                StringBuilder tempstr = new StringBuilder(256);
                string szDefPrinter;
                int dwBufSize = tempstr.Capacity;
    
                GetDefaultPrinter(tempstr, ref dwBufSize);
                szDefPrinter = tempstr.ToString();
    
                /*
                change the default printer prior to calling the
                ShellExecutePrint function.
                */
                if (string.Compare(szPrinter, szDefPrinter, true) != 0)
                {
                    SetDefaultPrinter(szPrinter);
                }
    
                strPath = GetZanConfigurationDir(szPrinter);
    
                if (!strPath.EndsWith("\\")) strPath = string.Concat(strPath, "\\");
                strPath = string.Concat(strPath, "event.ini");
                //enable event notification
                WritePrivateProfileString("event", "enable", "1", strPath);
                //set enddoc event name
                WritePrivateProfileString("event", "enddoc", szEnddocEvent, strPath);
    
                EventWaitHandle ewh;
                ewh = new EventWaitHandle(false, EventResetMode.AutoReset, szEnddocEvent);
    
                //The print job status is "sent to printer" when
                //ShellExecutePrint returns.
                ShellExecutePrint("c:\\abc\\1.doc");
                //wait for the EndDoc event to be received,
                //an indication that the submitted print job has indeed completed
                ewh.WaitOne();
    
                //The print job status is "sent to printer" when
                //ShellExecutePrint returns.
                ShellExecutePrint("c:\\abc\\1.pdf");
                //wait for the EndDoc event to be received,
                //an indication that the submitted print job has indeed completed
                ewh.WaitOne();
    
                /*set default printer back to original*/
                if (string.Compare(szPrinter, szDefPrinter, true) != 0)
                {
                    SetDefaultPrinter(szDefPrinter);
                }
    
            }
    
            [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern bool GetDefaultPrinter(StringBuilder pszBuffer,
                ref int size);
    
            [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern bool SetDefaultPrinter(string Name);
    
            [DllImport("kernel32.dll")]
            static extern uint GetPrivateProfileString(string lpAppName,
                string lpKeyName, string lpDefault,
                StringBuilder lpReturnedString, int nSize, string lpFileName);
    
            [DllImport("kernel32.dll")]
            static extern bool WritePrivateProfileString(string lpAppName,
                                                         string lpKeyName,
                string lpString, string lpFileName);
    
            [DllImport("kernel32.dll")]
            static extern uint GetPrivateProfileInt(string lpAppName,
                string lpKeyName, int nDefault, string lpFileName);
    
    
            [DllImport("shell32.dll")]
            static extern bool SHGetFolderPath(int hwndOwner,
            int nFolder, int hToken, int dwFlags, StringBuilder pszPath);
            const int CSIDL_COMMON_DOCUMENTS = 0x002e;
        }
    }
    
    


    Return to top



    Internet Explorer automation VB, Delphi, C, VC.NET, VB.NET and C# code samples: print HTML files programmatically
    You can write an application that uses the Microsoft WebBrowser Control to print HTML files programmatically without displaying the print dialog.
    You can immediately print the current document in the WebBrowser without prompting the user for the printer dialog as follows:
    ExecWB OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER

    If you want to change the page margins, header, and footer settings, and the default Internet Explorer printer programmatically, please read the Microsoft Knowledge Base Articles Q267240 "How to print custom headers and footers for a WebBrowser control in Internet Explorer" and Q236777 "How to change print settings for Internet Explorer and the WebBrowser control programmatically in Internet Explorer".

    VB, Delphi, C/C++, VC.NET, VB.NET and C# code samples that illustrate using Internet Explorer's automation to print HTML files programmatically are shown below. The code samples will all wait for the EndDoc event to make sure that the printing is done before destroying the Internet Explorer. The code samples simply use the "SignalPrintDone" as the EndDoc event name. However, in a real application, for uniqueness, we recommend using an event name such as "Zan Image Printer(bw) SignalPrintDone" or a GUID string such as "{66A568A9-EECE-4695-BE9F-0CF85135E702}", so that it won't conflict with any other Zan Image Printer and Windows application.
    To compile the VC.NET, VB.NET and C# code samples, you first need to set a reference to the "Microsoft Internet Controls" in your project by following the steps below:
    1. In Solution Explorer, right click the project node, then click Add Reference.
    2. In the Add Reference dialog, click the COM tab.
    3. Click the "Microsoft Internet Controls", and then click Select.

    Tips:
  • In .NET 2.0, a new managed WebBrowser control is introduced.

  • You cannot quit Internet Explorer while the printing is pending.

  • In addition to web pages, you can print other browser-enabled document such as GIF, JPEG, and text file with the WebBrowser Control.

  • Microsoft Internet Explorer truncates long directory and file names. Make sure your HTML file name is short or copy the HTML file you want to print into a folder with short name.


  • VB code sample:
    Option Explicit
    
    Private Declare Sub Sleep Lib "kernel32" ( _
        ByVal dwMilliseconds As Long)
        
    Private Declare Function GetDefaultPrinter Lib "winspool.drv" _
    Alias "GetDefaultPrinterA" (ByVal pszBuffer As String, _
    pcchBuffer As Long) As Long
    
    Private Declare Function SetDefaultPrinter Lib "winspool.drv" _
    Alias "SetDefaultPrinterA" (ByVal pszPrinter As String) As Long
    
    Private Declare Function SHGetFolderPath Lib "shell32" _
    Alias "SHGetFolderPathA" _
    (ByVal hwndOwner As Long, ByVal nFolder As Long, _
    ByVal hToken As Long, ByVal dwFlags As Long, _
    ByVal pszPath As String) As Long
       
    Private Declare Function GetPrivateProfileInt Lib "kernel32.dll" _
    Alias "GetPrivateProfileIntA" _
    (ByVal lpApplicationName As String, _
    ByVal lpKeyName As String, ByVal nDefault As Integer, _
    ByVal lpFileName As String) As Integer
    
    Private Declare Function WritePrivateProfileString Lib "kernel32.dll" _
    Alias "WritePrivateProfileStringA" _
    (ByVal lpApplicationName As String, _
    ByVal lpKeyName As String, ByVal lpString As String, _
    ByVal lpFileName As String) As Integer
    
    Private Declare Function WaitForSingleObject Lib "kernel32.dll" _
    (ByVal hHandle As Long, ByVal _
    dwMilliseconds As Long) As Long
    
    Private Declare Function RegCloseKey Lib "advapi32.dll" _
    (ByVal hKey As Long) As Long
    
    Private Declare Function RegOpenKeyEx Lib "advapi32.dll" _
       Alias "RegOpenKeyExA" _
      (ByVal hKey As Long, _
       ByVal lpSubKey As String, _
       ByVal ulOptions As Long, _
       ByVal samDesired As Long, _
       phkResult As Long) As Long
    
    Private Declare Function RegQueryValueEx Lib "advapi32.dll" _
    Alias "RegQueryValueExA" (ByVal hKey As Long, _
    ByVal lpValueName As String, ByVal lpReserved As Long, _
    lpType As Long, lpData As Any, lpcbData As Long) As Long
    
    
    Private Declare Function CreateEvent Lib "kernel32" _
    Alias "CreateEventA" (ByVal lpEventAttributes As Long, _
    ByVal bManualReset As Long, ByVal bInitialState As _
    Long, ByVal lpname As String) As Long
    
    Private Declare Function CloseHandle Lib "kernel32" _
    (ByVal hObject As Long) As Long
    
    
    Private Declare Function GetVersionEx Lib "kernel32" _
       Alias "GetVersionExA" _
      (lpVersionInformation As OSVERSIONINFO) As Long
    
    
    
    Private Const HKEY_LOCAL_MACHINE = &H80000002
    'Registry action types.
    Private Const ERROR_SUCCESS = 0
    Private Const STANDARD_RIGHTS_READ As Long = &H20000
    Private Const KEY_QUERY_VALUE As Long = &H1
    Private Const KEY_ENUMERATE_SUB_KEYS As Long = &H8
    Private Const KEY_NOTIFY As Long = &H10
    Private Const SYNCHRONIZE As Long = &H100000
    Private Const KEY_READ As Long = ((STANDARD_RIGHTS_READ Or _
                                       KEY_QUERY_VALUE Or _
                                       KEY_ENUMERATE_SUB_KEYS Or _
                                       KEY_NOTIFY) And _
                                       (Not SYNCHRONIZE))
    
    
    'Used CSIDL values.
    Private Const CSIDL_APPDATA As Long = &H1A
    Private Const CSIDL_PROGRAM_FILES  As Long = &H26
    Private Const CSIDL_COMMON_APPDATA As Long = &H23
    Private Const CSIDL_COMMON_DOCUMENTS As Long = &H2E
    
    Private Const SHGFP_TYPE_CURRENT = 0
    Private Const S_OK As Long = 0
    Private Const MAX_PATH = 260
    Private Const SW_SHOWNORMAL = 1
    Private Const INFINITE = &HFFFF
    
    'Windows-defined type OSVERSIONINFO
    Private Type OSVERSIONINFO
      OSVSize         As Long
      dwVerMajor      As Long 'dwVerMajor = 6: Vista or above
      dwVerMinor      As Long
      dwBuildNumber   As Long
                                     
      PlatformID      As Long
      szCSDVersion    As String * 128
                                     
    End Type
    
    
    
    'Determines whether the given path refers to an existing
    'directory
    Function DirExists(ByVal DName As String) As Boolean
    Dim sDummy As String
    On Error Resume Next
    
    If Right(DName, 1) <> "\" Then DName = DName & "\"
    sDummy = Dir$(DName & "*.*", vbDirectory)
    DirExists = Not (sDummy = "")
    End Function
    
    
    'Searches a path for a file name
    Function GetFilePath(FileName As String) As String
        Dim i As Long
        For i = Len(FileName) To 1 Step -1
            Select Case Mid$(FileName, i, 1)
                Case ":"
                    GetFilePath = Left$(FileName, i)
                    Exit For
                Case "\"
                    GetFilePath = Left$(FileName, i - 1)
                    Exit For
            End Select
        Next
    End Function
    
    
    'Determines Zan Image Printer installation directory
    Private Function GetZanInstallDir() As String
    
    Dim sPath As String
    Dim szTmp As String * MAX_PATH
    Dim lResult As Long
    Dim hKey, dwSize As Long
    
    
    dwSize = MAX_PATH
    
    'first check to see if the uninstall registry entry exists
    If RegOpenKeyEx(HKEY_LOCAL_MACHINE, _
    "\Software\Microsoft\Windows\CurrentVersion\Uninstall\zvprt50" _
          , 0&, KEY_READ, hKey) = ERROR_SUCCESS Then
          If RegQueryValueEx(hKey, "UninstallString", _
          0&, 0&, ByVal szTmp, dwSize) = ERROR_SUCCESS Then
          
          sPath = Left$(szTmp, _
                InStr(szTmp, vbNullChar) - 1)
    
          sPath = GetFilePath(sPath)
          
          If DirExists(sPath) Then
          GetZanInstallDir = sPath
          Exit Function
          End If
          
          End If
          
    End If
         
    'fallback to the \Program Files\zvprt50 folder:
    lResult = SHGetFolderPath(0, _
                       CSIDL_PROGRAM_FILES, _
                       0, _
                       SHGFP_TYPE_CURRENT, _
                       szTmp)
                       
    sPath = Left$(szTmp, _
                InStr(szTmp, vbNullChar) - 1)
                
    If Right$(sPath, 1) <> "\" Then
        sPath = sPath & "\"
     End If
     sPath = sPath & "zvprt50"
     GetZanInstallDir = sPath
    End Function
    
    
    
    'Determines Zan Image Printer
    'configuration directory for the ini setting files
    Private Function GetZanConfigurationDir(szPrinter As String) As String
       Dim sPath As String * MAX_PATH
       Dim lResult As Long
       Dim lPolicy As Long
       Dim csidl As Long
       Dim osv As OSVERSIONINFO
       Dim LRet As Long
       Dim sCfg As String
    
       'read the OS info
       osv.OSVSize = Len(osv)
       LRet = GetVersionEx(osv)
       
       'read configure.ini from
       'Zan Image Printer installation directory
       sCfg = GetZanInstallDir()
    
       If Right$(sCfg, 1) <> "\" Then
        sCfg = sCfg & "\"
       End If
       sCfg = sCfg & "configure.ini"
    
       
       'Read the all users (per-machine) folder policy
       'from configure.ini:
       
       'policy=1: auto detect, if Vista or newer,
       'use CSIDL_COMMON_DOCUMENTS as the
       'all users (per-machine) folder;
       'otherwise, use CSIDL_COMMON_APPDATA
       'policy=2: use CSIDL_COMMON_APPDATA
       'policy=3: use CSIDL_COMMON_DOCUMENTS
       
    
       lPolicy = GetPrivateProfileInt("allusersfolder", "policy", _
       1, sCfg)
       
       'handle the auto detect policy
       If lPolicy = 1 Then
         'Vista and 2008: dwVerMajor>=6
         If osv.dwVerMajor >= 6 Then
         lPolicy = 3
         Else
         lPolicy = 2
         End If
       End If
       
       If lPolicy = 2 Then
       csidl = CSIDL_COMMON_APPDATA
       Else
       csidl = CSIDL_COMMON_DOCUMENTS
       End If
        
       
       'get the all users (per-machine) folder
       lResult = SHGetFolderPath(0, _
                       csidl, _
                       0, _
                       SHGFP_TYPE_CURRENT, _
                       sPath)
                       
       sCfg = Left$(sPath, _
                InStr(sPath, vbNullChar) - 1)
                
       If Right$(sCfg, 1) <> "\" Then
        sCfg = sCfg & "\"
       End If
       sCfg = sCfg & "zvprt50\" & szPrinter
       
       'if the all users (per-machine) folder exists,
       'then this zan image printer was installed per-machine:
       'all users share the same settings
       If DirExists(sCfg) Then
       'all users will share the same
       'settings for the printer
       GetZanConfigurationDir = sCfg
       Exit Function
       End If
       
       'if the all users (per-machine) folder doesn't exist,
       'assume each user has his own settings
       'for the printer:
       lResult = SHGetFolderPath(0, _
                       CSIDL_APPDATA, _
                       0, _
                       SHGFP_TYPE_CURRENT, _
                       sPath)
                       
       sCfg = Left$(sPath, _
                InStr(sPath, vbNullChar) - 1)
                
       If Right$(sCfg, 1) <> "\" Then
        sCfg = sCfg & "\"
       End If
       sCfg = sCfg & "zvprt50\" & szPrinter
       
       GetZanConfigurationDir = sCfg
    End Function
    
    
    
    
    Public Sub printhtml(szPrinter As String, htmlfile As String)
      Const OLECMDID_PRINT = 6
      Const OLECMDEXECOPT_DONTPROMPTUSER = 2
      Const OLECMDEXECOPT_PROMPTUSER = 1
      Dim IE
      Dim szDefPrinter As String, lLen As Long
      Dim sNameBuff As String
      Dim szEnddocEvent, strPath As String
      Dim hEndDoc As Long
      Dim i As Long
    
      szEnddocEvent = "SignalPrintDone"
     
      hEndDoc = CreateEvent(ByVal 0&, False, False, szEnddocEvent)
    
      'remember current default printer
      GetDefaultPrinter vbNullChar, lLen
      sNameBuff = Space$(lLen)
      GetDefaultPrinter sNameBuff, lLen
      szDefPrinter = Left$(sNameBuff, _
                      InStr(sNameBuff, vbNullChar) - 1)
                      
      szDefPrinter = LCase(szDefPrinter)
      szPrinter = LCase(szPrinter)
                      
      'change the default printer prior to calling the
      'ExecWB function.
      If szDefPrinter <> Trim$(szPrinter) Then
      SetDefaultPrinter szPrinter
      End If
      
      
      strPath = GetZanConfigurationDir(szPrinter)
      If Right$(strPath, 1) <> "\" Then
        strPath = strPath & "\"
      End If
    
      strPath = strPath & "event.ini"
     
      'enable event notification
      WritePrivateProfileString "event", "enable", _
       "1", strPath
    
      'set enddoc event name
      WritePrivateProfileString "event", "enddoc", _
      szEnddocEvent, strPath
      
      'IE automation via Microsoft WebBrowser control
      Set IE = CreateObject("InternetExplorer.Application")
      
      IE.Visible = True
      IE.Navigate htmlfile
    
      'Wait until URL navigation is done
      Do While IE.ReadyState <> 4
        Sleep 250
      Loop
      
      
      
      'The print job status is "sent to printer" when
      'ExecWB returns
      IE.ExecWB OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER
      
      'wait for the EndDoc event to be received,
      'an indication that the submitted print job
      'has indeed completed
      i = WaitForSingleObject(hEndDoc, INFINITE)
      
      IE.Quit
      Set IE = Nothing
      
      'set default printer back to original
      If szDefPrinter <> Trim$(szPrinter) Then
      SetDefaultPrinter szDefPrinter
      End If
      CloseHandle (hEndDoc)
    End Sub
    
    
    
    Public Sub Main()
    printhtml "zan image printer(bw)", "C:\htmlfiles\document.htm"
    End Sub
    
    
    Delphi code sample:
    unit zanprinter;
    
    interface
    
    uses
    Windows, Messages, SysUtils, ShlObj, ShellAPI, SHFolder, ComObj;
    
    function GetDefaultPrinter(prnName:PAnsiChar; var bufSize:DWORD):
    BOOL; stdcall; external 'winspool.drv' name 'GetDefaultPrinterA';
    
    function SetDefaultPrinter(prnName:PAnsiChar):
    BOOL; stdcall; external 'winspool.drv' name 'SetDefaultPrinterA';
    
    procedure GetZanInstallDir(var APath: String);
    procedure printhtml(szPrinter:String; htmlfile:String);
    procedure GetZanConfigurationDir(var szPrinter: String; var cfgdir: String);
    
    implementation
    
    //Determines Zan Image Printer installation directory
    procedure GetZanInstallDir(var APath: String);
    var
      hkeyStartup: HKEY;
      dwSize: DWORD;
    begin
      dwSize := MAX_PATH;
      SetLength(APath, MAX_PATH);
    
      //first check to see if the uninstall registry entry exists
      if RegOpenKeyEx(HKEY_LOCAL_MACHINE,
       '\Software\Microsoft\Windows\CurrentVersion\Uninstall\zvprt50',
       0,
       KEY_READ,
       hkeyStartup) = ERROR_SUCCESS then
       begin
    
       if RegQueryValueEx(hkeyStartup,
                         'UninstallString', nil, nil,
                          PBYTE(Pchar(APath)),
                          @dwSize) = ERROR_SUCCESS then
       begin
          APath := String (PChar(APath));
          APath := ExtractFilePath(APath);
       end;
    
       //Close the Key, we won't be needing it anymore
       RegCloseKey(hkeyStartup);
    
       if DirectoryExists(APath) then Exit;
      end;
    
      //fallback to the \Program Files\zvprt50 folder:
      SHGetFolderPath(0, CSIDL_PROGRAM_FILES, 0, 0,
                      PChar(APath));
    
      APath := String (PChar (APath));
      if (APath[Length(APath)] <> '\')
      then APath := APath + '\';
    
      APath := APath + 'zvprt50';
    end;
    
    
    //Determines Zan Image Printer
    //configuration directory for the ini setting files
    procedure GetZanConfigurationDir(var szPrinter: String; var cfgdir: String);
    var
      osv: TOSVersionInfo;
      lPolicy, csidl: Integer;
    begin
      SetLength(cfgdir, MAX_PATH);
    
      //read the OS info
      FillChar(osv, SizeOf(osv), 0);
      osv.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
      GetVersionEx(osv);
    
      //read configure.ini from
      //Zan Image Printer installation directory
      GetZanInstallDir(cfgdir);
      if (cfgdir[Length(cfgdir)] <> '\') then cfgdir := cfgdir + '\';
      cfgdir := cfgdir + 'configure.ini';
    
      //read configure.ini from
      //Zan Image Printer installation directory.
      //Read the all users (per-machine) folder policy
      //from configure.ini:
    
      //policy=1: auto detect, if Vista or newer,
      //use CSIDL_COMMON_DOCUMENTS as the
      //all users (per-machine) folder;
      //otherwise, use CSIDL_COMMON_APPDATA
      //policy=2: use CSIDL_COMMON_APPDATA
      //policy=3: use CSIDL_COMMON_DOCUMENTS
      lPolicy := GetPrivateProfileInt('allusersfolder', 'policy',
       1, PChar(cfgdir));
    
      //handle the auto detect policy
      if lPolicy = 1 then
      begin
         //Vista and 2008: dwVerMajor>=6
         if osv.dwMajorVersion >= 6 then lPolicy := 3
         else  lPolicy := 2;
      end;
    
      if lPolicy = 2 then  csidl := CSIDL_COMMON_APPDATA
      else  csidl := CSIDL_COMMON_DOCUMENTS;
    
      //get the all users (per-machine) folder
      SetLength(cfgdir, MAX_PATH);
      SHGetFolderPath(0, csidl, 0, 0, PChar(cfgdir));
      cfgdir := String (PChar (cfgdir));
      if (cfgdir[Length(cfgdir)] <> '\') then cfgdir := cfgdir + '\';
      cfgdir := cfgdir + 'zvprt50\' + szPrinter;
    
      //if the all users (per-machine) folder exists,
      //then this zan image printer was installed per-machine:
      //all users share the same settings
      if DirectoryExists(cfgdir) then Exit;
    
      //if the all users (per-machine) folder doesn't exist,
      //assume each user has his own settings
      //for the printer:
      SHGetFolderPath(0, CSIDL_APPDATA, 0, 0, PChar(cfgdir));
      cfgdir := String (PChar (cfgdir));
      if (cfgdir[Length(cfgdir)] <> '\') then cfgdir := cfgdir + '\';
      cfgdir := cfgdir + 'zvprt50\' + szPrinter;
    end;
    
    
    
    procedure printhtml(szPrinter:String; htmlfile:String);
    const
      OLECMDID_PRINT = $00000006;
      OLECMDEXECOPT_DONTPROMPTUSER = $00000002;
    var
      ie: Variant;
      szDefPrinter, szEnddocEvent, strPath: String;
      lBufSize: DWord;
      hEndDoc: THandle;
    begin
    
      //remember current default printer
      SetLength(szDefPrinter, MAX_PATH);
      lBufSize := MAX_PATH;
      GetDefaultPrinter(Pchar(szDefPrinter), lBufSize);
      szDefPrinter := String (PChar(szDefPrinter));
      szDefPrinter := LowerCase(szDefPrinter);
      szPrinter := LowerCase(szPrinter);
    
      //change the default printer prior to calling the
      //ExecWB function.
      if szDefPrinter <> szPrinter then
        SetDefaultPrinter(PChar(szPrinter));
    
      szEnddocEvent := 'SignalPrintDone';
      hEndDoc := CreateEvent(nil,False,False,Pchar(szEnddocEvent));
    
      GetZanConfigurationDir(szPrinter, strPath);
      if (strPath[Length(strPath)] <> '\')
      then  strPath := strPath + '\';
      strPath :=strPath + 'event.ini';
    
      //enable event notification
      WritePrivateProfileString('event','enable','1',Pchar(strPath));
      //set enddoc event name
      WritePrivateProfileString('event', 'enddoc',
      Pchar(szEnddocEvent), Pchar(strPath));
    
      //IE automation via Microsoft WebBrowser control
      ie := CreateOleObject('InternetExplorer.Application');
    
      ie.Visible := True;
      ie.Navigate(htmlfile);
      //Wait until URL navigation is done
      while ie.ReadyState <> 4 do
        sleep(250);
    
      //The print job status is "sent to printer" when
      //ExecWB returns
      ie.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER);
    
      //wait for the EndDoc event to be received,
      //an indication that the submitted print
      //job has indeed completed
      WaitForSingleObject(hEndDoc, INFINITE);
    
      ie.quit;
    
      //set default printer back to original
      if szDefPrinter <> szPrinter then
      SetDefaultPrinter(pchar(szDefPrinter));
    
      CloseHandle(hEndDoc);
     end;
    
    end.
    
    C++ code sample:
    #include <windows.h>
    #include <winspool.h>
    #include <shlobj.h>
    #include <shlwapi.h>
    #include <shellapi.h>
    
    /*#import statement and smart pointers*/
    #import  <shdocvw.dll>
    
    #pragma comment(lib, "shlwapi.lib")
    
    
    //Determines whether the given path refers to 
    //an existing directory
    BOOL IsFolderExists(char *lpDirectoryName)
    {
    	if(0 == strlen(lpDirectoryName))
    	{
    		return FALSE;
    	}
    
    	DWORD dwFileAttr = GetFileAttributes(lpDirectoryName);
    
    	if((dwFileAttr != 0xFFFFFFFF) &&
    		(dwFileAttr & FILE_ATTRIBUTE_DIRECTORY))
    	{
    		return TRUE;
    	}
    	else
    	{
    		return FALSE;
    	}
    }
    
    
    
    //Determines Zan Image Printer installation directory
    void GetZanInstallDir(char *installfolder)
    {
    	HKEY hkeyStartup;
    
    	//first check to see if the uninstall registry entry exists
    	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
    		"\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\zvprt50",
    		0,          
    		KEY_READ,  
    		&hkeyStartup) == ERROR_SUCCESS)
    	{
    		DWORD dwSize = MAX_PATH;
    
    		if(RegQueryValueEx(hkeyStartup, 
    			"UninstallString", 
    			NULL,
    			NULL,
    			(LPBYTE)installfolder,
    			&dwSize) == ERROR_SUCCESS)
    		{
    			PathRemoveFileSpec(installfolder);
    			PathAddBackslash(installfolder);
    		}
    
    		/*Close the Key, we won't be needing it anymore*/
    		RegCloseKey(hkeyStartup);
    
    		if(IsFolderExists(installfolder))
    		{
    			return;
    		}
    	}
    
    	//fallback to the \Program Files\zvprt50 folder:
    	SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, 0, installfolder);
    	PathAddBackslash(installfolder);
    
    	strcat(installfolder,"zvprt50");
    }
    
    
    
    BOOL IsVistaOrAbove(void)
    {
    	OSVERSIONINFOEX osvi;
    	BOOL bOsVersionInfoEx;
    
    	ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
    
    	//Try calling GetVersionEx using the OSVERSIONINFOEX structure.
    	//If that fails, try using the OSVERSIONINFO structure.
    	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    	if(!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*)&osvi)))
    	{
    		osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    		if(!GetVersionEx((OSVERSIONINFO*)&osvi))
    			return FALSE;
    	}
    
    	//vista and 2008: 6
    	//2003: 5
    	//xp: 5
    	if(osvi.dwMajorVersion >= 6)
    	{
    		return TRUE;
    	}
    	else
    	{
    		return FALSE;
    	}
    }
    
    
    
    //Determines Zan Image Printer
    //configuration directory for the ini setting files
    void GetZanConfigurationDir(char *sPrinter, char *sCfg)
    {
    	DWORD lPolicy;
    	DWORD csidl;
    
    	//read configure.ini from
    	//Zan Image Printer installation directory
    	GetZanInstallDir(sCfg);
    	PathAddBackslash(sCfg);
    	strcat(sCfg,"configure.ini");
    
    	//Read the all users (per-machine) folder policy
    	//from configure.ini:
    
    	//policy=1: auto detect, if Vista or newer,
    	//use CSIDL_COMMON_DOCUMENTS as the
    	//all users (per-machine) folder;
    	//otherwise, use CSIDL_COMMON_APPDATA
    	//policy=2: use CSIDL_COMMON_APPDATA
    	//policy=3: use CSIDL_COMMON_DOCUMENTS
    
    	lPolicy = GetPrivateProfileInt("allusersfolder", 
    		"policy", 1, sCfg);
    
    	//handle the auto detect policy
    	if(1 == lPolicy)
    	{
    		if(IsVistaOrAbove())  lPolicy = 3;
    		else lPolicy = 2;
    	}
    
    
    	if(2 == lPolicy)
    	{
    		csidl = CSIDL_COMMON_APPDATA;
    	}
    	else
    	{
    		csidl = CSIDL_COMMON_DOCUMENTS;
    	}
    
    	//get the all users (per-machine) folder
    	SHGetFolderPath(NULL, csidl, NULL, 0, sCfg);
    	PathAddBackslash(sCfg);
    	strcat(sCfg, "zvprt50\\");
    	strcat(sCfg, sPrinter);
    		
    
    	//if the all users (per-machine) folder exists,
    	//this zan image printer was installed per-machine: 
    	//all users share the same settings
    	if(IsFolderExists(sCfg)) return;
    
    
    	//if the all users (per-machine) folder doesn't exist,
    	//assume each user has his own settings
    	//for the printer:
    	SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, sCfg);
    	PathAddBackslash(sCfg);
    	strcat(sCfg, "zvprt50\\");
    	strcat(sCfg, sPrinter);
    }
    
    
    
    
    void printhtml(char *printername, char *htmlfile)
    {
    	char olddefprinter[MAX_PATH] = "";
    	DWORD dwcchBufLen = MAX_PATH;
    
    	/*remember current default printer*/
    	GetDefaultPrinter(olddefprinter, &dwcchBufLen);
    
    	/*
    	change the default printer prior to calling the
    	ExecWB function.
    	*/
    	if(strlen(olddefprinter) 
    		&& strcmpi(olddefprinter, printername)
    		)
    	{
    		/*set default printer*/
    		SetDefaultPrinter(printername);
    	}
    
    	//enddoc event name
    	char* szEnddocEvent = "SignalPrintDone";
    	HANDLE hEndDoc;
    
    	hEndDoc=CreateEvent(NULL, FALSE, FALSE, szEnddocEvent);
    	if(hEndDoc == NULL)
    	{
    		return;
    	}
    
    	char  strPath[MAX_PATH];
    
    	GetZanConfigurationDir(printername, strPath);
    	PathAddBackslash(strPath);
    	strcat(strPath,"event.ini");
    
    	//enable event notification
    	WritePrivateProfileString("event", "enable", "1",strPath);
    	//set enddoc event name
    	WritePrivateProfileString("event", "enddoc", 
    		szEnddocEvent, strPath);
    
    	/*IE automation via Microsoft WebBrowser control*/
    	
    	/*CoInitialize(0) creates a single-threaded apartment*/ 
    	/*CoInitialize(0);*/
    	
    	/*Need to define _WIN32_DCOM preprocessor symbol in your project settings*/
    	/*CoInitializeEx with the COINIT_MULTITHREADED flag 
    	produces a multi-threaded apartment 
    	*/
    	CoInitializeEx(NULL, COINIT_MULTITHREADED);
    	{
    		/*IE Automation*/
    		SHDocVw::IWebBrowser2Ptr pIE(__uuidof(SHDocVw::InternetExplorer));
    
    		pIE->Visible = false;
    		pIE->Navigate(htmlfile);
    
    		/*Wait until URL navigation is done*/
    		//120 seconds
            DWORD nTimeout = 120*1000;
    		
    		READYSTATE result;
    		DWORD nFirstTick = GetTickCount();
    		
    		do
    		{
    			pIE->get_ReadyState(&result);
    			
    			if(result != READYSTATE_COMPLETE)
    				Sleep(250);
    			
    			if(nTimeout > 0)
    			{
    				if((GetTickCount() - nFirstTick) > nTimeout)
    				{
    				   break;
    				}
    			}
    		}while (result != READYSTATE_COMPLETE);
    		
    
    		VARIANT vNull; 
    		vNull.vt = VT_EMPTY; 
    
    		//The print job status is "sent to printer" when
    		//ExecWB returns.
    		HRESULT hr = pIE->ExecWB(OLECMDID_PRINT, 
    			OLECMDEXECOPT_DONTPROMPTUSER, &vNull, &vNull); 
    
    		//wait for the EndDoc event to be received,
    		//an indication that the submitted print job has indeed completed
    		WaitForSingleObject(hEndDoc, INFINITE);
    
    		pIE->Quit();
    	}
    	CoUninitialize();
    
    	/*set default printer back to original*/
    	if(strlen(olddefprinter) 
    		&& strcmpi(olddefprinter, printername)
    		)
    	{
    		SetDefaultPrinter(olddefprinter);
    	}
    	CloseHandle(hEndDoc);
    }
    
    
    
    int main(int argc, char* argv[])
    {
    
    	printhtml("zan image printer(bw)", "c:\\htmlfiles\\document.htm");
    
    	return 0;
    }
    
    

    VC.NET code sample:
    using namespace System;
    using namespace System::Text;
    using namespace System::Runtime::InteropServices;
    using namespace System::Threading;
    using namespace Microsoft::Win32;
    using namespace System::IO;
    using namespace System::Diagnostics;
    using namespace SHDocVw;
    
    // Declare the function that is exported from unmanaged dll:
    [DllImport("winspool.drv")]
    extern "C" bool _cdecl GetDefaultPrinter(
    	 StringBuilder^ pszBuffer, int *size);
    
    [DllImport("winspool.drv")]
    extern "C" bool _cdecl SetDefaultPrinter(
    	 String^ pszPrinter);
    
    [DllImport("KERNEL32.DLL")]
    extern "C" int _cdecl GetPrivateProfileString(
       String^ lpAppName, 
       String^ lpKeyName,
       String^ lpDefault, 
       StringBuilder^ lpReturnedString, 
       int nSize,
       String^ lpFileName);
    
    [DllImport("KERNEL32.DLL")]
    extern "C" bool _cdecl WritePrivateProfileString(
       String^ lpAppName, 
       String^ lpKeyName,
       String^ lpString, 
       String^ lpFileName);
    
    [DllImport("KERNEL32.DLL")]
    extern "C" int _cdecl GetPrivateProfileInt(
       String^ lpAppName, 
       String^ lpKeyName,
       int nDefault, 
       String^ lpFileName);
    
    [DllImport("shell32.dll")]
    extern "C" bool _cdecl SHGetFolderPath(int hwndOwner,
    int nFolder, int hToken, int dwFlags, StringBuilder^ pszPath);
    const int CSIDL_COMMON_DOCUMENTS = 0x002e;
    
    
    
    //Determines Zan Image Printer installation directory
    String^ GetZanInstallDir(void)
    {
    	String^ installfolder = String::Empty;
    	RegistryKey ^ rkTest;
    
    	//first check to see if the uninstall registry entry exists
    	rkTest = Registry::LocalMachine->OpenSubKey(
    		L"\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\zvprt50");
    	if(rkTest)
    	{
    		installfolder = rkTest->GetValue(L"UninstallString")->ToString();
    		rkTest->Close();
    
    		if(installfolder->Length)
    		{
    			installfolder = Path::GetDirectoryName(installfolder);
    
    			DirectoryInfo^ installdir1=gcnew DirectoryInfo(installfolder);
    			if(installdir1->Exists)
    			{
    				return installfolder;
    			}
    		}
    	}
    
    	//fallback to the \Program Files\zvprt50 folder:
    	installfolder = Environment::GetFolderPath
    		(Environment::SpecialFolder::ProgramFiles);
    
    	if(!installfolder->EndsWith(L"\\")) 
    		installfolder = String::Concat(installfolder, L"\\");
    
    	installfolder=String::Concat(installfolder, L"zvprt50");
    
    	return installfolder;
    }
    
    
    //Determines Zan Image Printer
    //configuration directory for the ini setting files
    String^ GetZanConfigurationDir(String^ szPrinter)
    {
    	//read the OS info
    	OperatingSystem^ os = System::Environment::OSVersion;
    	String^ sCfg;
    	int lPolicy;
    	StringBuilder^ tmpstr = gcnew StringBuilder(256);
    
    	//read configure.ini from
    	//Zan Image Printer installation directory
    	sCfg = GetZanInstallDir();
    
    	if(!sCfg->EndsWith(L"\\")) 
    		sCfg = String::Concat(sCfg, L"\\");
    
    	sCfg = String::Concat(sCfg, L"configure.ini");
    
    
    	//Read the all users (per-machine) folder policy
    	//from configure.ini:
    
    	//policy=1: auto detect, if Vista or newer,
    	//use CSIDL_COMMON_DOCUMENTS as the
    	//all users (per-machine) folder;
    	//otherwise, use CSIDL_COMMON_APPDATA
    	//policy=2: use CSIDL_COMMON_APPDATA
    	//policy=3: use CSIDL_COMMON_DOCUMENTS
    
    	lPolicy = GetPrivateProfileInt(L"allusersfolder", L"policy",
    		1, sCfg);
    
    	//handle the auto detect policy
    	if(1 == lPolicy)
    	{
    		//Vista and 2008: dwVerMajor>=6
    		if(os->Version->Major >= 6)
    		{
    			lPolicy = 3;
    		}
    		else
    		{
    			lPolicy = 2;
    		}
    	}
    
    
    	//get the all users (per-machine) folder
    	//if the all users (per-machine) folder exists,
    	//then this zan image printer was installed per-machine: 
    	//all users share the same settings
    	if(2 == lPolicy)
    	{
    		//csidl = CSIDL_COMMON_APPDATA;
    		sCfg = Environment::GetFolderPath
    			(Environment::SpecialFolder::CommonApplicationData);
    
    	}
    	else
    	{
    		//csidl = CSIDL_COMMON_DOCUMENTS;
    		SHGetFolderPath(0, CSIDL_COMMON_DOCUMENTS, 0, 0, tmpstr);
    		sCfg = tmpstr->ToString();
    	}
    
    	if(!sCfg->EndsWith(L"\\")) sCfg = String::Concat(sCfg, L"\\");
    	sCfg = String::Concat(sCfg, L"zvprt50\\");
    	sCfg = String::Concat(sCfg, szPrinter);
    
    	//all users will share the same
    	//settings for the printer
    	DirectoryInfo^ tmpdir = gcnew DirectoryInfo(sCfg);
    	if(tmpdir->Exists)
    	{
    		return sCfg;
    	}
    
    	//if the all users (per-machine) folder doesn't exist,
    	//assume each user has his own settings
    	//for the printer:
    	sCfg = Environment::GetFolderPath
    		(Environment::SpecialFolder::ApplicationData);
    
    	if(!sCfg->EndsWith(L"\\")) sCfg = String::Concat(sCfg, L"\\");
    	sCfg = String::Concat(sCfg, L"zvprt50\\");
    	sCfg = String::Concat(sCfg, szPrinter);
    
    	return sCfg;
    }
    
    
    
    
    
    void printhtml(String^ szPrinter, String^ htmlfile)
    {
    	StringBuilder^ tmpstr = gcnew StringBuilder(256);
    	String^ szDefPrinter;
    	int dwBufSize = tmpstr->Capacity;
    
    	/*
    	change the default printer prior to calling the
    	ExecWB function.
    	*/
    	GetDefaultPrinter(tmpstr, &dwBufSize);
    	szDefPrinter = tmpstr->ToString();
    
    	if(String::Compare(szPrinter, szDefPrinter, true) != 0)
    	{
    		SetDefaultPrinter(szPrinter);
    	}
    
    	//enddoc event name
    	String^ szEnddocEvent = L"SignalPrintDone";
    	String^ strPath;
    
    	strPath = GetZanConfigurationDir(szPrinter);
    
    	if(!strPath->EndsWith(L"\\")) strPath=String::Concat(strPath, L"\\");
    	strPath = String::Concat(strPath, L"event.ini");
    
    	//enable event notification
    	WritePrivateProfileString(L"event", L"enable", L"1", strPath);
    	//set enddoc event name
    	WritePrivateProfileString(L"event",L"enddoc",szEnddocEvent, strPath);
    
    	EventWaitHandle^ ewh;
    	ewh=gcnew EventWaitHandle(false,EventResetMode::AutoReset,szEnddocEvent);
    
    	InternetExplorer^ explorer = gcnew InternetExplorerClass;
    	IWebBrowserApp^ webBrowser = explorer;
    	Object^ noValue = System::Reflection::Missing::Value;
    
    	webBrowser->Visible = true;
    	webBrowser->Navigate(htmlfile, noValue, noValue, noValue, noValue);
    
    	/*Wait until URL navigation is done*/
    	while(webBrowser->Busy)
    	{
    		Thread::Sleep(250);
    	}
    
    	//The print job status is "sent to printer" when
    	//ExecWB returns.
    	explorer->ExecWB(SHDocVw::OLECMDID::OLECMDID_PRINT,
    		SHDocVw::OLECMDEXECOPT::OLECMDEXECOPT_DONTPROMPTUSER, 
    		noValue,
    		noValue);
    
    	//wait for the EndDoc event to be received,
    	//an indication that the submitted print job has 
    	//indeed completed
    	ewh->WaitOne();
    
    	explorer->Quit();
    
    	/*set default printer back to original*/
    	if(String::Compare(szPrinter, szDefPrinter, true) != 0)
    	{
    		SetDefaultPrinter(szDefPrinter);
    	}
    }
    
    
    
    
    int main(array ^args)
    {
    	printhtml(L"zan image printer(bw)", L"c:\\htmlfiles\\document.htm");
    
    	return 0;
    }
    
    


    VB.NET code sample:
    Imports System
    Imports System.Runtime.InteropServices
    Imports System.Text
    Imports System.IO
    Imports System.Diagnostics
    Imports System.Threading
    Imports Microsoft.Win32
    Imports SHDocVw
    
    
    Module Module1
        Declare Function GetDefaultPrinter Lib "winspool.drv" Alias _
        "GetDefaultPrinterA" (ByVal pszBuffer As System.Text.StringBuilder, _
        ByRef size As Int32) As Boolean
    
        Declare Function SetDefaultPrinter Lib "winspool.drv" Alias _
        "SetDefaultPrinterA" (ByVal pszPrinter As String) As Boolean
    
        Private Declare Function GetPrivateProfileString Lib "kernel32" _
             Alias "GetPrivateProfileStringW" _
            (ByVal lpAppName As String, _
             ByVal lpKeyName As String, _
             ByVal lpDefault As String, _
             ByVal lpReturnedString As StringBuilder, _
             ByVal nSize As Integer, _
             ByVal lpFileName As String) As Integer
    
        Private Declare Function GetPrivateProfileInt Lib "kernel32.dll" _
                Alias "GetPrivateProfileIntA" _
               (ByVal lpApplicationName _
                As String, ByVal lpKeyName As String, ByVal nDefault As _
                Integer, ByVal lpFileName As String) As Integer
    
        Private Declare Function WritePrivateProfileString Lib "kernel32.dll" _
                Alias "WritePrivateProfileStringA" _
               (ByVal lpAppName As String, _
                ByVal lpKeyName As String, _
                ByVal lpString As String, _
                ByVal lpFileName As String) As Boolean
    
        Private Declare Function SHGetFolderPath Lib "shell32.dll" _
        Alias "SHGetFolderPathA" _
        (ByVal hwndOwner As Integer, _
        ByVal nFolder As Integer, _
        ByVal hToken As Integer, _
        ByVal dwFlags As Integer, _
        ByVal pszPath As StringBuilder) As Integer
    
        'All Users\Documents 
        Private Const CSIDL_COMMON_DOCUMENTS = &H2E
    
    
        'Determines Zan Image Printer installation directory
        Function GetZanInstallDir() As String
            Dim installfolder As String
            Dim rkTest As RegistryKey
    
            'first check to see if the uninstall registry entry exists
            rkTest = Registry.LocalMachine.OpenSubKey _
     ("SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\zvprt50")
    
            If Not (rkTest Is Nothing) Then
                installfolder = rkTest.GetValue _
                  ("UninstallString").ToString()
                rkTest.Close()
                If (installfolder.Length > 0) Then
                    installfolder = Path.GetDirectoryName(installfolder)
                    Dim installdir1 As DirectoryInfo = _
                       New DirectoryInfo(installfolder)
    
                    If installdir1.Exists Then
                        Return installfolder
                    End If
                End If
            End If
            'fallback to the \Program Files\zvprt50 folder:
            installfolder = Environment.GetFolderPath _
    (Environment.SpecialFolder.ProgramFiles)
    
            If Not installfolder.EndsWith("\") Then
                installfolder = String.Concat(installfolder, "\")
            End If
    
            installfolder = String.Concat(installfolder, "zvprt50")
            Return installfolder
        End Function
    
    
        'Determines Zan Image Printer
        'configuration directory for the ini setting files
        Function GetZanConfigurationDir(ByVal szPrinter As String) As String
            'read the OS info
            Dim os As OperatingSystem
            Dim sCfg As String
            Dim lPolicy As Integer
            Dim tmpstr As StringBuilder
    
            tmpstr = New StringBuilder(256)
    
            os = System.Environment.OSVersion
    
            'read configure.ini from
            'Zan Image Printer installation directory
            sCfg = GetZanInstallDir()
    
            If Not sCfg.EndsWith("\") Then
                sCfg = String.Concat(sCfg, "\")
            End If
    
            sCfg = String.Concat(sCfg, "configure.ini")
    
    
            'Read the all users (per-machine) folder policy
            'from configure.ini:
    
            'policy=1: auto detect, if Vista or newer,
            'use CSIDL_COMMON_DOCUMENTS as the
            'all users (per-machine) folder;
            'otherwise, use CSIDL_COMMON_APPDATA
            'policy=2: use CSIDL_COMMON_APPDATA
            'policy=3: use CSIDL_COMMON_DOCUMENTS
    
            lPolicy = GetPrivateProfileInt("allusersfolder", _
                "policy", 1, sCfg)
    
            'Vista and 2008: dwVerMajor>=6
            If lPolicy = 1 Then
                If os.Version.Major >= 6 Then
                    lPolicy = 3
                Else
                    lPolicy = 2
                End If
            End If
    
    
            'get the all users (per-machine) folder
            'if the all users (per-machine) folder exists,
            'then this zan image printer was installed per-machine: 
            'all users share the same settings
            If lPolicy = 2 Then
                'csidl = CSIDL_COMMON_APPDATA;
                sCfg = Environment.GetFolderPath( _
                Environment.SpecialFolder.CommonApplicationData)
            Else
                'csidl = CSIDL_COMMON_DOCUMENTS;
                SHGetFolderPath(0, CSIDL_COMMON_DOCUMENTS, 0, 0, tmpstr)
                sCfg = tmpstr.ToString()
            End If
    
    
            If Not sCfg.EndsWith("\") Then
                sCfg = String.Concat(sCfg, "\")
            End If
            sCfg = String.Concat(sCfg, "zvprt50\")
            sCfg = String.Concat(sCfg, szPrinter)
    
            'all users will share the same
            'settings for the printer
            Dim tmpdir As DirectoryInfo = _
                       New DirectoryInfo(sCfg)
    
            If tmpdir.Exists Then
                Return sCfg
            End If
    
            'if the all users (per-machine) folder doesn't exist,
            'assume each user has his own settings
            'for the printer:
            sCfg = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
    
            If Not sCfg.EndsWith("\") Then
                sCfg = String.Concat(sCfg, "\")
            End If
            sCfg = String.Concat(sCfg, "zvprt50\")
            sCfg = String.Concat(sCfg, szPrinter)
    
            Return sCfg
        End Function
    
    
    
    
        Sub printhtml(ByVal szPrinter As String, ByVal htmlfile As String)
            Dim szEnddocEvent As String = "SignalPrintDone"
            Dim strPath As String
            Dim tmpstr As StringBuilder
    
            tmpstr = New StringBuilder(256)
    
            Dim szDefPrinter As String
            Dim dwBufSize As Integer
            dwBufSize = tmpstr.Capacity
    
            GetDefaultPrinter(tmpstr, dwBufSize)
            szDefPrinter = tmpstr.ToString()
    
            'change the default printer prior to calling the
            'ExecWB function.
            If String.Compare(szPrinter, szDefPrinter, True) <> 0 Then
                SetDefaultPrinter(szPrinter)
            End If
    
            strPath = GetZanConfigurationDir(szPrinter)
    
            If Not strPath.EndsWith("\") Then
                strPath = String.Concat(strPath, "\")
            End If
    
            strPath = String.Concat(strPath, "event.ini")
    
            'enable event notification
            WritePrivateProfileString("event", "enable", "1", strPath)
            'set enddoc event name
            WritePrivateProfileString("event", "enddoc", _
            szEnddocEvent, strPath)
    
            Dim ewh As EventWaitHandle
            ewh = New EventWaitHandle(False, EventResetMode.AutoReset, _
            szEnddocEvent)
    
            Dim explorer As InternetExplorer = New InternetExplorerClass()
            Dim WebBrowser As IWebBrowserApp = CType(explorer, IWebBrowserApp)
            Dim noValue As Object = Nothing
    
            WebBrowser.Visible = True
            WebBrowser.Navigate(htmlfile, noValue, noValue, noValue, noValue)
    
            'Wait until URL navigation is done
            While WebBrowser.Busy
                Thread.Sleep(250)
            End While
    
    
            'printing without print dialog
            'The print job status is "sent to printer" when
            'ExecWB returns.
            explorer.ExecWB(SHDocVw.OLECMDID.OLECMDID_PRINT, _
                            SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, _
                            noValue, noValue)
    
            'wait for the EndDoc event to be received,
            'an indication that the submitted print job has indeed completed
            ewh.WaitOne()
    
            explorer.Quit()
    
            'set default printer back to original
            If String.Compare(szPrinter, szDefPrinter, True) <> 0 Then
                SetDefaultPrinter(szDefPrinter)
            End If
        End Sub
    
    
        Sub Main()
            printhtml("zan image printer(bw)", "c:\htmlfiles\document.htm")
        End Sub
    
    End Module
    
    

    C# code sample:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.IO;
    using Microsoft.Win32;
    using SHDocVw;
    
    
    namespace printhtml_csharp
    {
        class Program
        {
            //Determines Zan Image Printer installation directory
            static string GetZanInstallDir()
            {
                string installfolder = string.Empty;
                RegistryKey rkTest;
    
                //first check to see if the uninstall registry entry exists
                rkTest = Registry.LocalMachine.OpenSubKey(
                "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\zvprt50");
    
                if (rkTest != null)
                {
                    installfolder = rkTest.GetValue("UninstallString").ToString();
                    rkTest.Close();
    
                    if (installfolder.Length > 0)
                    {
                        installfolder = Path.GetDirectoryName(installfolder);
    
                        DirectoryInfo installdir1 = new DirectoryInfo(installfolder);
                        if (installdir1.Exists)
                        {
                            return installfolder;
                        }
                    }
                }
    
                //fallback to the \Program Files\zvprt50 folder:
                installfolder = Environment.GetFolderPath
                    (Environment.SpecialFolder.ProgramFiles);
    
                if (!installfolder.EndsWith("\\"))
                    installfolder = string.Concat(installfolder, "\\");
    
                installfolder = string.Concat(installfolder, "zvprt50");
    
                return installfolder;
            }
    
    
    
            //Determines Zan Image Printer
            //configuration directory for the ini setting files
            static string GetZanConfigurationDir(string szPrinter)
            {
                //read the OS info
                OperatingSystem os = System.Environment.OSVersion;
                string sCfg;
                uint lPolicy;
                StringBuilder tmpstr = new StringBuilder(256);
    
                //read configure.ini from
                //Zan Image Printer installation directory
                sCfg = GetZanInstallDir();
    
                if (!sCfg.EndsWith("\\"))
                    sCfg = string.Concat(sCfg, "\\");
    
                sCfg = string.Concat(sCfg, "configure.ini");
    
    
                //Read the all users (per-machine) folder policy
                //from configure.ini:
    
                //policy=1: auto detect, if Vista or newer,
                //use CSIDL_COMMON_DOCUMENTS as the
                //all users (per-machine) folder;
                //otherwise, use CSIDL_COMMON_APPDATA
                //policy=2: use CSIDL_COMMON_APPDATA
                //policy=3: use CSIDL_COMMON_DOCUMENTS
    
                lPolicy = GetPrivateProfileInt("allusersfolder", "policy",
                    1, sCfg);
    
                //handle the auto detect policy
                if (1 == lPolicy)
                {
                    //Vista and 2008: dwVerMajor>=6
                    if (os.Version.Major >= 6)
                    {
                        lPolicy = 3;
                    }
                    else
                    {
                        lPolicy = 2;
                    }
                }
    
    
                //get the all users (per-machine) folder
                //if the all users (per-machine) folder exists,
                //then this zan image printer was installed per-machine: 
                //all users share the same settings
                if (2 == lPolicy)
                {
                    //csidl = CSIDL_COMMON_APPDATA;
                    sCfg = Environment.GetFolderPath
                        (Environment.SpecialFolder.CommonApplicationData);
    
                }
                else
                {
                    //csidl = CSIDL_COMMON_DOCUMENTS;
                    SHGetFolderPath(0, CSIDL_COMMON_DOCUMENTS, 0, 0, tmpstr);
                    sCfg = tmpstr.ToString();
                }
    
                if (!sCfg.EndsWith("\\")) sCfg = string.Concat(sCfg, "\\");
                sCfg = string.Concat(sCfg, "zvprt50\\");
                sCfg = string.Concat(sCfg, szPrinter);
    
                //all users will share the same
                //settings for the printer
                DirectoryInfo tmpdir = new DirectoryInfo(sCfg);
                if (tmpdir.Exists)
                {
                    return sCfg;
                }
    
                //if the all users (per-machine) folder doesn't exist,
                //assume each user has his own settings
                //for the printer:
                sCfg = Environment.GetFolderPath
                    (Environment.SpecialFolder.ApplicationData);
    
                if (!sCfg.EndsWith("\\")) sCfg = string.Concat(sCfg, "\\");
                sCfg = string.Concat(sCfg, "zvprt50\\");
                sCfg = string.Concat(sCfg, szPrinter);
    
                return sCfg;
            }
    
    
            static void printhtml(string szPrinter, string htmlfile)
            {
                StringBuilder tempstr = new StringBuilder(256);
                string szDefPrinter;
                int dwBufSize = tempstr.Capacity;
    
                /*
                change the default printer prior to calling the
                ExecWB function.
                */
                GetDefaultPrinter(tempstr, ref dwBufSize);
                szDefPrinter = tempstr.ToString();
    
                if (string.Compare(szPrinter, szDefPrinter, true) != 0)
                {
                    SetDefaultPrinter(szPrinter);
                }
    
                //enddoc event name
                string szEnddocEvent = "SignalPrintDone";
                string strPath;
    
    
                strPath = GetZanConfigurationDir(szPrinter);
    
                if (!strPath.EndsWith("\\"))
                    strPath = string.Concat(strPath, "\\");
    
                strPath = string.Concat(strPath,"event.ini");
    
                //enable event notification
                WritePrivateProfileString("event", "enable", "1", strPath);
                //set enddoc event name
                WritePrivateProfileString("event", "enddoc", szEnddocEvent, strPath);
    
                EventWaitHandle ewh;
                ewh = new EventWaitHandle(false, EventResetMode.AutoReset, szEnddocEvent);
    
                InternetExplorer explorer = new InternetExplorerClass();
                IWebBrowserApp webBrowser = explorer;
                Object noValue = null;
    
                webBrowser.Visible = true;
                webBrowser.Navigate(htmlfile, ref noValue,
                  ref noValue, ref noValue, ref noValue);
    
                /*Wait until URL navigation is done*/
                while (webBrowser.Busy)
                {
                    Thread.Sleep(250);
                }
    
                
                //printing without print dialog
                //The print job status is "sent to printer" when
                //ExecWB returns.
                explorer.ExecWB(SHDocVw.OLECMDID.OLECMDID_PRINT,
                  SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER,
                  ref noValue,
                  ref noValue);
    
                //wait for the EndDoc event to be received,
                //an indication that the submitted print job has indeed completed
                ewh.WaitOne();
                explorer.Quit();
    
                /*set default printer back to original*/
                if (string.Compare(szPrinter, szDefPrinter, true) != 0)
                {
                    SetDefaultPrinter(szDefPrinter);
                }
            }
    
    
            static void Main(string[] args)
            {
                printhtml("zan image printer(bw)", "c:\\htmlfiles\\document.htm");
            }
    
            [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern bool GetDefaultPrinter(StringBuilder pszBuffer,
            ref int size);
    
            [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern bool SetDefaultPrinter(string Name);
    
            [DllImport("kernel32.dll")]
            static extern uint GetPrivateProfileString(string lpAppName,
                string lpKeyName, string lpDefault,
                StringBuilder lpReturnedString, int nSize, string lpFileName);
    
            [DllImport("kernel32.dll")]
            static extern bool WritePrivateProfileString(string lpAppName,
                                                         string lpKeyName,
                string lpString, string lpFileName);
    
            [DllImport("kernel32.dll")]
            static extern uint GetPrivateProfileInt(string lpAppName,
                string lpKeyName, int nDefault, string lpFileName);
    
    
            [DllImport("shell32.dll")]
            static extern bool SHGetFolderPath(int hwndOwner,
            int nFolder, int hToken, int dwFlags, StringBuilder pszPath);
            const int CSIDL_COMMON_DOCUMENTS = 0x002e;
    
        }
    }
    
    



    Return to top




    Microsoft Word automation VB, Delphi, C, VC.NET, VB.NET and C# code samples: print Word DOC files programmatically
    Below are the code samples that illustrate using Microsoft Word automation to print DOC files programmatically.
    To compile the VC.NET, VB.NET and C# code samples, you first need to set a reference to the "Microsoft Word Object Library" in your project by following the steps below:
    1. In Solution Explorer, right click the project node, then click Add Reference.
    2. In the Add Reference dialog, click the COM tab.
    3. Click the "Microsoft Word X.0 Object Library"(X is the version number), and then click Select.

    VB code sample:
    Option Explicit
    
    Private Declare Sub Sleep Lib "kernel32" ( _
        ByVal dwMilliseconds As Long)
    
    
    Public Sub printdoc(szPrinter As String, docfile As String)
    Dim wdApp As Object
    Dim oldactiveprinter As String
    
    'Word Automation
    Set wdApp = CreateObject("Word.Application")
    'show Word window
    wdApp.Visible = True
    wdApp.Documents.Open (docfile)
    
    'remember current active printer
    oldactiveprinter = wdApp.ActivePrinter
    
    oldactiveprinter = LCase(oldactiveprinter)
    szPrinter = LCase(szPrinter)
    
    If oldactiveprinter <> Trim$(szPrinter) Then
    wdApp.ActivePrinter = szPrinter
    End If
    
    wdApp.ActiveDocument.PrintOut
    
    'Make sure all of the documents are gone from the queue
    Do While wdApp.BackgroundPrintingStatus > 0
        Sleep 100
      Loop
      
    'set active printer back to original
    If oldactiveprinter <> Trim$(szPrinter) Then
    wdApp.ActivePrinter = oldactiveprinter
    End If
    
    wdApp.ActiveDocument.Close (False)
    
    'Close instance of MS Word
    wdApp.Quit
    
    Set wdApp = Nothing
    End Sub
    
    Public Sub Main()
    printdoc "zan image printer(bw)", "c:\abc\1.doc"
    End Sub
    

    Delphi code sample:
    uses Windows, ComObj;
    procedure printdoc(printername:String; docfile:String);
    implementation
    
    procedure printdoc(printername:String; docfile:String);
    var
      wdApp: Variant;
      oldactiveprinter: String;
      begin
    
      //Word automation
      //start an instance of MS Word
      wdApp := CreateOleObject('Word.Application');
      //show Word window
      wdApp.Visible := True;
      //remember current active printer
      oldactiveprinter := wdApp.ActivePrinter;
      wdApp.ActivePrinter := printername;
      wdApp.Documents.Open(docfile);
    
      wdApp.ActiveDocument.PrintOut;
    
      //Make sure all of the documents are gone from the queue
      while(wdApp.BackgroundPrintingStatus > 0) do
       Sleep(250);
    
      //set active printer back to original
      if oldactiveprinter <> printername then
      wdApp.ActivePrinter := oldactiveprinter;
    
      wdApp.ActiveDocument.Close(False);
      wdApp.quit(False);
     end;
    
    printdoc('zan image printer(bw)', 'c:\abc\1.doc');
    
    C++ code sample:
    #include <windows.h>
    #include <winspool.h>
    #include <ole2.h>
    
    #pragma warning(disable:4146)
    
    //#import statement and smart pointers:
    //The #import statement is different for each version of the 
    //Microsoft Word Object Library, change the path to your own Word 
    //type library if needed
    #import "c:\Program Files\Common Files\Microsoft Shared\Office10\MSO.DLL" 
    #import "c:\Program Files\\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.olb" 
    #import "c:\Program Files\Microsoft Office\Office10\MSWORD.olb" \
            rename("ExitWindows","ExitWindowsEx")
    
    void printdoc(char *printername, char *docfile)
    {
    	CoInitialize(NULL);
    	CLSID clsid;
    	
    	/*Word automation*/
    	CLSIDFromProgID(L"Word.Application", &clsid); 
    
    	Word::_ApplicationPtr pApp;
    	
    	pApp.CreateInstance (clsid, NULL);
    
    	/*show Word window*/
    	pApp->PutVisible(VARIANT_TRUE);
    	
    	/*remember current active printer*/
    	BSTR org_activeprinter;
    	pApp->get_ActivePrinter(&org_activeprinter);
    
    	_variant_t bstrFileName(docfile);
    	pApp->GetDocuments()->Open(&bstrFileName);
    
    	pApp->put_ActivePrinter(_bstr_t(printername));
    	
    	Word::_DocumentPtr pWordDocument = pApp->GetActiveDocument();
    	//print the document
    	pWordDocument->PrintOut();
    
    	// Make sure all of the documents are gone from the queue
    	while(pApp->BackgroundPrintingStatus > 0)
    	{
    		Sleep(250);
    	}
    	
    	/*set active printer back to original*/
    	pApp->put_ActivePrinter(org_activeprinter);
    
    	SysFreeString(org_activeprinter);
    
    	_variant_t v((long)Word::wdDoNotSaveChanges);
    
    	pApp->Quit(&v);
    	
    	CoUninitialize();
    }
    
    printdoc("zan image printer(bw)", "c:\\abc\\1.doc");
    

    VC.NET code sample:
    using namespace System;
    using namespace System::Text;
    using namespace System::Runtime::InteropServices;
    using namespace System::Threading;
    
    void printdoc(String^ szPrinter, String^ docfile)
    {
    	Word::ApplicationClass^ ac = gcnew Word::ApplicationClass();
    	Word::Application^ app = ac->Application;
    	String^ szActiveprinter;
    	Object^ missing = System::Reflection::Missing::Value;
    
    	szActiveprinter = app->ActivePrinter;
    	
    	//remember current active printer
    	if(String::Compare(szPrinter, szActiveprinter, true) != 0)
    	{
    		app->ActivePrinter = szPrinter;
    	}
    	app->Visible = true;
    	
    	Word::Document^ aDoc = gcnew Word::Document();
    	aDoc = app->Documents->Add(docfile, missing, missing, missing);
    	
    	app->PrintOut(missing, missing, missing, missing, missing, missing,
    		missing, missing, missing, missing, missing, missing,
    		missing, missing, missing, missing, missing, missing, missing);
    
    	// Make sure all of the documents are gone from the queue
    	while(app->BackgroundPrintingStatus > 0)
    	{
    		Thread::Sleep(250);
    	}
    
    	//set active printer back to original
    	if(String::Compare(szPrinter, szActiveprinter, true) != 0)
    	{
    		app->ActivePrinter = szActiveprinter;
    	 }
    	 ac->Quit(missing, missing, missing);
    }
    
    printdoc(L"zan image printer(bw)", L"c:\\abc\\1.doc");
    


    VB.NET code sample:
    Imports System.Runtime.InteropServices
    Imports System.Text
    Imports System
    Imports System.Threading
    
    Module Module1
     Sub printdoc(ByVal szPrinter As String, ByVal docfile As Object)
         Dim ac As Word.ApplicationClass = New Word.ApplicationClass()
         Dim app As Word.Application = ac.Application
         Dim szActiveprinter As String
    
         szActiveprinter = app.ActivePrinter
    
         'remember current active printer
         If String.Compare(szPrinter, szActiveprinter, True) <> 0 Then
             app.ActivePrinter = szPrinter
         End If
    
         app.Visible = True
    
         Dim aDoc As Word.Document = New Word.Document()
         Dim missing As Object
         missing = System.Reflection.Missing.Value
    
         aDoc = app.Documents.Open(docfile, _
                                    missing, missing, missing, _
                                    missing, missing, missing, _
                                    missing, missing, missing, _
                                    missing, missing)
    
         app.PrintOut(missing, missing, missing, missing, missing, missing, _
                       missing, missing, missing, missing, missing, missing, _
                       missing, missing, missing, missing, missing, missing, _
                       missing)
    
         ' Make sure all of the documents are gone from the queue
         While app.BackgroundPrintingStatus > 0
             Thread.Sleep(250)
         End While
    
         'set active printer back to original
         'remember current active printer
         If String.Compare(szPrinter, szActiveprinter, True) <> 0 Then
             app.ActivePrinter = szActiveprinter
         End If
             
         ac.Quit(missing, missing, missing)
     End Sub
    
     Sub Main()
         printdoc("zan image printer(bw)", "c:\abc\1.doc")
     End Sub
    End Module
    

    C# code sample:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Threading;
    
    class Program
    {
     static void printdoc(string szPrinter, object docfile)
     {
         Word.ApplicationClass ac = new Word.ApplicationClass();
         Word.Application app = ac.Application;
         string szActiveprinter;
    
         szActiveprinter = app.ActivePrinter;
    
         //remember current active printer
         if (String.Compare(szPrinter, szActiveprinter, true) != 0)
         {
             app.ActivePrinter = szPrinter;
         }
         app.Visible = true;
    
         Word.Document aDoc = new Word.Document();
         object missing = System.Reflection.Missing.Value;
    
    
         aDoc = app.Documents.Open(ref docfile,
                                   ref missing, ref missing, 
                                   ref missing, ref missing, 
                                   ref missing, ref missing,
                                   ref missing, ref missing, 
                                   ref missing, ref missing, 
                                   ref missing);
                                   
    
         app.PrintOut(ref missing, ref missing, ref missing, 
                      ref missing, ref missing, ref missing,
                      ref missing, ref missing, ref missing, 
                      ref missing, ref missing, ref missing,
                      ref missing, ref missing, ref missing, 
                      ref missing, ref missing, ref missing, 
                      ref missing);
    
         // Make sure all of the documents are gone from the queue
         while (app.BackgroundPrintingStatus > 0)
         {
             Thread.Sleep(250);
         }
    
         //set active printer back to original
         if (String.Compare(szPrinter,szActiveprinter,true) != 0)
         {
             app.ActivePrinter = szActiveprinter;
         }
         ac.Quit(ref missing, ref missing, ref missing);
     }
    
    
     static void Main(string[] args)
     {
         printdoc("zan image printer(bw)", "c:\\abc\\1.doc");
     }
    }
    



    Return to top




    Microsoft Excel automation VB, Delphi, C, VC.NET, VB.NET and C# code samples: print Excel XLS files programmatically
    Below are the code samples that illustrate using Microsoft Excel automation to print XLS files programmatically.
    The code samples will print all sheets in the workbook. The VB, Delphi and C/C++ code samples also contain commented out code showing how to print just the selected sheet (such as the first sheet), you can uncomment it and put it back if needed.
    To compile the VC.NET, VB.NET and C# code samples, you first need to set a reference to the "Microsoft Excel Object Library" in your project by following the steps below:
    1. In Solution Explorer, right click the project node, then click Add Reference.
    2. In the Add Reference dialog, click the COM tab.
    3. Click the "Microsoft Excel X.0 Object Library"(X is the version number), and then click Select.

    VB code sample:
    Option Explicit
    
    Private Declare Sub Sleep Lib "kernel32" ( _
        ByVal dwMilliseconds As Long)
    
    'print to the current default printer
    Public Sub printxls(xlsfile As String)
    Dim ExcelApp As Object
    Dim ObjSheet As Object
    
    'Excel Automation
    Set ExcelApp = CreateObject("excel.Application")
    ExcelApp.Visible = True
    ExcelApp.Workbooks.Open (xlsfile)
    
    'print all sheets in the workbook
    ExcelApp.ActiveWorkbook.PrintOut
    
    'print the first sheet, sheet index starts from 1
    Set ObjSheet = ExcelApp.ActiveWorkbook.WorkSheets(1)
    'ObjSheet.PrintOut
    
    'close instance of MS Excel
    ExcelApp.ActiveWorkbook.Close (False)
    ExcelApp.Quit
    Set ExcelApp = Nothing
    End Sub
    
    Public Sub Main()
    printxls "c:\abc\1.xls"
    End Sub
    

    Delphi code sample:
    uses Windows, ComObj;
    procedure printxls(xlsfile:String);
    implementation
    
    procedure printxls(xlsfile:String);
    var
      ExcelApp: Variant;
      ObjSheet: Variant;
      begin
    
      //Excel automation
      //start an instance of MS Excel
      ExcelApp := CreateOleObject('Excel.Application');
      ExcelApp.Visible := True;
      ExcelApp.Workbooks.Open(xlsfile);
    
      //print all sheets in the workbook
      ExcelApp.ActiveWorkbook.PrintOut;
    
      //print the first sheet, sheet index starts from 1
      ObjSheet := ExcelApp.ActiveWorkBook.WorkSheets [1];
      //ObjSheet.PrintOut;
    
      ExcelApp.ActiveWorkbook.Close(False);
      //Quit Excel
      ExcelApp.Quit;
     end;
    
    printxls('c:\abc\1.xls');
    
    C++ code sample:
    #include <windows.h>
    #include <ole2.h>
    
    #pragma warning(disable:4146)
    
    //#import statement and smart pointers below:
    //The #import statement is different for each version of the 
    //Microsoft Excel Object Library, change the path to your own Excel 
    //type library if needed
    #import "c:\Program Files\Common Files\Microsoft Shared\Office10\MSO.DLL" 
    #import "c:\Program Files\\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.olb" 
    #import "C:\Program Files\Microsoft Office\Office10\EXCEL.EXE" \
            rename("DialogBox","_DialogBox") \
            rename("RGB","_RGB") \
            exclude("IFont","IPicture")
    
    
    /*print to the current default printer*/
    void printxls(char *xlsfile)
    {
       Excel::_ApplicationPtr ExcelApp; 
       Excel::WorkbooksPtr ExcelWorkBooks; 
       Excel::_WorkbookPtr ExcelWorkBook; 
    
       /*Excel automation*/
       CoInitialize(NULL); 
       if(ExcelApp.CreateInstance(__uuidof(Excel::Application)) == S_OK) 
       { 
        ExcelApp->PutVisible(0, VARIANT_TRUE);
        ExcelWorkBooks = ExcelApp->GetWorkbooks(); 
        
        ExcelWorkBook = ExcelWorkBooks->Open(_bstr_t(xlsfile)); 
    
        /*print all sheets in the workbook*/
        ExcelWorkBook->PrintOut();
        
        /*print the selected sheet*/
        Excel::WorksheetsPtr pSheets = ExcelApp->GetSheets(); 
        /*Get first sheet*/
        VARIANT vt; 
        VariantInit(&vt); 
        vt.vt = VT_I2; 
        /*sheet index starts from 1*/
        vt.iVal = (short)1; 
        Excel::_WorksheetPtr worksheet = pSheets->GetItem(vt);
        /*worksheet->PrintOut();*/
    
        ExcelWorkBook->Close(); 
        ExcelApp->Quit();
       } 
       CoUninitialize(); 
    }
    
    printxls("C:\\abc\\1.xls");
    

    VC.NET code sample:
    using namespace System;
    using namespace System::Text;
    using namespace System::Runtime::InteropServices;
    using namespace System::Threading;
    
    /*print to the current default printer*/
    void printxls(String^ xlsfile)
    {
      /*Excel automation*/
      Excel::ApplicationClass^ ac = gcnew Excel::ApplicationClass();
      Excel::Application^ app = ac->Application;
      Excel::Workbooks^ workbooks = app->Workbooks;
      Object^ missing = System::Reflection::Missing::Value;
    
      Excel::Workbook^ workbook = workbooks->Open(xlsfile, 
      missing, missing, missing, missing,
      missing, missing, missing, missing,
      missing, missing, missing, missing);
    
      app->Visible = true;
      /*print all sheets in the workbook*/
      //The print job status is "sent to printer" when
      //PrintOut returns.
      workbook->PrintOut(missing, missing, missing, missing,
      missing, missing, missing, missing);
      
      workbook->Close(missing, missing, missing);
      app->Quit();
    }
    printxls(L"C:\\abc\\1.xls");
    

    VB.NET code sample:
    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports System.Runtime.InteropServices
    Imports System.Threading
    
    Module Module1
     'print to the current default printer
     Sub printxls(ByVal xlsfile As String)
         'Excel automation
         Dim ac As Excel.ApplicationClass = New Excel.ApplicationClass()
         Dim app As Excel.Application = ac.Application
         Dim workbooks As Excel.Workbooks = app.Workbooks
         Dim missing As Object = System.Reflection.Missing.Value
    
         Dim workbook As Excel.Workbook = workbooks.Open(xlsfile, _
                        missing, missing, missing, missing, _
                        missing, missing, missing, missing, _
                        missing, missing, missing, missing)
    
         app.Visible = True
         'print all sheets in the workbook
         'The print job status is "sent to printer" when
         'PrintOut returns.
         workbook.PrintOut(missing, missing, missing, missing, _
                           missing, missing, missing, missing)
    
         workbook.Close(missing, missing, missing)
    
         app.Quit()
     End Sub
    
     Sub Main()
         printxls("C:\abc\1.xls")
     End Sub
    End Module
    

    C# code sample:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Threading;
    class Program
    {
     /*print to the current default printer*/
     static void printxls(string xlsfile)
     {
         /*Excel automation*/
         Excel.ApplicationClass ac = new Excel.ApplicationClass();
         Excel.Application app = ac.Application;
         app.Visible = true;
         Excel.Workbooks workbooks = app.Workbooks;
         Object missing = System.Reflection.Missing.Value;
    
         Excel.Workbook workbook = 
             workbooks.Open(xlsfile, 
             missing, missing, missing, missing,
             missing, missing, missing, missing,
             missing, missing, missing, missing);
    
         /*print all sheets in the workbook*/
         //The print job status is "sent to printer" when
         //PrintOut returns.
         workbook.PrintOut(missing, missing, missing, missing,
                           missing, missing, missing, missing);
    
         workbook.Close(missing, missing, missing);
    
         app.Quit();
     }
    
     static void Main(string[] args)
     {
         printxls("C:\\abc\\1.xls");
     }
    }
    



    Return to top




    VB, Delphi, C, VC.NET, VB.NET and C# code samples: get and set the default printer in Windows
    The GetDefaultPrinter Win32 API retrieves the printer name of the default printer for the current user on the local computer.
    The SetDefaultPrinter Win32 API sets the printer name of the default printer for the current user on the local computer.

    The following code samples illustrate the technique to change the default printer:

    VB code sample:
    Option Explicit
    Private Declare Function GetDefaultPrinter Lib "winspool.drv" Alias _
    "GetDefaultPrinterA" (ByVal pszBuffer As String, pcchBuffer As Long) As Long
    
    Private Declare Function SetDefaultPrinter Lib "winspool.drv" _
       Alias "SetDefaultPrinterA" _
      (ByVal pszPrinter As String) As Long
    
    
    Public Sub Main()
    Dim sPrinterName As String
    Dim sNameBuff As String, lLen As Long
    
    GetDefaultPrinter vbNullChar, lLen
    sNameBuff = Space$(lLen)
    GetDefaultPrinter sNameBuff, lLen
    
    sPrinterName = Left$(sNameBuff, _
                InStr(sNameBuff, vbNullChar) - 1)
    
    SetDefaultPrinter "zan image printer(bw)"
    
    End Sub
    
    Delphi code sample:
    uses
    Windows, Messages, SysUtils, ShlObj, ShellAPI, SHFolder, ComObj;
    
    function GetDefaultPrinter(prnName:PAnsiChar; var bufSize:DWORD):
    BOOL; stdcall; external 'winspool.drv' name 'GetDefaultPrinterA';
    
    function SetDefaultPrinter(prnName:PAnsiChar):
    BOOL; stdcall; external 'winspool.drv' name 'SetDefaultPrinterA';
    procedure test_defprinter();
    
    implementation
    
    procedure test_defprinter();
    var
      szDefPrinter: String;
      lBufSize: DWord;
    begin
      SetLength(szDefPrinter, MAX_PATH);
      lBufSize := MAX_PATH;
      GetDefaultPrinter(Pchar(szDefPrinter), lBufSize);
      szDefPrinter := String (PChar(szDefPrinter));
    
      SetDefaultPrinter('zan image printer(bw)');
    end;
    

    C code sample:
    #include <windows.h>
    #include <winspool.h>
    
    char  szDefPrinter[MAX_PATH];
    DWORD dwBufSize;
    
    dwBufSize = MAX_PATH;
    
    GetDefaultPrinter(szDefPrinter, &dwBufSize);
    
    SetDefaultPrinter("zan image printer(bw)");
    


    VC.NET code sample:
    using namespace System;
    using namespace System::Text;
    using namespace System::Runtime::InteropServices;
    
    // Declare the function that is exported from unmanaged dll:
    [DllImport("winspool.drv")]
    extern "C" bool _cdecl GetDefaultPrinter(
    	 StringBuilder^ pszBuffer, int *size);
    
    [DllImport("winspool.drv")]
    extern "C" bool _cdecl SetDefaultPrinter(
    	 String^ pszPrinter);
    
    	StringBuilder^ tempstr = gcnew StringBuilder(256);
    	String^ szDefPrinter;
    	int dwBufSize = tempstr->Capacity;
    
    	GetDefaultPrinter(tempstr, &dwBufSize);
    	szDefPrinter = tempstr->ToString();
    
    	SetDefaultPrinter(L"zan image printer(bw)");
    

    VB.NET code sample:
    Imports System.Runtime.InteropServices
    Imports System.Text
    Imports System
    
    Module Module1
     Declare Function GetDefaultPrinter Lib "winspool.drv" _
     Alias "GetDefaultPrinterA" (ByVal pszBuffer As System.Text.StringBuilder, _
     ByRef size As Int32) As Boolean
    
     Declare Function SetDefaultPrinter Lib "winspool.drv" Alias _
     "SetDefaultPrinterA" (ByVal pszPrinter As String) As Boolean
    
    
     Sub Main()
         Dim sPrinterName As String
         Dim tempstr As StringBuilder
         tempstr = New StringBuilder(256)
    
         GetDefaultPrinter(tempstr, tempstr.Capacity)
         sPrinterName = tempstr.ToString()
    
         SetDefaultPrinter("zan image printer(bw)")
     End Sub
    End Module
    

    C# code sample:
    using System.Runtime.InteropServices;
     class Program
     {
      static void Main(string[] args)
      {
          StringBuilder tempstr = new StringBuilder(256);
          string szDefPrinter ;
          int dwBufSize = tempstr.Capacity;
    
          GetDefaultPrinter(tempstr, ref dwBufSize);
          szDefPrinter = tempstr.ToString();
    
          // Set default printer
          SetDefaultPrinter("zan image printer(bw)");
      }
    
      [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
      public static extern bool GetDefaultPrinter(StringBuilder pszBuffer, 
          ref int size);
    
      [DllImport("winspool.drv", CharSet = CharSet.Auto, 
          SetLastError = true)]
      public static extern bool SetDefaultPrinter(string Name);
     }
     



    Return to top

    Copyright © 2002-2010, http://www.zan1011.com, All Rights Reserved.