/// <summary> /// Adds a new port with the given name /// </summary> /// <param name="portName">The name of the port to add</param> /// <exception cref="Win32Exception">Raised when an underlying call fails</exception> public void AddPort(string portName) { Precondition.NotNullOrEmpty(portName, "portName"); SafeNativeMethods.PORT_INFO_1 pInfo = new SafeNativeMethods.PORT_INFO_1 { szPortName = portName }; int result = SafeNativeMethods.AddPortEx(null, 1, ref pInfo, PortMonitor); if (result != 0) { Logger.InfoFormat("Port created with name of {0}", portName); return; } result = Marshal.GetLastWin32Error(); if (result != 87) { throw new Win32Exception(result); } // Double check that the port does, in fact, exist if (this.PortExists(portName)) { throw new VirtualPrinterException(string.Format("Port {0} already exists", portName)); } throw new Win32Exception(result); }
/// <summary> /// Creates a new printer on the system /// </summary> /// <param name="printerName">The name of the printer</param> /// <param name="portName">The port to listen on</param> /// <param name="driverName">The name of the print driver to use</param> /// <param name="printProcessor">The processor to use</param> public void CreatePrinter(string printerName, string portName, string driverName, string printProcessor) { Precondition.NotNullOrEmpty(printerName, "printerName"); Precondition.NotNullOrEmpty(portName, "portName"); Precondition.NotNullOrEmpty(driverName, "driverName"); Precondition.NotNullOrEmpty(printProcessor, "printProcessor"); SafeNativeMethods.PRINTER_INFO_2 _pInfo = new SafeNativeMethods.PRINTER_INFO_2 { pPrinterName = printerName, pPortName = portName, pDriverName = driverName, pPrintProcessor = printProcessor }; IntPtr hPrinter = SafeNativeMethods.AddPrinter(null, 2, ref _pInfo); if (hPrinter != IntPtr.Zero) { SafeNativeMethods.ClosePrinter(hPrinter); Logger.InfoFormat("Printer created with name {0} using port: {1} and driver {2}", printerName, portName, driverName); } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } }
/// <summary> /// Returns a value indicating whether a given port is already present /// </summary> /// <param name="portName">The name of the port to look for</param> /// <returns>True if the port exists, otherwise false</returns> public bool PortExists(string portName) { Precondition.NotNullOrEmpty(portName, "portName"); return (GetInstalledPorts() .Any(port => string.Compare(port, portName, StringComparison.InvariantCultureIgnoreCase) == 0)); }
/// <summary> /// Updates the printer instance to use a new port /// </summary> /// <param name="currentPort">The name of the current port in use</param> /// <param name="newPort">The new port to listen on</param> /// <param name="portCreated">True if the port has already been created</param> /// <param name="printerName">The name of the printer</param> /// <returns>True if the port was created</returns> public bool UpdatePort(string currentPort, string newPort, bool portCreated, string printerName) { Precondition.NotNull(currentPort, "currentPort"); Precondition.NotNullOrEmpty(newPort, "newPort"); Precondition.NotNullOrEmpty(printerName, "printerName"); bool created = false; if (!this.PortExists(newPort)) { this.AddPort(newPort); created = true; } ManagementObjectSearcher searcher = new ManagementObjectSearcher(string.Format("SELECT * FROM Win32_Printer WHERE Name='{0}'", printerName)); string priorPort = string.Empty; foreach (ManagementBaseObject printer in searcher.Get()) { var portNameObj = printer["PortName"]; priorPort = portNameObj == null ? string.Empty : portNameObj.ToString(); printer["PortName"] = newPort; ManagementObject printerObject = printer as ManagementObject; if (printerObject != null) { printerObject.Put(); // Call put to save the settings. } } /* If this application instance created the port, and the new one is different, * delete the old one */ if (priorPort != newPort && !string.IsNullOrEmpty(priorPort)) { this.DeletePort(priorPort); } return(created); }
/// <summary> /// Returns a value indicating whether the given printer exists /// </summary> /// <param name="printerName">The name of the printer to check</param> /// <returns>True if the printer already exists, false if not</returns> public bool PrinterExists(string printerName) { Precondition.NotNullOrEmpty(printerName, "printerName"); var defaults = new SafeNativeMethods.PRINTER_DEFAULTS { DesiredAccess = SafeNativeMethods.PRINTER_ALL_ACCESS, pDatatype = IntPtr.Zero, pDevMode = IntPtr.Zero }; IntPtr hPrinter; if (SafeNativeMethods.OpenPrinter(printerName, out hPrinter, ref defaults)) { SafeNativeMethods.ClosePrinter(hPrinter); return(hPrinter != IntPtr.Zero); } return(false); }
/// <summary> /// Deletes the given printer from the system /// </summary> /// <param name="printerName">The name of the printer to delete</param> /// <param name="portCreated">If true, the port is deleted as part of this operation</param> public void DeletePrinter(string printerName, bool portCreated) { Precondition.NotNullOrEmpty(printerName, "printerName"); var pDefaults = new SafeNativeMethods.PRINTER_DEFAULTS { DesiredAccess = SafeNativeMethods.PRINTER_ALL_ACCESS, pDatatype = IntPtr.Zero, pDevMode = IntPtr.Zero }; Exception failure = null; /* * Set the port to the default port before deleting the printer. Otherwise the delete may fail because the port is in use */ try { this.UpdatePort(string.Empty, DefaultPort, portCreated, printerName); } catch (Win32Exception) { } catch (VirtualPrinterException) { } for (int retries = 0; ; retries++) { IntPtr hPrinter; if (SafeNativeMethods.OpenPrinter(printerName, out hPrinter, ref pDefaults)) { try { /* * Retry the deletion of the printer for a second or so, just in case * the spooler has not had time to clean up its last print job */ if (!SafeNativeMethods.DeletePrinter(hPrinter)) { if (retries < MaxPrinterDeleteAttempts) { Thread.Sleep(PrinterDeleteRetryDelayMs); continue; } failure = new Win32Exception(Marshal.GetLastWin32Error()); } break; } finally { SafeNativeMethods.ClosePrinter(hPrinter); } } failure = new Win32Exception(Marshal.GetLastWin32Error()); break; } if (failure != null && this.PrinterExists(printerName)) { throw failure; } }