windows printer state c

WINDOWS PRINTER STATE C

Artonik 14/02/2017

La récupération de l'état d'une imprimante peut se faire d'au moins deux manières en dot net WMI ou Winspool.


La récupération de l'état d'une imprimante peut être necessaire dans une application, notamment pour savoir si l'impression s'est déroulée correctement ou si l'imprimante est en défaut (bourrage papier, plus de papier etc...)

Le statut de l'imprimante peut être stocké par une enumération Flags de ce type :
 

    [Flags]
    public enum PrinterStatus
    {
        PRINTER_STATUS_OK = 0x00000000,
        PRINTER_STATUS_BUSY = 0x00000200,
        PRINTER_STATUS_DOOR_OPEN = 0x00400000,
        PRINTER_STATUS_ERROR = 0x00000002,
        PRINTER_STATUS_INITIALIZING = 0x00008000,
        PRINTER_STATUS_IO_ACTIVE = 0x00000100,
        PRINTER_STATUS_MANUAL_FEED = 0x00000020,
        PRINTER_STATUS_NO_TONER = 0x00040000,
        PRINTER_STATUS_NOT_AVAILABLE = 0x00001000,
        PRINTER_STATUS_OFFLINE = 0x00000080,
        PRINTER_STATUS_OUT_OF_MEMORY = 0x00200000,
        PRINTER_STATUS_OUTPUT_BIN_FULL = 0x00000800,
        PRINTER_STATUS_PAGE_PUNT = 0x00080000,
        PRINTER_STATUS_PAPER_JAM = 0x00000008,
        PRINTER_STATUS_PAPER_OUT = 0x00000010,
        PRINTER_STATUS_PAPER_PROBLEM = 0x00000040,
        PRINTER_STATUS_PAUSED = 0x00000001,
        PRINTER_STATUS_PENDING_DELETION = 0x00000004,
        PRINTER_STATUS_PRINTING = 0x00000400,
        PRINTER_STATUS_PROCESSING = 0x00004000,
        PRINTER_STATUS_TONER_LOW = 0x00020000,
        PRINTER_STATUS_USER_INTERVENTION = 0x00100000,
        PRINTER_STATUS_WAITING = 0x20000000,
        PRINTER_STATUS_WARMING_UP = 0x00010000
    }


Il existe de nombreux exemples en WMI qui ressemble a cela :
// Get the ManagementObjectCollection representing
// the result of the WMI query.
string query = "SELECT PrinterState,Name FROM Win32_Printer WHERE Name='" + printername + "'";
 
using (var TmpPrinterStateSearcher = new ManagementObjectSearcher(query))
{
    using (System.Management.ManagementObjectCollection moc = TmpPrinterStateSearcher.Get())
    {
        foreach (ManagementObject service in moc)
        { 
            uint state = (uint)service.Properties["PrinterState"].Value;
            IzyfilCommon.Enums.PrinterStatus s = (IzyfilCommon.Enums.PrinterStatus)state; 
            return s;
        }
    }
}

Mais cette méthode souffre d'un problème majeur le temps de recherche peut être long (plusieurs secondes) donc pénalisant pour l'application et l'utilisateur.

Une autre méthode moins connue semble t'il, se base sur l'importation de winspool.drv et permet de connaitre l'état de l'imprimante en quelques millisecondes.
On trouve de la documentation a ce sujet sur pinvoke.net dans les articles suivants Getprinter et PrinterInfo2 notamment ainsi que ici.
Sur la MSDN les informations relatives a la lecture des propriétés notamment ici et ici.

public class SpoolPrinterInfo

   {
       [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
       public static extern int OpenPrinter(string pPrinterName, out IntPtr phPrinter, ref PRINTER_DEFAULTS pDefault);
 
       [DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
       public static extern bool GetPrinter(IntPtr hPrinter, Int32 dwLevel, IntPtr pPrinter, Int32 dwBuf, out Int32 dwNeeded);
 
       [DllImport("winspool.drv", SetLastError = true)]
       public static extern int ClosePrinter(IntPtr hPrinter);
 
       [StructLayout(LayoutKind.Sequential)]
       public struct PRINTER_DEFAULTS
       {
           public IntPtr pDatatype;
           public IntPtr pDevMode;
           public int DesiredAccess;
       }
 
       [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
       public struct PRINTER_INFO_2
       {
           /// <summary>
           /// This member MUST be a non-NULL pointer to a string that MUST specify the name of the server that hosts the printer. For rules governing server names, see section 2.2.4.16.
           /// summary>
           [MarshalAs(UnmanagedType.LPTStr)]
           public string pServerName;
           /// <summary>
           /// This member MUST be a non-NULL pointer to a string that MUST specify the name of a printer. For rules governing printer names, see section 2.2.4.14.
           /// summary>
           [MarshalAs(UnmanagedType.LPTStr)]
           public string pPrinterName;
           /// <summary>
           /// This member is an optional pointer to a string that specifies the share name for the printer. This string MUST be ignored unless the Attributes member contains the PRINTER_ATTRIBUTED_SHARED flag. For rules governing path names, see section 2.2.4.9.
           /// summary>
           [MarshalAs(UnmanagedType.LPTStr)]
           public string pShareName;
           /// <summary>
           /// This member is a pointer to a string that specifies the port(s) used to transmit data to a printer. For rules governing port names, see section 2.2.4.10.
           /// summary>
           [MarshalAs(UnmanagedType.LPTStr)]
           public string pPortName;
           /// <summary>
           ///  This member is a pointer to a string that specifies the name of the printer driver. For rules governing printer driver names, see section 2.2.4.3.
           /// summary>
           [MarshalAs(UnmanagedType.LPTStr)]
           public string pDriverName;
           /// <summary>
           ///  This member is an optional pointer to a string that MUST specify additional information about the printer.<18>
           /// summary>
           [MarshalAs(UnmanagedType.LPTStr)]
           public string pComment;
           /// <summary>
           /// This member is an optional pointer to a string that specifies the location of the printer.
           /// summary>
           [MarshalAs(UnmanagedType.LPTStr)]
           public string pLocation;
           /// <summary>
           /// This member is an optional pointer to a truncated DEVMODE structure (section 2.2.1.1.1), and MUST be ignored on receipt. Actual DEVMODE data is passed to a method via a custom-marshaled _DEVMODE structure (section 2.2.2.1) in a DEVMODE_CONTAINER (section 2.2.1.2.1).
           /// summary>
           public IntPtr pDevMode;
           /// <summary>
           ///  This member is an optional pointer to a string that specifies the name of a file whose contents are used to create a separator page. This page is used to separate print jobs sent to the printer. For rules governing path names, see section 2.2.4.9.
           /// summary>
           [MarshalAs(UnmanagedType.LPTStr)]
           public string pSepFile;
           /// <summary>
           /// This member is an optional pointer to a string that specifies the name of the print processor used by the printer. For rules governing print processor names, see section 2.2.4.11.
           /// summary>
           [MarshalAs(UnmanagedType.LPTStr)]
           public string pPrintProcessor;
           /// <summary>
           /// This member is an optional pointer to a string that specifies the default data format used to record print jobs on the printer. For rules governing data type names, see section 2.2.4.2.
           /// summary>
           [MarshalAs(UnmanagedType.LPTStr)]
           public string pDatatype;
           /// <summary>
           /// his member is an optional pointer to a string that specifies the default print processor parameters.
           /// summary>
           [MarshalAs(UnmanagedType.LPTStr)]
           public string pParameters;
           /// <summary>
           /// This member is an optional pointer to a SECURITY_DESCRIPTOR structure ([MS-DTYP] section 2.4.6), and MUST be ignored on receipt. Actual SECURITY_DESCRIPTOR data is passed to a method via a self-relative SECURITY_DESCRIPTOR structure in a SECURITY_CONTAINER (section 2.2.1.2.13).
           /// summary>
           public IntPtr pSecurityDescriptor;
 
           public uint Attributes;
           /// <summary>
           ///  The value of this member specifies a priority value that the spooler uses to route each print job. The value of this member MUST be from 0 through 99, inclusive.
           /// summary>
           public uint Priority;
           /// <summary>
           /// The value of this member specifies the default priority value assigned to each print job. The value of this member MUST be from 0 through 99, inclusive.
           /// summary>
           public uint DefaultPriority;
           /// <summary>
           /// The value of this member specifies the earliest time that a job can be printed. The time is expressed as the number of minutes after 12:00 AM GMT within a 24-hour boundary.
           /// summary>
           public uint StartTime;
           /// <summary>
           /// The value of this member specifies the latest time that a job can be printed. The time is expressed as the number of minutes after 12:00 AM GMT within a 24-hour boundary
           /// summary>
           public uint UntilTime;
           /// <summary>
           /// This member specifies the printer status. It is the result of a bitwise OR of zero or more printer status values (section 2.2.3.12).
           /// summary>
           public uint Status;
           /// <summary>
           ///  The value of this member specifies the number of print jobs that have been queued for the printer
           /// summary>
           public uint cJobs;
           /// <summary>
           ///  The value of this member specifies the average pages per minute that have been printed on the printer.
           /// summary>
           public uint AveragePPM;
       }
 
       /// <summary>
       /// rend le status de l'imprimante
       /// summary>
       /// <param name="printerName">param>
       /// <returns>returns>
       public static PRINTER_INFO_2? GetPrinterInfo(String printerName)
       {
           IntPtr pHandle;
           PRINTER_DEFAULTS defaults = new PRINTER_DEFAULTS();
           PRINTER_INFO_2? Info2 = null;
 
           OpenPrinter(printerName, out pHandle, ref defaults);
 
           Int32 cbNeeded = 0;
 
           bool bRet = GetPrinter(pHandle, 2, IntPtr.Zero, 0, out cbNeeded);
 
           if (cbNeeded > 0)
           {
               IntPtr pAddr = Marshal.AllocHGlobal((int)cbNeeded);
 
               bRet = GetPrinter(pHandle, 2, pAddr, cbNeeded, out cbNeeded);
 
               if (bRet)
               {
                   Info2 = (PRINTER_INFO_2)Marshal.PtrToStructure(pAddr, typeof(PRINTER_INFO_2));
               }
 
               Marshal.FreeHGlobal(pAddr);
           }
 
           ClosePrinter(pHandle);
 
           return Info2;
       }
   }

Récupération de l'état d'une imprimante en c# dot net - Le Blog

Windows printer state c
Artonik est un éditeur de solutions spécialisé dans les domaines de la gestion l'accueil et de l'affichage dynamique. IzyFil solution globale pour la gestion de l'accueil et des files d'attentes et MediaBerry solution d'affichage dynamique. #frenchtech

windows printer state c

La récupération de l'état d'une imprimante peut se faire d'au moins deux manières en dot net WMI ou Winspool.

Le blog