Практическое руководство. Печать XPS-файлов программным способом
Можно использовать перегрузку AddJob способ печати Формат XPS (XML Paper Specification) файлы, не открывая PrintDialog или, в принципе, все UI вообще.
Можно также распечатать Формат XPS (XML Paper Specification) файлов с помощью многочисленных Write и WriteAsync методы XpsDocumentWriter. Дополнительные сведения см. в разделе Печать документа XPS.
Еще один способ печати Формат XPS (XML Paper Specification) заключается в использовании PrintDocument или PrintVisual методы PrintDialog элемента управления. См. раздел Вызов диалогового окна печати.
Пример
Основные действия с помощью с тремя параметрами AddJob(String, String, Boolean) метод, как показано ниже. Подробные сведения см. в примере.
Определите, является ли принтер принтером XPSDrv. (Дополнительные сведения о XPSDrv см. в разделе Обзор печати.)
Если принтер не является принтером XPSDrv, задайте однопотоковое подразделение потока.
Создайте экземпляр сервера печати и объект очереди печати.
Вызовите метод, указав имя задания, файл для печати и Boolean флаг, указывающий, будет ли принтер принтером XPSDrv.
В приведенном ниже примере показано, как выполнить пакетную печать всех файлов XPS в каталоге. Несмотря на то, что приложение предлагает пользователю указать каталог, с тремя параметрами AddJob(String, String, Boolean) метод не требует UI . Его можно использовать в любом пути кода при условии, что вы знаете имя файла XPS и путь, который вы можете ему передать.
С тремя параметрами AddJob(String, String, Boolean) перегрузки AddJob должна выполняться в однопотоковом подразделении всякий раз, когда Boolean параметр false
, который он должен быть, если используется принтер XPSDrv. Однако по умолчанию состояние подразделения для Microsoft .NET многопотоковое. Данное значение по умолчанию должно быть обращено, поскольку в этом примере предполагается, что принтер не является принтером XPSDrv.
Изменить значение по умолчанию можно одним из двух способов. Первый способ — просто добавьте STAThreadAttribute (то есть "[System.STAThreadAttribute()]
«) непосредственно над первой строки приложения Main
метод (обычно"static void Main(string[] args)
«). Тем не менее, многие приложения требуют Main
метод имеют состояние многопотокового подразделения, поэтому второй метод: поместить вызов AddJob(String, String, Boolean) в отдельном потоке, имеющий состояние подразделения присваивается STA с SetApartmentState. В следующем примере используется второй метод.
Соответственно, пример начинается с создания экземпляра Thread объекта и его передачи PrintXPS метод как ThreadStart параметр. (Метод PrintXPS определяется ниже в этом примере.) Затем для потока устанавливается однопотоковое подразделение. Остальной код метода Main
начинается с нового потока.
Основу этого примера составляет метод static
BatchXPSPrinter.PrintXPS. После создания сервера и очереди печати метод предлагает пользователю выбрать каталог, содержащий файлы XPS. После проверки существования каталога и наличие *.xps файлы в ней, метод добавляет каждый такой файл в очередь печати. В примере предполагается, что принтер не является принтером XPSDrv, поэтому мы передаем false
для последнего параметра AddJob(String, String, Boolean) метод. В связи с этим метод проверит разметку XPS в файле и только после этого конвертирует его в язык описания страниц принтера. Если проверка завершается ошибкой, выдается исключение. Код в примере перехватит исключение, сообщит о нем пользователю, а затем перейдет к обработке следующего файла XPS.
class Program
{
[System.MTAThreadAttribute()] // Added for clarity, but this line is redundant because MTA is the default.
static void Main(string[] args)
{
// Create the secondary thread and pass the printing method for
// the constructor's ThreadStart delegate parameter. The BatchXPSPrinter
// class is defined below.
Thread printingThread = new Thread(BatchXPSPrinter.PrintXPS);
// Set the thread that will use PrintQueue.AddJob to single threading.
printingThread.SetApartmentState(ApartmentState.STA);
// Start the printing thread. The method passed to the Thread
// constructor will execute.
printingThread.Start();
}//end Main
}//end Program class
public class BatchXPSPrinter
{
public static void PrintXPS()
{
// Create print server and print queue.
LocalPrintServer localPrintServer = new LocalPrintServer();
PrintQueue defaultPrintQueue = LocalPrintServer.GetDefaultPrintQueue();
// Prompt user to identify the directory, and then create the directory object.
Console.Write("Enter the directory containing the XPS files: ");
String directoryPath = Console.ReadLine();
DirectoryInfo dir = new DirectoryInfo(directoryPath);
// If the user mistyped, end the thread and return to the Main thread.
if (!dir.Exists)
{
Console.WriteLine("There is no such directory.");
}
else
{
// If there are no XPS files in the directory, end the thread
// and return to the Main thread.
if (dir.GetFiles("*.xps").Length == 0)
{
Console.WriteLine("There are no XPS files in the directory.");
}
else
{
Console.WriteLine("\nJobs will now be added to the print queue.");
Console.WriteLine("If the queue is not paused and the printer is working, jobs will begin printing.");
// Batch process all XPS files in the directory.
foreach (FileInfo f in dir.GetFiles("*.xps"))
{
String nextFile = directoryPath + "\\" + f.Name;
Console.WriteLine("Adding {0} to queue.", nextFile);
try
{
// Print the Xps file while providing XPS validation and progress notifications.
PrintSystemJobInfo xpsPrintJob = defaultPrintQueue.AddJob(f.Name, nextFile, false);
}
catch (PrintJobException e)
{
Console.WriteLine("\n\t{0} could not be added to the print queue.", f.Name);
if (e.InnerException.Message == "File contains corrupted data.")
{
Console.WriteLine("\tIt is not a valid XPS file. Use the isXPS Conformance Tool to debug it.");
}
Console.WriteLine("\tContinuing with next XPS file.\n");
}
}// end for each XPS file
}//end if there are no XPS files in the directory
}//end if the directory does not exist
Console.WriteLine("Press Enter to end program.");
Console.ReadLine();
}// end PrintXPS method
}// end BatchXPSPrinter class
Если вы используете принтер XPSDrv, последнему параметру можно присвоить значение true
. В этом случае, поскольку XPS является языком описания страниц принтера, метод отправляет файл на принтер без проверки или преобразования в другой язык описания страниц. Если вы не уверены во время разработки ли приложение будет использовать принтер XPSDrv, можно изменить приложение, чтобы оно считывало IsXpsDevice свойство и ветви, оно читало.
Так как изначально потребуется всего несколько принтеров доступны сразу же после выпуска Windows Vista и Microsoft .NET Framework, может потребоваться маскировка принтер XPSDrv, как принтер XPSDrv. Для этого добавьте файл Pipelineconfig.xml в список файлов в следующем разделе реестра компьютера, на котором выполняется ваше приложение:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Environments\Windows NT x86\Drivers\Version-3\<PseudoXPSPrinter> \DependentFiles
где <PseudoXPSPrinter> — это любая очередь печати. После этого компьютер необходимо перезагрузить.
Эта маскировка позволит передавать true
как последний параметр AddJob(String, String, Boolean) без возникновения исключения, но поскольку <PseudoXPSPrinter > деле не является принтером XPSDrv, будет распечатан только мусор.
Примечание для простоты в примере выше используется наличие *.xps расширения в качестве проверки того, что файл XPS. При этом файлы XPS не обязательно должны иметь такое расширение. isXPS.exe (isXPS Conformance Tool) является одним из способов проверки файла на соответствие XPS.