新项目中牵涉到对打印机的一些操作,最重要的莫过于获取打印机的状态,IP等信息,代码量不大,但是也是自己花了一点时间总结出来的,希望能帮助需要的朋友。
PrinterCommunicate用于连接打印机并发送指令
1 public class PrinterCommunicate 2 { 3 4 public bool CheckNetWorkConnection(string strPrinterIP, int intPrinterPort) 5 { 6 System.Net.Sockets.TcpClient Zebraclient = new TcpClient(); 7 try 8 { 9 Zebraclient.Connect(strPrinterIP, intPrinterPort); 10 return Zebraclient.Connected; 11 } 12 catch 13 { 14 return false; 15 } 16 } 17 18 public bool SendZPL_ViaNetwork(string strPrinterIP, int intPrinterPort, string strPrinterCommand, out string strOutMsg) 19 { 20 strOutMsg = ""; 21 22 System.Net.Sockets.TcpClient Zebraclient = new TcpClient(); 23 try 24 { 25 Zebraclient.SendTimeout = 1500; 26 Zebraclient.ReceiveTimeout = 1500; 27 //defining ip address and port number 28 Zebraclient.Connect(strPrinterIP, intPrinterPort); 29 30 if (Zebraclient.Connected == true) 31 { 32 //send and receive illustrated below 33 NetworkStream mynetworkstream; 34 StreamReader mystreamreader; 35 StreamWriter mystreamwriter; 36 mynetworkstream = Zebraclient.GetStream(); 37 mystreamreader = new StreamReader(mynetworkstream); 38 mystreamwriter = new StreamWriter(mynetworkstream); 39 40 mystreamwriter.WriteLine(strPrinterCommand); 41 mystreamwriter.Flush(); 42 char[] mk = null; 43 mk = new char[256]; 44 mystreamreader.Read(mk, 0, mk.Length); 45 string data1 = new string(mk); 46 strOutMsg = data1; 47 Zebraclient.Close(); 48 49 return true; 50 } 51 else 52 { 53 strOutMsg = "Connection failed"; 54 return false; 55 } 56 } 57 catch (Exception ex) 58 { 59 Log.WriteLogToFile("IPP_PCL", "PrinterCommunicate.cs -- SendZPL_ViaNetwork", "-99", ex.Message); 60 strOutMsg = "EXCEPTION_ERROR"; 61 } 62 63 return false; 64 } 65 66 }
WindowsPrintQueue用于获取打印机的型号,以及得到打印机的WindowsPrintQueue
1 public class WindowsPrintQueue 2 { 3 /// <summary> 4 /// whether the two printer is same model. 5 /// </summary> 6 /// <param name="printerName1"></param> 7 /// <param name="printerName2"></param> 8 /// <returns></returns> 9 public bool IsSameModel(string printerName1, string printerName2) 10 { 11 return GetPrinterModel(printerName1).Equals(GetPrinterModel(printerName2)); 12 } 13 14 /// <summary> 15 /// whether the printer is zebra model. 16 /// </summary> 17 /// <param name="printerName1"></param> 18 /// <param name="printerName2"></param> 19 /// <returns></returns> 20 public bool IsZebraPrinter(string printerName) 21 { 22 string zebraModel = "ZEBRA"; 23 return GetPrinterModel(printerName).Contains(zebraModel); 24 } 25 26 /// <summary> 27 /// Return printer model 28 /// </summary> 29 /// <param name="printerName"></param> 30 /// <returns></returns> 31 public string GetPrinterModel(string printerName) 32 { 33 string model = string.Empty; 34 System.Printing.PrintQueue printQueue = GetPrintQueue(printerName); 35 if (printQueue != null) 36 { 37 //Get printer model 38 if (printQueue.Description.IndexOf(",") == printQueue.Description.LastIndexOf(",")) 39 { 40 model = printQueue.Description.Substring(printQueue.Description.IndexOf(",") + 1,
printQueue.Description.LastIndexOf(",") - printQueue.Description.IndexOf(",") - 1); 41 } 42 else 43 { 44 model = printQueue.Description.Substring(printQueue.Description.IndexOf(",") + 1); 45 } 46 } 47 return model; 48 } 49 50 /// <summary> 51 /// Get Windows Print Queue via printer name 52 /// </summary> 53 /// <param name="printerName"></param> 54 /// <returns></returns> 55 public System.Printing.PrintQueue GetPrintQueue(string printerName) 56 { 57 System.Printing.PrintQueue printQueue = null; 58 PrintServer server = new PrintServer(printerName); 59 foreach (System.Printing.PrintQueue pq in server.GetPrintQueues()) 60 { 61 if (pq.FullName.Equals(printerName)) 62 { 63 printQueue = pq; 64 } 65 } 66 return printQueue; 67 } 68 69 /// <summary> 70 /// Get Windows Print Queue via printer name 71 /// 如果两个printer指向的是同一个物理打印机,则如果copy1的printQueue已经打开,
///则发送到copy2的打印job也会添加到已经打开的copy1的printQueue中. 72 /// </summary> 73 /// <param name="printerName"></param> 74 /// <returns></returns> 75 public System.Printing.PrintQueue GetOpenedPrintQueueOfSameModel(string printerName) 76 { 77 System.Printing.PrintQueue doorOpenedprintQueue = null; 78 System.Printing.PrintQueue currentPrinterPrintQueue = null; 79 PrintServer server = new PrintServer(printerName); 80 foreach (System.Printing.PrintQueue pq in server.GetPrintQueues()) 81 { 82 if (pq.FullName.Equals(printerName)) 83 { 84 currentPrinterPrintQueue = pq; 85 } 86 else 87 { 88 if (IsSameModel(printerName, pq.FullName)) 89 { 90 if (pq.IsDoorOpened) 91 { 92 doorOpenedprintQueue = pq; 93 break; 94 } 95 } 96 } 97 } 98 99 if (doorOpenedprintQueue != null) 100 { 101 return doorOpenedprintQueue; 102 } 103 else 104 { 105 return currentPrinterPrintQueue; 106 } 107 } 108 }
PrinterPropertyManager用于管理打印机的状态以及查询修改打印机属性
1 class PrinterPropertyManager 2 { 3 /// <summary> 4 /// 获取打印机的IP地址和端口号 5 /// </summary> 6 /// <param name="printerName">打印机名称</param> 8 public KeyValuePair<string, int> GetPrinterIPAndPort(string printerName) 9 { 10 string port = GetPrinterPropertyValue(printerName, "PortName"); 11 //Query portName's property from regedit 12 string[] portQuerys = GetPortQuerys(port); 13 foreach (var portQuery in portQuerys) 14 { 15 RegistryKey portKey = Registry.LocalMachine.OpenSubKey(portQuery, RegistryKeyPermissionCheck.Default,
System.Security.AccessControl.RegistryRights.QueryValues); 16 if (portKey != null) 17 {
/*
* 取IP的时候要特别注意,如果端口类型为"Advanced Port Monitor",那么IP地址会保存到IPAddress属性中
* 如果端口类型为"Standard Tcp/Ip Port",那么IP地址会保存到HostName属性中。
*/ 18 object IPValue = portKey.GetValue("IPAddress", String.Empty,
RegistryValueOptions.DoNotExpandEnvironmentNames);
19 object portValue = portKey.GetValue("PortNumber", String.Empty,
RegistryValueOptions.DoNotExpandEnvironmentNames); 20 if (IPValue != null && portValue != null) 21 { 22 return new KeyValuePair<string, int>(IPValue.ToString(), (Int32)portValue); 23 } 24 } 25 } 26 return new KeyValuePair<string, int>(); 27 } 28 29 /// <summary> 30 /// determine whether the printer is network printer. 31 /// </summary> 34 public bool IsNetWorkPrinter(string printer) 35 { 36 string port = GetPrinterPropertyValue(printer, "PortName"); 37 //Query portName's property from regedit 38 string[] portQuerys = GetNetWorkPortQuerys(port); 39 foreach (var portQuery in portQuerys) 40 { 41 RegistryKey portKey = Registry.LocalMachine.OpenSubKey(portQuery, RegistryKeyPermissionCheck.Default,
System.Security.AccessControl.RegistryRights.QueryValues); 42 if (portKey != null) 43 { 44 return true; 45 } 46 } 47 return false; 48 } 49 50 private string[] GetNetWorkPortQuerys(string portName) 51 { 52 return new string[] 53 { 54 @"System\CurrentControlSet\Control\Print\Monitors\Advanced Port Monitor\Ports\" + portName, 55 @"System\CurrentControlSet\Control\Print\Monitors\Standard TCP/IP Port\Ports\" + portName 56 }; 57 } 58 59 private string[] GetPortQuerys(string portName) 60 { 61 return new string[] 62 { 63 @"System\CurrentControlSet\Control\Print\Monitors\Advanced Port Monitor\Ports\" + portName, 64 @"System\CurrentControlSet\Control\Print\Monitors\Local Port\Ports\" + portName, 65 @"System\CurrentControlSet\Control\Print\Monitors\Standard TCP/IP Port\Ports\" + portName, 66 @"System\CurrentControlSet\Control\Print\Monitors\USB Monitor\Ports\" + portName, 67 @"System\CurrentControlSet\Control\Print\Monitors\WSD Port\Ports\" + portName, 68 }; 69 } 70 71 /// <summary> 72 /// get printer property value
/// 使用WMI查询打印机的信息,需要打开windows management instrumentation服务 73 /// </summary> 77 public string GetPrinterPropertyValue(string printerName, string propertyName) 78 { 79 80 string propertyValue = string.Empty; 81 //Query printer's portName from WIN32_Printer 82 string query = string.Format("SELECT * from Win32_Printer WHERE Name = '{0}'", printerName); 83 ManagementObjectSearcher searcher = new ManagementObjectSearcher(query); 84 ManagementObjectCollection managementObjects = searcher.Get(); 85 foreach (ManagementObject managementObject in managementObjects) 86 { 87 PropertyData propertyData = managementObject.Properties[propertyName]; 88 if (propertyData != null) 89 { 90 propertyValue = propertyData.Value.ToString(); 91 } 92 } 93 return propertyValue; 94 } 95 96 /// <summary> 97 /// change printer property value 98 /// </summary> 102 public void SetPrinterPropertyValue(string printerName, string propertyName, string propertyValue) 103 { 104 105 //Query printer's portName from WIN32_Printer 106 string query = string.Format("SELECT * from Win32_Printer WHERE Name = '{0}'", printerName); 107 ManagementObjectSearcher searcher = new ManagementObjectSearcher(query); 108 ManagementObjectCollection managementObjects = searcher.Get(); 109 foreach (ManagementObject managementObject in managementObjects) 110 { 111 PropertyData propertyData = managementObject.Properties[propertyName]; 112 if (propertyData != null) 113 { 114 propertyData.Value = propertyValue; 115 managementObject.Put(); 116 } 117 } 118 }
/// <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;
} 119 120 /// <summary> 121 /// 获取打印机名字的列表 122 /// </summary> 124 public ArrayList GetPrinterNames() 125 { 126 ArrayList result = new ArrayList(); 127 128 foreach (string ss in PrinterSettings.InstalledPrinters) 129 { 130 result.Add(ss); 131 } 132 return result; 133 } 134 135 /// <summary> 136 /// 获取打印机状态 137 /// </summary> 138 /// <param name="printerName">打印机名称</param> 140 public PrinterStatus GetPrinterStatus(string printerName,out bool isError,out string errorDescription) 141 { 142 //init return variable 143 isError = false; 144 errorDescription = string.Empty; 145 PrinterStatus printerStatus = PrinterStatus.Idle; 146 if (IsNetWorkPrinter(printerName)) 147 { 148 KeyValuePair<string, int> ipPortKeyValuePair = GetPrinterIPAndPort(printerName); 149 PrinterCommunicate printerCommunicate = new PrinterCommunicate(); 150 if (printerCommunicate.CheckNetWorkConnection(ipPortKeyValuePair.Key, ipPortKeyValuePair.Value)) 151 { 152 WindowsPrintQueue winowsPrintQueue = new WindowsPrintQueue(); 153 if (winowsPrintQueue.IsZebraPrinter(printerName)) 154 { 155 //get actual status of zebra printer via zebra command 156 if(IsPause(ipPortKeyValuePair.Key, ipPortKeyValuePair.Value)) 157 { 158 printerStatus = PrinterStatus.Paused; 159 } 160 161 string errorMsg = string.Empty; 162 if(IsError(ipPortKeyValuePair.Key, ipPortKeyValuePair.Value, out errorMsg)) 163 { 164 isError = true; 165 errorDescription = GetZebraPrinterErrorStatusDescription(errorMsg); 166 } 167 } 168 } 169 else 170 { 171 //not connected 172 printerStatus = PrinterStatus.Offline; 173 } 174 } 175 return printerStatus; 176 } 177 178 /// <summary> 179 /// determine whether the network printer is in pause.Only for zebra model printer 180 /// </summary> 185 private bool IsPause(string ip, int port) 186 { 187 string strOutMsg = null; 188 string zebraCommand = "^XA~HS^XZ"; 189 PrinterCommunicate printerCommunicate = new PrinterCommunicate(); 190 if (printerCommunicate.SendZPL_ViaNetwork(ip, port, zebraCommand, out strOutMsg)) 191 { 192 //split retMsg with "\r\n" 193 string[] retMsgs = strOutMsg.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); 194 if (retMsgs != null) 195 { 196 string retFirstMsgItem = retMsgs[0]; 197 string[] retFirstMsgItems = retFirstMsgItem.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); 198 return "1".Equals(retFirstMsgItems[2]); 199 } 200 } 201 return false; 202 } 203 204 /// <summary> 205 /// determine whether the network printer is in error.only for zebra model printer 206 /// </summary> 207 /// <param name="ip"></param> 208 /// <param name="port"></param> 209 /// <param name="strOutMsg"></param> 210 /// <returns></returns> 211 private bool IsError(string ip, int port, out string strOutMsg) 212 { 213 strOutMsg = string.Empty; 214 string zebraCommand = "^XA~HQES^XZ"; 215 PrinterCommunicate printerCommunicate = new PrinterCommunicate(); 216 if (printerCommunicate.SendZPL_ViaNetwork(ip, port, zebraCommand, out strOutMsg)) 217 { 218 //split retMsg with "\r\n" 219 string[] retMsgs = strOutMsg.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); 220 if (retMsgs != null) 221 { 222 for (int i = 0; i < retMsgs.Length; i++) 223 { 224 string retMsgItem = retMsgs[i]; 225 if (string.IsNullOrEmpty(retMsgItem) || !retMsgItem.Contains(":")) { continue; } 226 227 string[] retMsgItemSplited = retMsgItem.Split(new string[] { ":" }, StringSplitOptions.RemoveEmptyEntries); 228 if (retMsgItemSplited == null || retMsgItemSplited.Length == 0) { continue; } 229 230 string errorMsg = retMsgItemSplited[1].Trim(); 231 if (!string.IsNullOrEmpty(errorMsg)) 232 { 233 string errorFlag = errorMsg.Substring(0, 1); 234 if ("1".Equals(errorFlag)) 235 { 236 strOutMsg = errorMsg; 237 return true; 238 } 239 } 240 } 241 } 242 } 243 return false; 244 } 245 246 /// <summary> 247 /// get actual status of zebra printer via zebra command. 248 /// </summary> 249 /// <param name="ip"></param> 250 /// <param name="port"></param> 251 /// <returns></returns> 252 private string GetZebraPrinterErrorStatusDescription(string errorMsg) 253 { 254 StringBuilder status = new StringBuilder(); 255 //error happend 256 string nibble1 = errorMsg.Substring(errorMsg.Length - 1, 1); 257 string nibble2 = errorMsg.Substring(errorMsg.Length - 2, 1); 258 string nibble3 = errorMsg.Substring(errorMsg.Length - 3, 1); 259 260 if (!"0".Equals(nibble1)) 261 { 262 Dictionary<int, string> nibble1ErrorDictionary = new Dictionary<int, string>(); 263 nibble1ErrorDictionary.Add(1, "Midea Out"); 264 nibble1ErrorDictionary.Add(2, "Ribbon Out"); 265 nibble1ErrorDictionary.Add(4, "Head Open"); 266 nibble1ErrorDictionary.Add(8, "Cutter Fault"); 267 268 status.Append(GetErrorDescriptionFromNibble(nibble1, nibble1ErrorDictionary)); 269 } 270 271 if (!"0".Equals(nibble2)) 272 { 273 Dictionary<int, string> nibble2ErrorDictionary = new Dictionary<int, string>(); 274 nibble2ErrorDictionary.Add(1, "Printhead Over Temperature"); 275 nibble2ErrorDictionary.Add(2, "Motor Over Temperature"); 276 nibble2ErrorDictionary.Add(4, "Bad Printhead Element"); 277 nibble2ErrorDictionary.Add(8, "Printhead Detection Error"); 278 279 status.Append(GetErrorDescriptionFromNibble(nibble1, nibble2ErrorDictionary)); 280 } 281 282 if (!"0".Equals(nibble3)) 283 { 284 Dictionary<int, string> nibble3ErrorDictionary = new Dictionary<int, string>(); 285 nibble3ErrorDictionary.Add(1, "Invalid Firmware Config"); 286 nibble3ErrorDictionary.Add(2, "Printhead Thermistor Open"); 287 288 status.Append(GetErrorDescriptionFromNibble(nibble1, nibble3ErrorDictionary)); 289 } 290 291 string strStatus = status.ToString(); 292 return strStatus.Substring(0, strStatus.Length - 1); 293 } 294 295 private StringBuilder GetErrorDescriptionFromNibble(string nibble, Dictionary<int, string> statusDictionary) 296 { 297 int intNibble = Convert.ToInt32(nibble); 298 StringBuilder status = new StringBuilder(); 299 if (statusDictionary != null) 300 { 301 foreach (var statusKV in statusDictionary) 302 { 303 if ((intNibble & statusKV.Key) == statusKV.Key) 304 { 305 status.Append(statusKV.Value); 306 status.Append(","); 307 } 308 } 309 } 310 return status; 311 } 312 } 313 314 315 316 public enum PrinterStatus 317 { 318 Other = 1, 319 Unknown = 2, 320 Idle = 3, 321 Printing = 4, 322 Warmup = 5, 323 Paused = 6, 324 Offline = 7 325 }
获取已安装的打印机驱动
public IEnumerable<string> GetPrintDrivers() { var dirvers = new List<string>(); //Query printer's portName from WIN32_Printer string 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; }