PrintCapabilities printCapabilites = SelectedPrinter.GetPrintCapabilities(); IEnumerable pagesizeList = printCapabilites.PageMediaSizeCapability;
以上代码未列出打印机驱动程序支持的所有页面大小,这是我的问题。
作为示例,如果您使用Microsoft XPS打印机驱动程序,您会发现pagesizeList(上面)将缺少某些页面大小。 “Letter Small”是缺少页面大小之一(MS Word将成功列出此页面大小)。
作为 快速 检查,我将打印机功能转储到xml,如下所示:
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();
生成的xml文件中的PageMediaSize节点确实具有所有页面大小和缺少的页面大小。
显示的网页似乎名称以psk开头:
<psf:Option name="psk:ISOA4" constrained="psk:None">
但未显示的网页似乎有:
<psf:Option name="ns0000:LETTERSMALL" constrained="psk:None">
未显示的Epson打印驱动程序页面类似:
<psf:Option name="epns200:IndexCard5x8" constrained="psk:None">
基本上,名称以“psk”PageMediaSizeCapability显示的页面显示,但如果它是制造自定义的,即epns200,ns0000,则不会列出。任何想法为什么以及如何解决这个问题?节点/页面在那里但是PageMediaSizeCapability不喜欢它!
提前致谢
编辑:
作为MS状态'PrintCapabilities对象是一种易于使用的表示某种类型的XML文档,称为PrintCapabilities文档。但是文档的信息比对象Full description
更多答案 0 :(得分:3)
您必须保存从PrintCapabilities xml读取的纸张名称,并使用它来创建PrintTicket xml(PrintTicket具有接受xml流的构造函数),然后使用PrintTicket。以下是PrintTicket XML的示例(ns0000:User0000000257是我创建的自定义纸张尺寸的名称):
<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>
答案 1 :(得分:1)
尽管这是一个较旧的主题,但在我们需要读取和更新自定义属性时,指向正确的方向很有帮助。
以下代码改编自此主题:XPS打印,托盘选择和InputBinCapability(InputBin)=问题:http://www.windows-tech.info/14/29c7cf575646cb39.php。 Jo0815底部的答案包含了你在下面看到的大部分内容,尤其是指向正确方向的XPath表达式。
此外,使用您的更改更新PrintQueue.UserPrintTicket,而不是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
}
}