(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 Variables
public 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 Variables
public static int Main( string[] args )
{
try
{
#region Initialize Variables
bool 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 Parsing
if ( 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 Printers
string 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 Printers
foreach ( ManagementObject queryObj in searcher1.Get( ) )
{
printer = queryObj["DeviceID"].ToString( ); // printer name
if ( !useRegex || new Regex( pattern, RegexOptions.IgnoreCase ).IsMatch( printer ) )
{
#region Investigate Current Printer Status
printerscount += 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 jobs
string 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 Status
takeaction = ( ( actionFlush && jobs > 0 ) || ( actionPause && status != WMIPrinterStatus.Paused ) || ( actionResume && status != WMIPrinterStatus.Unknown ) );
if ( takeaction )
{
#region Invoke Action
WMIActionResult result = (WMIActionResult) Convert.ToUInt32( queryObj.InvokeMethod( action, null ) );
WMIPrinterStatus newstatus = WMIPrinterStatus.Unknown;
#endregion Invoke Action
#region Investigate New Status After Action
if ( 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 Found
if ( 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 results
return ShowResults( sortby );
#endregion Display The results
}
catch ( Exception e )
{
#if DEBUG
return ErrorMessage( "{0}\n\t{1}", e.Message, e.StackTrace );
#endif
return 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 invoked
bool 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-exception
if ( 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-31
public 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: 2024-04-16; loaded in 0.0201 seconds