Cómo: Imprimir mediante programación archivos XPS
Puede usar una sobrecarga del método AddJob para imprimir archivos XML Paper Specification (XPS) sin abrir una PrintDialog o, en principio, cualquier interfaz de usuario (UI).
También puede imprimir archivos XPS utilizando los numerosos métodos XpsDocumentWriter.Write y XpsDocumentWriter.WriteAsync. Para obtener más información, vea Impresión de un documento XPS.
Otra forma de imprimir XPS es utilizar los métodos PrintDialog.PrintDocument o PrintDialog.PrintVisual. Vea Invocar un cuadro de diálogo de impresión.
Ejemplo
Los principales pasos para utilizar el método de tres parámetros AddJob(String, String, Boolean) son los siguientes. En el ejemplo siguiente se proporciona información detallada.
Determinar si la impresora es una impresora XPSDrv. Vea Introducción a la impresión para obtener más información sobre XPSDrv.
Si la impresora no es una impresora XPSDrv, establezca el apartamento del subproceso en un subproceso único.
Crear una instancia de un servidor de impresión y un objeto de cola de impresión.
Llame al método, especifique un nombre de trabajo, el archivo que se va a imprimir y una marca Boolean que indique si la impresora es una impresora XPSDrv o no.
En el ejemplo siguiente se muestra realizar la impresión por lotes de todos los archivos XPS en un directorio. Aunque la aplicación pide al usuario que especifique el directorio, el método de tres parámetros AddJob(String, String, Boolean) no requiere una interfaz de usuario (UI). Se puede utilizar en cualquier ruta de acceso del código donde haya un nombre de archivo XPS y la ruta de acceso que pueda pasar a ella.
La sobrecarga de AddJob(String, String, Boolean) de tres parámetros de AddJob debe ejecutarse en un apartamento de un solo subproceso siempre que el parámetro Boolean sea false
, lo que debe ser cuando se utiliza una impresora que no sea XPSDrv. Sin embargo, el estado del apartamento predeterminado de .NET es de varios subprocesos. Este es el valor predeterminado, ya que el en el ejemplo se da por hecho que estamos antes una impresora que no es XPSDrv.
Existen dos maneras de cambiar el valor predeterminado. Una forma consiste en agregar simplemente STAThreadAttribute (es decir, "[System.STAThreadAttribute()]
") justo encima de la primera línea del método Main
de la aplicación (normalmente "static void Main(string[] args)
"). Sin embargo, muchas aplicaciones requieren que el método Main
tenga un estado de apartamento multisubprocesos, por lo que existe un segundo método: poner la llamada en AddJob(String, String, Boolean) en un subproceso independiente cuyo estado de apartamento se establece en STA con SetApartmentState. El ejemplo siguiente utiliza esta segunda técnica.
En consecuencia, el ejemplo comienza instanciando un objeto Thread y pasándole un método PrintXPS como parámetro ThreadStart. (El método PrintXPS se define más adelante en el ejemplo). A continuación, el subproceso se establece en un apartamento de subproceso único. El único código restante del método Main
inicia el nuevo subproceso.
El grueso del ejemplo está en el método static
BatchXPSPrinter.PrintXPS. Después de crear una cola y un servidor de impresión, el método solicita al usuario un directorio que contenga archivos XPS. Después de validar la existencia del directorio y la presencia de archivos *.xps en él, el método agrega estos archivos a la cola de impresión. El ejemplo asume que la impresora no es XPSDrv, por lo que estamos pasando false
al último parámetro del método AddJob(String, String, Boolean). Por este motivo, el método validará la marcación XPS en el archivo antes de intentar convertirla en un lenguaje de descripción de la página de la impresora. Si se produce un error validación, se produce una excepción. El código de ejemplo detectará la excepción, la notificará al usuario y, a continuación, continuará con el proceso en el siguiente archivo 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
Friend Class Program
<System.MTAThreadAttribute()>
Shared Sub Main(ByVal args() As String) ' Added for clarity, but this line is redundant because MTA is the default.
' Create the secondary thread and pass the printing method for
' the constructor's ThreadStart delegate parameter. The BatchXPSPrinter
' class is defined below.
Dim printingThread As New Thread(AddressOf 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 Sub
End Class
Public Class BatchXPSPrinter
Public Shared Sub PrintXPS()
' Create print server and print queue.
Dim localPrintServer As New LocalPrintServer()
Dim defaultPrintQueue As PrintQueue = LocalPrintServer.GetDefaultPrintQueue()
' Prompt user to identify the directory, and then create the directory object.
Console.Write("Enter the directory containing the XPS files: ")
Dim directoryPath As String = Console.ReadLine()
Dim dir As New DirectoryInfo(directoryPath)
' If the user mistyped, end the thread and return to the Main thread.
If Not dir.Exists Then
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 Then
Console.WriteLine("There are no XPS files in the directory.")
Else
Console.WriteLine(vbLf & "Jobs 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.
For Each f As FileInfo In dir.GetFiles("*.xps")
Dim nextFile As String = directoryPath & "\" & f.Name
Console.WriteLine("Adding {0} to queue.", nextFile)
Try
' Print the Xps file while providing XPS validation and progress notifications.
Dim xpsPrintJob As PrintSystemJobInfo = defaultPrintQueue.AddJob(f.Name, nextFile, False)
Catch e As PrintJobException
Console.WriteLine(vbLf & vbTab & "{0} could not be added to the print queue.", f.Name)
If e.InnerException.Message = "File contains corrupted data." Then
Console.WriteLine(vbTab & "It is not a valid XPS file. Use the isXPS Conformance Tool to debug it.")
End If
Console.WriteLine(vbTab & "Continuing with next XPS file." & vbLf)
End Try
Next f ' end for each XPS file
End If 'end if there are no XPS files in the directory
End If 'end if the directory does not exist
Console.WriteLine("Press Enter to end program.")
Console.ReadLine()
End Sub
End Class
Si está utilizando una impresora XPSDrv, puede establecer el parámetro final en true
. En ese caso, puesto que XPS es el idioma de descripción de la página de la impresora, el método enviará el archivo a la impresora sin validarlo o convertirlo en otro idioma de descripción de página. Si no está seguro en el momento del diseño de si la aplicación va a usar una impresora XPSDrv, puede modificar la aplicación para que lea la propiedad IsXpsDevice y cree una rama de acuerdo con lo que encuentre.
Puesto que inicialmente habrá pocas impresoras XPSDrv disponibles inmediatamente después del lanzamiento de Windows Vista y Microsoft .NET Framework, puede que necesite camuflar una impresora no XPSDrv como una impresora XPSDrv. Para ello, agregue Pipelineconfig.xml a la lista de archivos en la siguiente clave del registro del equipo que ejecuta la aplicación:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Environments\Windows NT x86\Drivers\Version-3\<PseudoXPSPrinter>>\DependentFiles
donde <PseudoXPSPrinter >> es cualquier cola de impresión. El equipo debe reiniciarse a continuación.
Este camuflaje le permitirá pasar true
como el parámetro final de AddJob(String, String, Boolean) sin producir una excepción, pero puesto que <PseudoXPSPrinter> no es realmente una impresora XPSDrv, solo se imprimirán elementos no utilizados.
Nota:
Para simplificar, el ejemplo anterior utiliza la presencia de una extensión *.xps como prueba de que un archivo es XPS. Sin embargo, los archivos XPS no tienen necesariamente esta extensión. isXPS.exe (Herramienta isXPS Conformance) es una manera de probar la validez de un archivo para XPS.
Vea también
.NET Desktop feedback