I have a program that should monitor the statuses of Printers and should update them in real-time, but for some reason when i start the program, statuses do show up, but they are not changing once the printer starts printing etc. Right now some printers do show up with Error,Ready and Offline ant they are correct when i compare it within the windows Printers and Scanners.
This is my PrinterManager class
using PrinterApp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Printing;
using System.Windows.Navigation;
using System.Diagnostics;
using System.ComponentModel;
using PrinterApp.Views;
using System.Runtime.CompilerServices;
namespace PrinterApp.Managers
{
class PrinterManager : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
private string _printServerName;
public string printServerName
{
get => _printServerName;
set
{
if (_printServerName != value)
{
_printServerName = value;
OnPropertyChanged();
Debug.WriteLine($"PrinterManager.printServerName set to: {_printServerName}");
}
}
}
public PrinterManager()
{
//_printServerName = string.Empty;
Debug.WriteLine($"PrinterManager initialized with printServerName: {printServerName}");
}
public List<string> GetPrintersNoServer()
{
List<string> printerNames = new List<string>();
LocalPrintServer printServer = new LocalPrintServer();
PrintQueueCollection printQueues = printServer.GetPrintQueues(new[]
{
EnumeratedPrintQueueTypes.Connections,
EnumeratedPrintQueueTypes.Local,
});
foreach (PrintQueue printQueue in printQueues)
{
printerNames.Add(printQueue.Name);
}
return printerNames;
}
public string GetPrinterStatusNoServer(string printerName)
{
var printServer = new System.Printing.LocalPrintServer();
var printQueue = printServer.GetPrintQueue(printerName);
printQueue.Refresh();
var queueStatus = printQueue.QueueStatus;
if (queueStatus.HasFlag(PrintQueueStatus.PaperProblem))
return "Paper Problem";
if (queueStatus.HasFlag(PrintQueueStatus.NoToner))
return "No Toner";
if (queueStatus.HasFlag(PrintQueueStatus.DoorOpen))
return "Door Open";
if (queueStatus.HasFlag(PrintQueueStatus.Error))
return "Error";
if (queueStatus.HasFlag(PrintQueueStatus.Paused))
return "Paused";
if (queueStatus.HasFlag(PrintQueueStatus.PendingDeletion))
return "Pending Deletion";
if (queueStatus.HasFlag(PrintQueueStatus.ServerUnknown))
return "Server Unknown";
if (queueStatus.HasFlag(PrintQueueStatus.Offline))
return "Offline";
if (queueStatus.HasFlag(PrintQueueStatus.OutOfMemory))
return "Out of Memory";
if (queueStatus.HasFlag(PrintQueueStatus.PaperOut))
return "Paper Out";
if (queueStatus.HasFlag(PrintQueueStatus.OutputBinFull))
return "Output Bin Full";
if (queueStatus.HasFlag(PrintQueueStatus.PaperJam))
return "Paper Jam";
if (queueStatus.HasFlag(PrintQueueStatus.UserIntervention))
return "User Intervention";
if (queueStatus.HasFlag(PrintQueueStatus.IOActive))
return "IO Active";
if (queueStatus.HasFlag(PrintQueueStatus.Busy))
return "Busy";
if (queueStatus.HasFlag(PrintQueueStatus.Printing))
return "Printing";
else
return "Ready";
}
public List<string> GetPrinters()
{
List<string> printerNames = new List<string>();
System.Printing.PrintServer printServer = new System.Printing.PrintServer(printServerName);
PrintQueueCollection printQueues = printServer.GetPrintQueues(new[]
{
EnumeratedPrintQueueTypes.Connections,
//EnumeratedPrintQueueTypes.Local,
}) ;
foreach (PrintQueue printQueue in printQueues)
{
printerNames.Add(printQueue.Name);
}
return printerNames;
}
public string GetPrinterStatus(string printerName)
{
var printServer = new System.Printing.PrintServer(printServerName);
var printQueue = printServer.GetPrintQueue(printerName);
printQueue.Refresh();
var queueStatus = printQueue.QueueStatus;
if (queueStatus.HasFlag(PrintQueueStatus.PaperProblem))
return "Paper Problem";
if (queueStatus.HasFlag(PrintQueueStatus.NoToner))
return "No Toner";
if (queueStatus.HasFlag(PrintQueueStatus.DoorOpen))
return "Door Open";
if (queueStatus.HasFlag(PrintQueueStatus.Error))
return "Error";
if (queueStatus.HasFlag(PrintQueueStatus.Paused))
return "Paused";
if (queueStatus.HasFlag(PrintQueueStatus.PendingDeletion))
return "Pending Deletion";
if (queueStatus.HasFlag(PrintQueueStatus.ServerUnknown))
return "Server Unknown";
if (queueStatus.HasFlag(PrintQueueStatus.Offline))
return "Offline";
if (queueStatus.HasFlag(PrintQueueStatus.OutOfMemory))
return "Out of Memory";
if (queueStatus.HasFlag(PrintQueueStatus.PaperOut))
return "Paper Out";
if (queueStatus.HasFlag(PrintQueueStatus.OutputBinFull))
return "Output Bin Full";
if (queueStatus.HasFlag(PrintQueueStatus.PaperJam))
return "Paper Jam";
if (queueStatus.HasFlag(PrintQueueStatus.UserIntervention))
return "User Intervention";
if (queueStatus.HasFlag(PrintQueueStatus.IOActive))
return "IO Active";
if (queueStatus.HasFlag(PrintQueueStatus.Busy))
return "Busy";
if (queueStatus.HasFlag(PrintQueueStatus.Printing))
return "Printing";
if (queueStatus.HasFlag(PrintQueueStatus.Processing))
return "Processing";
//if (queueStatus.HasFlag(PrintQueueStatus.None))
// return "None";
var jobs = printQueue.GetPrintJobInfoCollection();
if (jobs == null)
{
return "Ready";
}
foreach (var job in jobs)
{
if (job.JobStatus.HasFlag(PrintJobStatus.Printing))
{
return "Printing";
}
if (job.JobStatus.HasFlag(PrintJobStatus.Spooling))
{
return "Spooling";
}
}
return "Ready";
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
And this is my ViewModel class
using PrinterApp.Managers;
using PrinterApp.Models;
using PrinterApp.Views;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
namespace PrinterApp.ViewModel
{
public class PrinterListViewModel:INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
private DispatcherTimer _timer;
private PrinterManager _printerManager = new PrinterManager();
private string? _serverName;
public string? serverName
{
get { return _serverName; }
set
{
if (_serverName != value)
{
_serverName = value;
}
}
}
//Printers printers = new Printers();
public PrinterListViewModel(string serverName)
{
_printerManager.printServerName = serverName;
this.serverName = serverName;
LoadPrinters();
StartStatusRefreshTimer();
}
public PrinterListViewModel()
{
Debug.WriteLine("BEZ SERVERA");
LoadPrintersNoServer();
StartStatusRefreshTimer();
}
public ObservableCollection<Printers> _printerList = new ObservableCollection<Printers>();
public ObservableCollection<Printers> PrinterList
{
get { return _printerList; }
set
{
_printerList = value;
OnPropertyChanged();
}
}
private void LoadPrintersNoServer()
{
try
{
var printers = _printerManager.GetPrintersNoServer();
foreach (var printer in printers)
{
var status = _printerManager.GetPrinterStatusNoServer(printer);
_printerList.Add(new Printers
{
Name = printer,
Status = status
});
}
}
catch (Exception ex)
{
MessageBox.Show($"An error occurred while loading printers: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void LoadPrinters()
{
try
{
var printers = _printerManager.GetPrinters();
foreach (var printer in printers)
{
var status = _printerManager.GetPrinterStatus(printer);
_printerList.Add(new Printers
{
Name = printer,
Status = status
});
}
}
catch(Exception ex)
{
MessageBox.Show($"An error occurred while loading printers: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void StartStatusRefreshTimer()
{
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromSeconds(0.5);
_timer.Tick += RefreshPrinterStatuses;
_timer.Start();
Debug.WriteLine("REFRESHED");
}
private void RefreshPrinterStatuses(object sender, EventArgs e)
{
try
{
foreach (var printer in _printerList)
{
var status = string.IsNullOrEmpty(serverName)
? _printerManager.GetPrinterStatusNoServer(printer.Name)
: _printerManager.GetPrinterStatus(printer.Name);
if (printer.Status != status)
{
Debug.WriteLine($"{DateTime.Now} {printer.Name} REFRESHED STATUS FROM {printer.Status} TO {status}");
printer.Status = status;
}
else
{
if(printer.Name=="PRODAJA110 C3320i")
Debug.WriteLine($"{DateTime.Now} {printer.Name} STATUS UNCHANGED: {status}");
}
}
}
catch (Exception ex)
{
Debug.WriteLine($"An error occurred while refreshing printer statuses: {ex.Message}");
}
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
//Debug.WriteLine($"OnPropertyChanged called for: {propertyName}");
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
//Debug.WriteLine(serverName);
}
}
}
As you can see i had to mix PrintQueueStatus with PrintJobInfoCollection for my program to change the status from Ready to Printing.
foreach (var job in jobs)
{
if (job.JobStatus.HasFlag(PrintJobStatus.Printing))
{
return "Printing";
}
if (job.JobStatus.HasFlag(PrintJobStatus.Spooling))
{
return "Spooling";
}
}
Without this statuses do not change. Am i missing something with the PrintQueueStatus enum and how it works?
Boris Brajkov is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.