目录
1、PrinterCommunicate用于连接打印机并发送指令:
2、WindowsPrintQueue用于获取打印机的型号,以及得到打印机的WindowsPrintQueue:
3、PrinterPropertyManager用于管理打印机的状态以及查询修改打印机属性:
4、获取已安装的打印机驱动:
新项目中牵涉到对打印机的一些操作,最重要的莫过于获取打印机的状态,IP等信息,代码量不大,但是也是自己花了一点时间总结出来的,希望能帮助需要的朋友。
1、PrinterCommunicate用于连接打印机并发送指令:
public class PrinterCommunicate{public bool CheckNetWorkConnection(string strPrinterIP, int intPrinterPort) {System.Net.Sockets.TcpClient Zebraclient = new TcpClient();try{Zebraclient.Connect(strPrinterIP, intPrinterPort);return Zebraclient.Connected;}catch{return false;}}public bool SendZPL_ViaNetwork(string strPrinterIP, int intPrinterPort, string strPrinterCommand, out string strOutMsg){strOutMsg = "";System.Net.Sockets.TcpClient Zebraclient = new TcpClient();try{Zebraclient.SendTimeout = 1500;Zebraclient.ReceiveTimeout = 1500;//defining ip address and port numberZebraclient.Connect(strPrinterIP, intPrinterPort);if (Zebraclient.Connected == true){//send and receive illustrated belowNetworkStream mynetworkstream;StreamReader mystreamreader;StreamWriter mystreamwriter;mynetworkstream = Zebraclient.GetStream();mystreamreader = new StreamReader(mynetworkstream);mystreamwriter = new StreamWriter(mynetworkstream);mystreamwriter.WriteLine(strPrinterCommand);mystreamwriter.Flush();char[] mk = null;mk = new char[256];mystreamreader.Read(mk, 0, mk.Length);string data1 = new string(mk);strOutMsg = data1;Zebraclient.Close();return true;}else{strOutMsg = "Connection failed";return false;}}catch (Exception ex){Log.WriteLogToFile("IPP_PCL", "PrinterCommunicate.cs -- SendZPL_ViaNetwork", "-99", ex.Message);strOutMsg = "EXCEPTION_ERROR";}return false;}}
2、WindowsPrintQueue用于获取打印机的型号,以及得到打印机的WindowsPrintQueue:
public class WindowsPrintQueue{/// <summary>/// whether the two printer is same model./// </summary>/// <param name="printerName1"></param>/// <param name="printerName2"></param>/// <returns></returns>public bool IsSameModel(string printerName1, string printerName2){return GetPrinterModel(printerName1).Equals(GetPrinterModel(printerName2));}/// <summary>/// whether the printer is zebra model./// </summary>/// <param name="printerName1"></param>/// <param name="printerName2"></param>/// <returns></returns>public bool IsZebraPrinter(string printerName){string zebraModel = "ZEBRA";return GetPrinterModel(printerName).Contains(zebraModel);}/// <summary>/// Return printer model/// </summary>/// <param name="printerName"></param>/// <returns></returns>public string GetPrinterModel(string printerName){string model = string.Empty;System.Printing.PrintQueue printQueue = GetPrintQueue(printerName);if (printQueue != null){//Get printer modelif (printQueue.Description.IndexOf(",") == printQueue.Description.LastIndexOf(",")){model = printQueue.Description.Substring(printQueue.Description.IndexOf(",") + 1,printQueue.Description.LastIndexOf(",") - printQueue.Description.IndexOf(",") - 1);}else{model = printQueue.Description.Substring(printQueue.Description.IndexOf(",") + 1);}}return model;}/// <summary>/// Get Windows Print Queue via printer name/// </summary>/// <param name="printerName"></param>/// <returns></returns>public System.Printing.PrintQueue GetPrintQueue(string printerName){System.Printing.PrintQueue printQueue = null;PrintServer server = new PrintServer(printerName);foreach (System.Printing.PrintQueue pq in server.GetPrintQueues()){if (pq.FullName.Equals(printerName)){printQueue = pq;}}return printQueue;}/// <summary>/// Get Windows Print Queue via printer name/// 如果两个printer指向的是同一个物理打印机,则如果copy1的printQueue已经打开,///则发送到copy2的打印job也会添加到已经打开的copy1的printQueue中./// </summary>/// <param name="printerName"></param>/// <returns></returns>public System.Printing.PrintQueue GetOpenedPrintQueueOfSameModel(string printerName){System.Printing.PrintQueue doorOpenedprintQueue = null;System.Printing.PrintQueue currentPrinterPrintQueue = null;PrintServer server = new PrintServer(printerName);foreach (System.Printing.PrintQueue pq in server.GetPrintQueues()){if (pq.FullName.Equals(printerName)){currentPrinterPrintQueue = pq;}else{if (IsSameModel(printerName, pq.FullName)){if (pq.IsDoorOpened){doorOpenedprintQueue = pq;break;}}}}if (doorOpenedprintQueue != null){return doorOpenedprintQueue;}else{return currentPrinterPrintQueue;}}}
3、PrinterPropertyManager用于管理打印机的状态以及查询修改打印机属性:
class PrinterPropertyManager{/// <summary>/// 获取打印机的IP地址和端口号/// </summary>/// <param name="printerName">打印机名称</param>public KeyValuePair<string, int> GetPrinterIPAndPort(string printerName){string port = GetPrinterPropertyValue(printerName, "PortName");//Query portName's property from regeditstring[] portQuerys = GetPortQuerys(port);foreach (var portQuery in portQuerys){RegistryKey portKey = Registry.LocalMachine.OpenSubKey(portQuery, RegistryKeyPermissionCheck.Default, System.Security.AccessControl.RegistryRights.QueryValues);if (portKey != null){/* * 取IP的时候要特别注意,如果端口类型为"Advanced Port Monitor",那么IP地址会保存到IPAddress属性中 * 如果端口类型为"Standard Tcp/Ip Port",那么IP地址会保存到HostName属性中。*/object IPValue = portKey.GetValue("IPAddress", String.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames);object portValue = portKey.GetValue("PortNumber", String.Empty,RegistryValueOptions.DoNotExpandEnvironmentNames);if (IPValue != null && portValue != null){return new KeyValuePair<string, int>(IPValue.ToString(), (Int32)portValue);}}}return new KeyValuePair<string, int>();}/// <summary>/// determine whether the printer is network printer./// </summary>public bool IsNetWorkPrinter(string printer){string port = GetPrinterPropertyValue(printer, "PortName");//Query portName's property from regeditstring[] portQuerys = GetNetWorkPortQuerys(port);foreach (var portQuery in portQuerys){RegistryKey portKey = Registry.LocalMachine.OpenSubKey(portQuery, RegistryKeyPermissionCheck.Default, System.Security.AccessControl.RegistryRights.QueryValues);if (portKey != null){return true;}}return false;}private string[] GetNetWorkPortQuerys(string portName){return new string[] {@"System\CurrentControlSet\Control\Print\Monitors\Advanced Port Monitor\Ports\" + portName,@"System\CurrentControlSet\Control\Print\Monitors\Standard TCP/IP Port\Ports\" + portName};}private string[] GetPortQuerys(string portName){return new string[] {@"System\CurrentControlSet\Control\Print\Monitors\Advanced Port Monitor\Ports\" + portName,@"System\CurrentControlSet\Control\Print\Monitors\Local Port\Ports\" + portName,@"System\CurrentControlSet\Control\Print\Monitors\Standard TCP/IP Port\Ports\" + portName,@"System\CurrentControlSet\Control\Print\Monitors\USB Monitor\Ports\" + portName,@"System\CurrentControlSet\Control\Print\Monitors\WSD Port\Ports\" + portName,};}/// <summary>/// get printer property value/// 使用WMI查询打印机的信息,需要打开windows management instrumentation服务/// </summary>public string GetPrinterPropertyValue(string printerName, string propertyName){string propertyValue = string.Empty;//Query printer's portName from WIN32_Printerstring query = string.Format("SELECT * from Win32_Printer WHERE Name = '{0}'", printerName);ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);ManagementObjectCollection managementObjects = searcher.Get();foreach (ManagementObject managementObject in managementObjects){PropertyData propertyData = managementObject.Properties[propertyName];if (propertyData != null){propertyValue = propertyData.Value.ToString();}}return propertyValue;}/// <summary>/// change printer property value/// </summary>public void SetPrinterPropertyValue(string printerName, string propertyName, string propertyValue){//Query printer's portName from WIN32_Printerstring query = string.Format("SELECT * from Win32_Printer WHERE Name = '{0}'", printerName);ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);ManagementObjectCollection managementObjects = searcher.Get();foreach (ManagementObject managementObject in managementObjects){PropertyData propertyData = managementObject.Properties[propertyName];if (propertyData != null){propertyData.Value = propertyValue;managementObject.Put();}}}/// <summary>/// whether the port is existed/// 检查某个打印端口是否存在/// </summary>/// <param name="printerName"></param>/// <param name="port"></param>/// <returns></returns>public bool IsPortExisted(string printerName,string port){string propertyName = "PortName";string currentPort = null;try{currentPort = GetPrinterPropertyValue(printerName, propertyName);SetPrinterPropertyValue(printerName, propertyName, port);SetPrinterPropertyValue(printerName, propertyName, currentPort);}catch (Exception ex){return false;}return true;}/// <summary>/// 获取打印机名字的列表/// </summary>public ArrayList GetPrinterNames(){ArrayList result = new ArrayList();foreach (string ss in PrinterSettings.InstalledPrinters){result.Add(ss);}return result;}/// <summary>/// 获取打印机状态/// </summary>/// <param name="printerName">打印机名称</param>public PrinterStatus GetPrinterStatus(string printerName,out bool isError,out string errorDescription){//init return variableisError = false;errorDescription = string.Empty;PrinterStatus printerStatus = PrinterStatus.Idle;if (IsNetWorkPrinter(printerName)){KeyValuePair<string, int> ipPortKeyValuePair = GetPrinterIPAndPort(printerName);PrinterCommunicate printerCommunicate = new PrinterCommunicate();if (printerCommunicate.CheckNetWorkConnection(ipPortKeyValuePair.Key, ipPortKeyValuePair.Value)){WindowsPrintQueue winowsPrintQueue = new WindowsPrintQueue();if (winowsPrintQueue.IsZebraPrinter(printerName)){//get actual status of zebra printer via zebra commandif(IsPause(ipPortKeyValuePair.Key, ipPortKeyValuePair.Value)){printerStatus = PrinterStatus.Paused;}string errorMsg = string.Empty;if(IsError(ipPortKeyValuePair.Key, ipPortKeyValuePair.Value, out errorMsg)){isError = true;errorDescription = GetZebraPrinterErrorStatusDescription(errorMsg);}}}else{//not connectedprinterStatus = PrinterStatus.Offline;}}return printerStatus;}/// <summary>/// determine whether the network printer is in pause.Only for zebra model printer/// </summary>private bool IsPause(string ip, int port){string strOutMsg = null;string zebraCommand = "^XA~HS^XZ";PrinterCommunicate printerCommunicate = new PrinterCommunicate();if (printerCommunicate.SendZPL_ViaNetwork(ip, port, zebraCommand, out strOutMsg)){//split retMsg with "\r\n"string[] retMsgs = strOutMsg.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);if (retMsgs != null){string retFirstMsgItem = retMsgs[0];string[] retFirstMsgItems = retFirstMsgItem.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);return "1".Equals(retFirstMsgItems[2]);}}return false;}/// <summary>/// determine whether the network printer is in error.only for zebra model printer/// </summary>/// <param name="ip"></param>/// <param name="port"></param>/// <param name="strOutMsg"></param>/// <returns></returns>private bool IsError(string ip, int port, out string strOutMsg){strOutMsg = string.Empty;string zebraCommand = "^XA~HQES^XZ";PrinterCommunicate printerCommunicate = new PrinterCommunicate();if (printerCommunicate.SendZPL_ViaNetwork(ip, port, zebraCommand, out strOutMsg)){//split retMsg with "\r\n"string[] retMsgs = strOutMsg.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);if (retMsgs != null){for (int i = 0; i < retMsgs.Length; i++){string retMsgItem = retMsgs[i];if (string.IsNullOrEmpty(retMsgItem) || !retMsgItem.Contains(":")) { continue; }string[] retMsgItemSplited = retMsgItem.Split(new string[] { ":" }, StringSplitOptions.RemoveEmptyEntries);if (retMsgItemSplited == null || retMsgItemSplited.Length == 0) { continue; }string errorMsg = retMsgItemSplited[1].Trim();if (!string.IsNullOrEmpty(errorMsg)){string errorFlag = errorMsg.Substring(0, 1);if ("1".Equals(errorFlag)){strOutMsg = errorMsg;return true;}}}}}return false;}/// <summary>/// get actual status of zebra printer via zebra command./// </summary>/// <param name="ip"></param>/// <param name="port"></param>/// <returns></returns>private string GetZebraPrinterErrorStatusDescription(string errorMsg){StringBuilder status = new StringBuilder();//error happendstring nibble1 = errorMsg.Substring(errorMsg.Length - 1, 1);string nibble2 = errorMsg.Substring(errorMsg.Length - 2, 1);string nibble3 = errorMsg.Substring(errorMsg.Length - 3, 1);if (!"0".Equals(nibble1)){Dictionary<int, string> nibble1ErrorDictionary = new Dictionary<int, string>();nibble1ErrorDictionary.Add(1, "Midea Out");nibble1ErrorDictionary.Add(2, "Ribbon Out");nibble1ErrorDictionary.Add(4, "Head Open");nibble1ErrorDictionary.Add(8, "Cutter Fault");status.Append(GetErrorDescriptionFromNibble(nibble1, nibble1ErrorDictionary));}if (!"0".Equals(nibble2)){Dictionary<int, string> nibble2ErrorDictionary = new Dictionary<int, string>();nibble2ErrorDictionary.Add(1, "Printhead Over Temperature");nibble2ErrorDictionary.Add(2, "Motor Over Temperature");nibble2ErrorDictionary.Add(4, "Bad Printhead Element");nibble2ErrorDictionary.Add(8, "Printhead Detection Error");status.Append(GetErrorDescriptionFromNibble(nibble1, nibble2ErrorDictionary));}if (!"0".Equals(nibble3)){Dictionary<int, string> nibble3ErrorDictionary = new Dictionary<int, string>();nibble3ErrorDictionary.Add(1, "Invalid Firmware Config");nibble3ErrorDictionary.Add(2, "Printhead Thermistor Open");status.Append(GetErrorDescriptionFromNibble(nibble1, nibble3ErrorDictionary));}string strStatus = status.ToString();return strStatus.Substring(0, strStatus.Length - 1);}private StringBuilder GetErrorDescriptionFromNibble(string nibble, Dictionary<int, string> statusDictionary){int intNibble = Convert.ToInt32(nibble);StringBuilder status = new StringBuilder();if (statusDictionary != null){foreach (var statusKV in statusDictionary){if ((intNibble & statusKV.Key) == statusKV.Key){status.Append(statusKV.Value);status.Append(",");}}}return status;}}public enum PrinterStatus{Other = 1,Unknown = 2,Idle = 3,Printing = 4,Warmup = 5,Paused = 6,Offline = 7}
4、获取已安装的打印机驱动:
public IEnumerable<string> GetPrintDrivers(){var dirvers = new List<string>();//Query printer's portName from WIN32_Printerstring query = string.Format("SELECT * from Win32_PrinterDriver");var searcher = new ManagementObjectSearcher(query);ManagementObjectCollection managementObjects = searcher.Get();foreach (ManagementObject managementObject in managementObjects){var name = managementObject.Properties["Name"].Value;dirvers.Add(name.ToString());}return dirvers;}