2010-06-04 13 views
5

PrintCapabilities printCapabilites = SelectedPrinter.GetPrintCapabilities(); IEnumerable pagesizeList = printCapabilites.PageMediaSizeCapability;GetPrintCapabilities no devolverá todos los tamaños de página

El código anterior no muestra todos los tamaños de página que admite el controlador de impresora y este es mi problema.

Como ejemplo si utiliza el controlador de impresora Microsoft XPS encontrará que pagesizeList (arriba) faltará algunos tamaños de página. "Letter Small" es uno de los tamaños de página que faltan (sin embargo, MS Word incluirá con éxito este tamaño de página).

Como comprobación rápida que vierten las capacidades de la impresora en XML de la siguiente manera:

long gpCLen = _selectedPrinter.GetPrintCapabilitiesAsXml().Length; 
FileStream fs = File.OpenWrite(@"c:\test.txt"); 
MemoryStream ms = _selectedPrinter.GetPrintCapabilitiesAsXml(); 
byte[] b = new byte[gpCLen]; 
ms.Read(b, 0, (int)gpCLen); 
fs.Write(b, 0, (int)gpCLen); 
fs.Close(); 

El nodo PageMediaSize en el archivo XML producido tiene, de hecho todos los tamaños de página y los que faltan.

páginas Aparece parecen tener su PSK nombre de inicio:

<psf:Option name="psk:ISOA4" constrained="psk:None"> 

pero las páginas no visualizados parecen tener:

<psf:Option name="ns0000:LETTERSMALL" constrained="psk:None"> 

páginas del controlador de impresión sin visualizar Epson son similares:

<psf:Option name="epns200:IndexCard5x8" constrained="psk:None"> 

Básicamente, una página cuyo nombre comienza 'psk' muestra PageMediaSizeCapability, pero si se trata de fabricación personalizado, es decir, epns200, ns0000, no aparece. ¿Alguna idea de por qué y cómo solucionar esto, por favor? ¡Los nodos/páginas están ahí pero a PageMediaSizeCapability no le gusta!

Gracias de antemano

EDIT:

Como estado MS 'Un objeto PrintCapabilities es un fácil-a-trabajar-con la representación de un determinado tipo de documento XML llamado un documento PrintCapabilities' Pero el documento tiene más información que el objeto Full description

Respuesta

3

tiene que guardar el nombre del papel que leyó de PrintCapabilities xml, y usarlo para crear un PrintTicket xml (PrintTicket tiene un constructor que acepta una secuencia xml), y luego use PrintTicket. Aquí está un ejemplo de PrintTicket XML (ns0000: User0000000257 es el nombre de HTE de un tamaño de papel personalizado que he creado):

<psf:PrintTicket xmlns:psf="http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
      xmlns:psk="http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords" 
      xmlns:ns0000="http://schemas.microsoft.com/windows/printing/oemdriverpt/Samsung_CLP-310 Series/5.1.2600.2180/" version="1"> 
    <psf:Feature name="psk:PageMediaSize"> 
    <psf:Option name="ns0000:User0000000257"></psf:Option> 
    </psf:Feature> 
</psf:PrintTicket> 
+0

+1: esto funciona y debe aceptarse como la respuesta. –

1

A pesar de que esto era un hilo de más edad, que era muy útil en indicarnos la dirección correcta cuando necesitábamos leer y actualizar propiedades personalizadas.

El código siguiente fue adaptado de este hilo: Impresión XPS, selección de bandeja e InputBinCapability (InputBin) = Problema: http://www.windows-tech.info/14/29c7cf575646cb39.php. La respuesta de Jo0815 en la parte inferior tenía la mayor parte de lo que ve a continuación, especialmente las expresiones XPath que nos indicaban la dirección correcta.

Además, actualice la PrintQueue.UserPrintTicket con sus cambios, NO la DefaultPrintTicket.

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Printing; 
using System.Text; 
using System.Windows; 
using System.Xml; 

// Adapted 
// From: XPS Printing, Tray selection and InputBinCapability (InputBin) = Problem 
// Link: http://www.windows-tech.info/14/29c7cf575646cb39.php - last answer at bottom by Jo0815 

namespace WpfApplication1 
{ 
    public static class WpfPrinterUtilities 
    { 
     #region GetPrintQueues 

     /// <summary> 
     /// Gets a dictionary of print queues where Key = print queue name 
     /// and Value = the print queue object. 
     /// </summary> 
     /// <param name="printQueueTypes">EnumeratedPrintQueueTypes params array of the types of print queues being requested.</param> 
     /// <returns>Dictionary of requested print queues where Key = print queue name and Value = the print queue object itself.</returns> 
     public static Dictionary<string, PrintQueue> GetPrintQueues(params EnumeratedPrintQueueTypes[] printQueueTypes) 
     { 
      var server = new PrintServer(); 
      return server.GetPrintQueues(printQueueTypes).ToDictionary(pq => pq.ShareName != null ? pq.ShareName : pq.Name); 
     } 

     #endregion 

     #region GetInputBins 

     /// <summary> 
     /// Reads print queue configuration xml to retrieve the current list of input bins. 
     /// </summary> 
     /// <param name="printQueue">The print queue to query.</param> 
     /// <returns></returns> 
     public static Dictionary<string, string> GetInputBins(PrintQueue printQueue) 
     { 
      Dictionary<string, string> inputBins = new Dictionary<string, string>(); 

      // Get the print queue PrintCapabilities. 
      XmlDocument xmlDoc = null; 
      using (MemoryStream stream = printQueue.GetPrintCapabilitiesAsXml()) 
      { 
       // Read the JobInputBins out of the PrintCapabilities. 
       xmlDoc = new XmlDocument(); 
       xmlDoc.Load(stream); 
      } 

      // Create NamespaceManager and add PrintSchemaFrameWork-Namespace (should be on DocumentElement of the PrintTicket). 
      // Prefix: psf NameSpace: xmlDoc.DocumentElement.NamespaceURI = "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework" 
      XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable); 
      manager.AddNamespace(xmlDoc.DocumentElement.Prefix, xmlDoc.DocumentElement.NamespaceURI); 

      // Select all job input bins. 
      XmlNodeList nodeList = xmlDoc.SelectNodes("//psf:Feature[@name='psk:JobInputBin']/psf:Option/psf:Property", manager); 

      // Load the Dictionary with the bin values and names. The names will be used to modify the print ticket if necessary. 
      foreach (XmlNode node in nodeList) 
      { 
       inputBins.Add(node.LastChild.InnerText, node.ParentNode.Attributes[0].Value); 
      } 

      return inputBins; 
     } 

     #endregion 

     #region ModifyPrintTicket 

     /// <summary> 
     /// Modifes a print ticket xml after updating a feature value. 
     /// 
     /// Sample usage: 
     /// Get Dictionary with Inputbins by calling the other method 
     /// and get "value" for the desired inputbin you'd like to use... 
     /// ... 
     /// desiredTray is then something like "NS0000:SurpriseOption7" for example. 
     /// defaultPrintTicket is the (Default)PrintTicket you want to modify from the PrintQueue for example 
     /// PrintTicket myPrintTicket = WpfPrinterUtils.ModifyPrintTicket(defaultPrintTicket, "psk:JobInputBin", desiredTray); 
     /// </summary> 
     /// <param name="ticket"></param> 
     /// <param name="featureName"></param> 
     /// <param name="newValue"></param> 
     /// <param name="printQueueName">Optional - If provided, a file is created with the print ticket xml. Useful for debugging.</param> 
     /// <param name="folder">Optional - If provided, the path for a file is created with the print ticket xml. Defaults to c:\. Useful for debugging.</param> 
     /// <param name="displayMessage">Optional - True to display a dialog with changes. Defaults to false. Useful for debugging.</param> 
     /// <returns></returns> 
     public static PrintTicket ModifyPrintTicket(PrintTicket ticket, string featureName, string newValue, string printQueueName = null, string folder = null, bool displayMessage = false) 
     { 
      if (ticket == null) 
      { 
       throw new ArgumentNullException("ticket"); 
      } 

      // Read Xml of the PrintTicket xml. 
      XmlDocument xmlDoc = new XmlDocument(); 
      xmlDoc.Load(ticket.GetXmlStream()); 

      // Create NamespaceManager and add PrintSchemaFrameWork-Namespace hinzufugen (should be on DocumentElement of the PrintTicket). 
      // Prefix: psf NameSpace: xmlDoc.DocumentElement.NamespaceURI = "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework" 
      XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable); 
      manager.AddNamespace(xmlDoc.DocumentElement.Prefix, xmlDoc.DocumentElement.NamespaceURI); 

      // Search node with desired feature we're looking for and set newValue for it 
      string xpath = string.Format("//psf:Feature[@name='{0}']/psf:Option", featureName); 
      XmlNode node = xmlDoc.SelectSingleNode(xpath, manager); 
      if (node != null) 
      { 
       if (node.Attributes["name"].Value != newValue) 
       { 
        if (displayMessage) 
        { 
         System.Windows.MessageBox.Show(string.Format("OldValue: {0}, NewValue: {1}", node.Attributes["name"].Value, newValue), "Input Bin"); 
        } 
        node.Attributes["name"].Value = newValue; 
       } 
      } 

      // Create a new PrintTicket out of the XML. 
      PrintTicket modifiedPrintTicket = null; 
      using (MemoryStream stream = new MemoryStream()) 
      { 
       xmlDoc.Save(stream); 
       stream.Position = 0; 
       modifiedPrintTicket = new PrintTicket(stream); 
      } 

      // For testing purpose save the print ticket to a file. 
      if (!string.IsNullOrWhiteSpace(printQueueName)) 
      { 
       if (string.IsNullOrWhiteSpace(folder)) 
       { 
        folder = "c:\\"; 
       } 
       // Colons are not valid in a file name. 
       newValue = newValue.Replace(':', ';'); 
       printQueueName = string.Format("{0} PrintTicket {1}.xml", Path.Combine(folder, printQueueName), newValue); 
       if (File.Exists(printQueueName)) 
       { 
        File.Delete(printQueueName); 
       } 
       if (!Directory.Exists(Path.GetDirectoryName(printQueueName))) 
       { 
        Directory.CreateDirectory(Path.GetDirectoryName(printQueueName)); 
       } 
       using (FileStream stream = new FileStream(printQueueName, FileMode.CreateNew, FileAccess.ReadWrite)) 
       { 
        modifiedPrintTicket.GetXmlStream().WriteTo(stream); 
       } 
      } 

      return modifiedPrintTicket; 
     } 

     #endregion 
    } 
} 
Cuestiones relacionadas