Как печатать файлы XPS программным способом
Обновлен: Ноябрь 2007
Для печати файлов Формат XPS (XML Paper Specification) можно использовать перегрузку метода AddJob не открывая PrintDialog или, в принципе, вообще пользовательский интерфейс.
Можно также напечатать файлы Формат 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) не требует пользовательский интерфейс. Его можно использовать в любом пути кода, где есть имя файла 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.
Суть примера содержится в методе staticBatchXPSPrinter.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 и выполняло переход в соответствии с тем, что будет обнаружено.
Поскольку будет существовать изначально несколько принтеров XPSDrv, доступных сразу после выпуска 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 является одним из способов проверки файла на соответствие XPS.
См. также
Задачи
Основные понятия
Управляемые и неуправляемые потоки
Средство проверки соответствия isXPS
Документы в Windows Presentation Foundation