(view source code of printing.cs as plain text)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Text.RegularExpressions;
namespace RobvanderWoude{public class Printing
{public const string progver = "3.04";
#region Global Variablespublic static char switchchar = '/';
public static List<string[]> actionslist = new List<string[]>( );
public static List<string[]> printerlist = new List<string[]>( );
public static bool actionFlush = false;
public static bool actionList = false;
public static bool actionPause = false;
public static bool actionResume = false;
public static string action = String.Empty;
#endregion Global Variablespublic static int Main( string[] args )
{ try { #region Initialize Variablesbool actionisset = false;
bool takeaction = true;
bool printerisset = false;
bool useAllPrn = false;
bool useDefault = false;
bool useRegex = false;
string pattern = ".*";
string printer = String.Empty;
bool sortisset = false;
string sortby = "N"; // sort by printer Name
WMIPrinterStatus status = WMIPrinterStatus.Unknown;
UInt32 jobs = 0;
int printerscount = 0;
int switchcharunix = 0;
int switchchardos = 0;
#endregion Initialize Variables #region Command Line Parsingif ( args.Length == 0 )
{return ErrorMessage( );
}if ( args.Length > 4 )
{return ErrorMessage( "Too many command line arguments" );
}foreach ( string arg in args )
{if ( arg.Length < 2 )
{return ErrorMessage( "Invalid command line argument \"{0}\"", arg );
}if ( "-/".Contains( arg[0] ) )
{if ( arg[0] == '-' )
{switchcharunix += 1;
} else {switchchardos += 1;
}switchchar = ( switchcharunix > switchchardos ? '-' : '/' );
switch ( arg[1].ToString( ).ToUpper( ) )
{case "?":
case "H":
case "-":
return ErrorMessage( );
case "A":
if ( useAllPrn )
{return ErrorMessage( "Duplicate command line switch {0}", SwitchString( arg[1] ) );
}if ( printerisset )
{return ErrorMessage( "Duplicate printer arguments \"{0}\" and \"{1}\"", printer, SwitchString( arg[1] ) );
}useAllPrn = true;
useDefault = false;
useRegex = false;
printer = SwitchString( arg[1] );
printerisset = true;
break;
case "D":
if ( useDefault )
{return ErrorMessage( "Duplicate command line switch {0}", SwitchString( arg[1] ) );
}if ( printerisset )
{return ErrorMessage( "Duplicate printer arguments \"{0}\" and \"{1}\"", printer, SwitchString( arg[1] ) );
}useDefault = true;
useAllPrn = false;
useRegex = false;
printer = SwitchString( arg[1] );
printerisset = true;
break;
case "F":
if ( actionFlush )
{return ErrorMessage( "Duplicate command line switch {0}", SwitchString( arg[1] ) );
}if ( actionisset )
{return ErrorMessage( "Duplicate action arguments \"{0}\" and \"CancelAllJobs\"", action );
}action = "CancelAllJobs";
actionisset = true;
actionFlush = true;
break;
case "L":
if ( actionList )
{return ErrorMessage( "Duplicate command line switch {0}", SwitchString( arg[1] ) );
}if ( actionisset )
{return ErrorMessage( "Duplicate action arguments \"{0}\" and \"List\"", action );
}action = "List";
actionList = true;
actionisset = true;
break;
case "P":
if ( actionPause )
{return ErrorMessage( "Duplicate command line switch {0}", SwitchString( arg[1] ) );
}if ( actionisset )
{return ErrorMessage( "Duplicate action arguments \"{0}\" and \"Pause\"", action );
}action = "Pause";
actionPause = true;
actionisset = true;
break;
case "R":
if ( actionResume )
{return ErrorMessage( "Duplicate command line switch {0}", SwitchString( arg[1] ) );
}if ( actionisset )
{return ErrorMessage( "Duplicate action arguments \"{0}\" and \"Resume\"", action );
}action = "Resume";
actionResume = true;
actionisset = true;
break;
case "S":
if ( sortisset )
{return ErrorMessage( "Duplicate command line switch {0}", SwitchString( arg[1] ) );
}if ( arg.Length == 2 )
{sortby = "N";
}else if ( arg.Length == 4 && arg[2] == ':' && "JNSjns".Contains( arg[3] ) )
{sortby = arg[3].ToString( ).ToUpper( );
}else if ( arg[2] == ':' )
{return ErrorMessage( "Invalid sort-by value \"{0}\"", arg );
} else {return ErrorMessage( "Invalid command line switch {0}", arg.ToUpper( ) );
}sortisset = true;
break;
case "X":
if ( useRegex )
{return ErrorMessage( "Duplicate command line switch {0}", SwitchString( arg[1] ) );
}if ( printerisset )
{return ErrorMessage( "Duplicate printer arguments \"{0}\" and \"{1}\"", printer, SwitchString( arg[1] ) );
}if ( arg.Length == 2 )
{return ErrorMessage( "No regex pattern specified with {0}", SwitchString( arg[1] ) );
}else if ( arg.Length == 3 && arg[2] == ':' )
{return ErrorMessage( "No regex pattern specified with {0}", SwitchString( arg[1] ) );
}else if ( arg.Length > 3 && arg[2] == ':' )
{pattern = arg.Substring( 3 );
if ( !VerifyRegExPattern( pattern ) )
{return ErrorMessage( "Invalid regex pattern \"{0}\"", pattern );
} } else {return ErrorMessage( "Invalid command line switch {0}", arg.ToUpper( ) );
}useAllPrn = false;
useDefault = false;
useRegex = true;
printer = arg;
printerisset = true;
break;
default:
return ErrorMessage( "Invalid command line switch {0}", arg.ToUpper( ) );
} } else {if ( printerisset )
{return ErrorMessage( "Duplicate printer arguments \"{0}\" and \"{1}\"", printer, arg );
}printer = arg;
useAllPrn = false;
useDefault = false;
useRegex = false;
printerisset = true;
} }if ( !printerisset )
{if ( actionList )
{useAllPrn = true;
useDefault = false;
printerisset = true;
} else {return ErrorMessage( "Printer not specified.\n\tSpecify a printer name, or regex pattern ({0}:\"regex\"), or use {1} (All printers) or {2} (Default printer).", SwitchString( "X" ), SwitchString( "A" ), SwitchString( "D" ) );
} }if ( !actionisset )
{return ErrorMessage( "No action specified.\n\tUse either {0} (List printers), or {1} (Pause printing),\n\tor {2} (Resume printing), or {3} (Flush print jobs).", SwitchString( "L" ), SwitchString( "P" ), SwitchString( "/R" ), SwitchString( "/F" ) );
} #endregion Command Line Parsing #region Enumerate Printersstring query1;
if ( useDefault )
{query1 = "SELECT * FROM Win32_Printer WHERE Default='TRUE'"; // default printer
}else if ( useAllPrn || useRegex )
{query1 = "SELECT * FROM Win32_Printer"; // all printers
} else {query1 = String.Format( "SELECT * FROM Win32_Printer WHERE DeviceID='{0}'", printer ); // specific printer
}ManagementObjectSearcher searcher1 = new ManagementObjectSearcher( "root\\CIMV2", query1 );
#endregion Enumerate Printersforeach ( ManagementObject queryObj in searcher1.Get( ) )
{printer = queryObj["DeviceID"].ToString( ); // printer name
if ( !useRegex || new Regex( pattern, RegexOptions.IgnoreCase ).IsMatch( printer ) )
{ #region Investigate Current Printer Statusprinterscount += 1;
status = (WMIPrinterStatus) Convert.ToUInt32( queryObj["ExtendedPrinterStatus"] ); // printer status
string[] properties = new string[3];
properties[0] = printer;
properties[1] = status.ToString( );
// number of queued print jobsstring query2 = String.Format( "SELECT * FROM Win32_PrintJob WHERE Name LIKE '{0}, %'", printer );
ManagementObjectSearcher searcher2 = new ManagementObjectSearcher( "root\\CIMV2", query2 );
try {jobs = Convert.ToUInt32( searcher2.Get( ).Count );
properties[2] = jobs.ToString( );
} catch {properties[2] = "Unknown";
}printerlist.Add( properties );
#endregion Investigate Current Printer Statustakeaction = ( ( actionFlush && jobs > 0 ) || ( actionPause && status != WMIPrinterStatus.Paused ) || ( actionResume && status != WMIPrinterStatus.Unknown ) );
if ( takeaction )
{ #region Invoke ActionWMIActionResult result = (WMIActionResult) Convert.ToUInt32( queryObj.InvokeMethod( action, null ) );
WMIPrinterStatus newstatus = WMIPrinterStatus.Unknown;
#endregion Invoke Action #region Investigate New Status After Actionif ( actionFlush )
{searcher2 = new ManagementObjectSearcher( "root\\CIMV2", query2 );
jobs = Convert.ToUInt32( searcher2.Get( ).Count );
} else {query2 = String.Format( "SELECT * FROM Win32_Printer WHERE DeviceID='{0}'", printer );
searcher2 = new ManagementObjectSearcher( "root\\CIMV2", query2 );
foreach ( ManagementObject queryObj2 in searcher2.Get( ) )
{newstatus = (WMIPrinterStatus) Convert.ToUInt32( queryObj2["ExtendedPrinterStatus"] );
} }string[] actions = new string[4];
actions[0] = printer;
actions[1] = newstatus.ToString( );
actions[2] = jobs.ToString( );
actions[3] = result.ToString( );
actionslist.Add( actions );
#endregion Investigate New Status After Action } } } #region Warn If No Printers Foundif ( printerscount == 0 )
{return ErrorMessage( "No matching printer found, use {0} for a list of valid printer names", ( switchchar == '/' ? "/L" : "-l" ) );
} #endregion Warn If No Printers Found #region Display The resultsreturn ShowResults( sortby );
#endregion Display The results }catch ( Exception e )
{#if DEBUGreturn ErrorMessage( "{0}\n\t{1}", e.Message, e.StackTrace );
#endifreturn ErrorMessage( e.Message );
} }public static int ShowResults( string sortby )
{int index = 0;
switch ( sortby )
{case "J": // Sort by # jobs
index = 2;
break;
case "N": // Sort by name
index = 0;
break;
case "S": // Sort by status
index = 1;
break;
}if ( sortby == "N" ) // Sort only by name, ascending
{ printerlist = printerlist.OrderBy( arr => arr[0] )
.ToList( );
actionslist = actionslist.OrderBy( arr => arr[0] )
.ToList( );
}else // Sort by status or # jobs, descending, then by name, ascending
{ printerlist = printerlist.OrderByDescending( arr => arr[index] )
.ThenBy( arr => arr[0] )
.ToList( );
actionslist = actionslist.OrderByDescending( arr => arr[index] )
.ThenBy( arr => arr[0] )
.ToList( );
}foreach ( string[] properties in printerlist )
{string printer = properties[0];
//UInt32 jobs = Convert.ToUInt32( properties[2] );string jobs = properties[2];
string status = properties[1];
// check if the action really was invokedbool takeaction = ( (( jobs != "Unknown" && !String.IsNullOrWhiteSpace(jobs) && jobs != "0" ) && actionFlush ) || ( actionPause && status != WMIPrinterStatus.Paused.ToString( ) ) || ( actionResume && status != WMIPrinterStatus.Unknown.ToString( ) ) );
if ( takeaction )
{string newstatus = WMIPrinterStatus.Other.ToString( );
//UInt32 newjobs = 0;string newjobs = "0";
string result = WMIActionResult.Other.ToString( );
foreach ( string[] actions in actionslist )
{if ( actions[0] == properties[0] ) // read the actions list for this printer
{newstatus = actions[1];
//newjobs = Convert.ToUInt32( actions[2] );newjobs = actions[2];
result = actions[3];
} }Console.Write( "Printer : " );
if ( result != WMIActionResult.Success.ToString( ) )
{Console.ForegroundColor = ConsoleColor.Yellow; // if unsuccessful, show printer name in yellow
}Console.WriteLine( printer );
Console.ResetColor( );
Console.WriteLine( "Printjobs : {0}", jobs );
Console.WriteLine( "Status : {0}", status );
if ( actionFlush )
{Console.Write( "Flush printjobs . . . " );
} else {Console.Write( "{0} printing . . . ", ( actionPause ? "Pause" : "Resume" ) );
}if ( result != WMIActionResult.Success.ToString( ) )
{Console.ForegroundColor = ConsoleColor.Red; // if unsuccessful, show result in red
}Console.WriteLine( result );
Console.ResetColor( );
if ( actionFlush )
{Console.WriteLine( "Printjobs : {0}", newjobs );
} else {Console.WriteLine( "Status : {0}", newstatus );
} }else // no action was invoked, just list status
{Console.WriteLine( "Printer : {0}", printer );
Console.WriteLine( "Printjobs : {0}", jobs );
Console.WriteLine( "Status : {0}", status );
}Console.WriteLine( );
}return 0;
}public static string SwitchString( char sw )
{return SwitchString( sw.ToString( ) );
}public static string SwitchString( string sw )
{if ( switchchar == '-' )
{return String.Format( "{0}{1}", switchchar, sw.ToLower( ) );
} else {return String.Format( "{0}{1}", switchchar, sw.ToUpper( ) );
} }static bool VerifyRegExPattern( string testpattern )
{ // Test validity of RegEx pattern // Based on http://stackoverflow.com/questions/218680/can-i-test-if-a-regex-is-valid-in-c-sharp-without-throwing-exceptionif ( String.IsNullOrWhiteSpace( testpattern ) )
{return false;
} try {Regex.Match( "", testpattern );
return true;
}catch ( ArgumentException )
{return false;
} }public static int ErrorMessage( params string[] errmsg )
{ /* Printing.exe, Version 3.04 Pause or resume printing, or flush all queued printjobs on the specified printer(s), or list all printers, their status and number of print jobs Usage: Printing.exe printer action [ option ] Printer: /A use All printers /D use Default printer /X:"regex" use all printers matching the regular eXpression name use the specified printer Action: /F Flush queued print jobs /L List printer name, status, and number of queued print jobs /P Pause printing /R Resume printing Option: /S:(N|S|J) Sort by printer Name (default), Status or # print Jobs Examples: PRINTING /D /P Pause printing on Default printer PRINTING PDF995 /F Flush print jobs of the printer named PDF995 PRINTING /A /R Resume printing on All printers PRINTING /L /S:J List all printers, Sort by # queued print Jobs Notes: Use doublequotes if the printer name contains spaces. With /L and no printer specified, All printers (/A) will be assumed. Credits: LINQ code to sort List of string arrays by Tim Schmelter: http://stackoverflow.com/questions/23873378#23873402 Test for validity of regex pattern based on code from: http://stackoverflow.com/questions/218680 PrinterInfo code by Bas van der Woude. Written by Rob van der Woude http://www.robvanderwoude.com */if ( errmsg.Length > 0 )
{List<string> errargs = new List<string>( errmsg );
errargs.RemoveAt( 0 );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.Write( "ERROR:\t" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
Console.ResetColor( );
}Console.Error.WriteLine( );
Console.Error.WriteLine( "Printing.exe, Version {0}", progver );
Console.Error.WriteLine( "Pause or resume printing, or flush all queued printjobs on the specified" );
Console.Error.WriteLine( "printer(s), or list all printers, their status and number of print jobs" );
Console.Error.WriteLine( );
Console.Error.Write( "Usage: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "Printing.exe printer action [ option ]" );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.Write( "Printer: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "{0}", SwitchString( "A" ) );
Console.ResetColor( );
Console.Error.Write( " use " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "A" );
Console.ResetColor( );
Console.Error.WriteLine( "ll printers" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " {0}", SwitchString( "D" ) );
Console.ResetColor( );
Console.Error.Write( " use " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "D" );
Console.ResetColor( );
Console.Error.WriteLine( "efault printer" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " {0}:\"regex\"", SwitchString( "X" ) );
Console.ResetColor( );
Console.Error.Write( " use all printers matching the regular e" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "X" );
Console.ResetColor( );
Console.Error.WriteLine( "pression" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " name" );
Console.ResetColor( );
Console.Error.WriteLine( " use the specified printer" );
Console.Error.Write( "Action: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "{0} F", SwitchString( "F" ) );
Console.ResetColor( );
Console.Error.WriteLine( "lush queued print jobs" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " {0} L", SwitchString( "L" ) );
Console.ResetColor( );
Console.Error.WriteLine( "ist printer name, status, and number of queued print jobs" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " {0} P", SwitchString( "P" ) );
Console.ResetColor( );
Console.Error.WriteLine( "ause printing" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " {0} R", SwitchString( "R" ) );
Console.ResetColor( );
Console.Error.WriteLine( "esume printing" );
Console.Error.Write( "Option: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "{0} S", SwitchString( "S:(N|S|J)" ) );
Console.ResetColor( );
Console.Error.Write( "ort by printer " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "N" );
Console.ResetColor( );
Console.Error.Write( "ame (default), " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "S" );
Console.ResetColor( );
Console.Error.Write( "tatus or # print " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "J" );
Console.ResetColor( );
Console.Error.WriteLine( "obs" );
Console.Error.WriteLine( );
Console.Error.Write( "Examples: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "PRINTING {0} {1} P", SwitchString( "D" ), SwitchString( "P" ) );
Console.ResetColor( );
Console.Error.Write( "ause printing on " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "D" );
Console.ResetColor( );
Console.Error.WriteLine( "efault printer" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " PRINTING PDF995 {0} F", SwitchString( "F" ) );
Console.ResetColor( );
Console.Error.Write( "lush print jobs of the printer named " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "PDF995" );
Console.ResetColor( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " PRINTING {0} {1} R", SwitchString( "A" ), SwitchString( "R" ) );
Console.ResetColor( );
Console.Error.Write( "esume printing on " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "A" );
Console.ResetColor( );
Console.Error.WriteLine( "ll printers" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " PRINTING {0} {1} L", SwitchString( "L" ), SwitchString( "S:J" ) );
Console.ResetColor( );
Console.Error.Write( "ist all printers, " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "S" );
Console.ResetColor( );
Console.Error.Write( "ort by # queued print " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "J" );
Console.ResetColor( );
Console.Error.WriteLine( "obs" );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Notes: Use doublequotes if the printer name contains spaces." );
Console.Error.Write( " With " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( SwitchString( "L" ) );
Console.ResetColor( );
Console.Error.Write( " and no printer specified, " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "A" );
Console.ResetColor( );
Console.Error.Write( "ll printers (" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( SwitchString( "A" ) );
Console.ResetColor( );
Console.Error.WriteLine( ") will be assumed." );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Credits: LINQ code to sort List of string arrays by Tim Schmelter:" );
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.Error.WriteLine( " http://stackoverflow.com/questions/23873378#23873402" );
Console.ResetColor( );
Console.Error.WriteLine( " Test for validity of regex pattern based on code from:" );
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.Error.WriteLine( " http://stackoverflow.com/questions/218680" );
Console.ResetColor( );
Console.Error.WriteLine( " PrinterInfo code by Bas van der Woude." );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Written by Rob van der Woude" );
Console.Error.WriteLine( "http://www.robvanderwoude.com" );
return 1;
} } #region PrinterInfo // Author : Bas van der Woude // Date : 2011-03-31public class PrinterInfo
{public string Name { get; set; }
public uint Status { get; set; }
public uint PrintJobCount { get; set; }
public WMIActionResult ActionResult { get; set; }
}public enum WMIActionResult
{Success = 0,
AccessDenied = 5,
Other = 8
}public enum WMIPrinterStatus
{Other = 1,
Unknown = 2,
Idle = 3,
Printing = 4,
Warmup = 5,
StoppedPrinting = 6,
Offline = 7,
Paused = 8,
Error = 9,
Busy = 10,
NotAvailable = 11,
Waiting = 12,
Processing = 13,
Initialization = 14,
PowerSave = 15,
PendingDeletion = 16,
IOActive = 17,
ManualFeed = 18
} #endregion PrinterInfo}page last modified: 2025-10-11; loaded in 0.0172 seconds