Procedura: stampa di file XPS a livello di codice
È possibile utilizzare un overload del metodo AddJob per stampare file XML Paper Specification (XPS) senza aprire un controllo PrintDialog o, in generale, alcuna user interface (UI).
È inoltre possibile stampare file XML Paper Specification (XPS) utilizzando i diversi metodi Write e WriteAsync della classe XpsDocumentWriter. Per ulteriori informazioni, vedere Printing an XPS Document.
Un altro modo disponibile per stampare i file XML Paper Specification (XPS) consiste nell'utilizzare il metodo PrintDocument o PrintVisual del controllo PrintDialog. Vedere Procedura: richiamare una finestra di dialogo di stampa.
Esempio
Di seguito sono elencati i passaggi principali da eseguire per utilizzare il metodo AddJob(String, String, Boolean) con tre parametri. Nell'esempio riportato di seguito vengono forniti i dettagli.
Determinare se la stampante è una stampante XPSDrv. (Per ulteriori informazioni su XPSDrv, vedere Cenni preliminari sulla stampa.)
Se la stampante non è una stampante XPSDrv, impostare l'apartment del thread su un thread singolo.
Creare un'istanza di un server di stampa e di un oggetto coda di stampa.
Chiamare il metodo, specificando un nome di processo, il file da stampare e un flag Boolean per indicare se la stampante è o meno una stampante XPSDrv.
Nell'esempio riportato di seguito viene illustrato come stampare in modalità batch tutti i file XPS contenuti in una directory. Sebbene venga richiesto all'utente di specificare la directory, il metodo AddJob(String, String, Boolean) con tre parametri non richiede un'user interface (UI). Può essere utilizzato in qualsiasi percorso di codice in cui sia presente il nome e il percorso di un file XPS da passare.
L'overload del metodo AddJob(String, String, Boolean) con tre parametri di AddJob deve essere eseguito in un apartment a thread singolo ogni volta che il parametro Boolean è false, ovvero ogni volta che viene utilizzata una stampante non XPSDrv. Tuttavia, lo stato dell'apartment predefinito per Microsoft .NET è a più thread. Questa impostazione predefinita deve essere invertita in quanto nell'esempio si presuppone che venga utilizzata una stampante non XPSDrv.
Sono disponibili due modi per modificare l'impostazione predefinita. Un modo consiste semplicemente nell'aggiungere STAThreadAttribute (ovvero "[System.STAThreadAttribute()]") appena sopra la prima riga del metodo Main dell'applicazione, in genere "static void Main(string[] args)". Tuttavia, poiché molte applicazioni richiedono che per il metodo Main lo stato dell'apartment sia a più thread, è disponibile un secondo modo che consiste nell'inserire la chiamata a AddJob(String, String, Boolean) in un thread separato il cui stato dell'apartment sia impostato su STA con il metodo SetApartmentState. Nell'esempio riportato di seguito viene utilizzata la seconda tecnica.
Di conseguenza, l'esempio prevede innanzitutto la creazione di un'istanza di un oggetto Thread e il relativo passaggo al metodo PrintXPS come parametro ThreadStart. (Il metodo PrintXPS verrà definito più avanti nell'esempio.) In secondo luogo, il thread viene impostato su un apartment a thread singolo. Il nuovo thread verrà avviato tramite il codice rimanente del metodo Main.
La parte fondamentale dell'esempio è rappresentata dal metodo static BatchXPSPrinter.PrintXPS. Dopo avere creato un server di stampa e una coda, viene richiesto all'utente di specificare una directory contenente i file XPS. Dopo che l'esistenza della directory e la presenza di file xps sono state accertate, ognuno di questi file viene aggiunto alla coda di stampa. Poiché nell'esempio si presuppone che la stampante non sia XPSDrv, false viene passato all'ultimo parametro del metodo AddJob(String, String, Boolean). Per questo motivo, il markup XPS verrà convalidato nel file prima che venga convertito nel linguaggio di descrizione della pagina della stampante. Se la convalida ha esito negativo, viene generata un'eccezione. Nel codice di esempio l'eccezione viene rilevata e l'utente viene notificato, dopodiché viene elaborato il file XPS successivo.
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 Main
End Class 'end Program 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 PrintXPS method
End Class ' end BatchXPSPrinter class
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
Se si utilizza una stampante XPSDrv, è possibile impostare il parametro finale su true. In questo caso, poiché XPS è il linguaggio di descrizione della pagina della stampante, il file verrà inviato alla stampante senza essere convalidato né convertito a un altro linguaggio di descrizione della pagina. Se in fase di progettazione non si è certi se verrà effettivamente utilizzata una stampante XPSDrv, è possibile modificare l'applicazione affinché venga letta la proprietà IsXpsDevice e la diramazione secondo quanto rilevato.
Poiché saranno poche le stampanti XPSDrv immediatamente disponibili dopo il rilascio di Windows Vista e Microsoft .NET Framework, potrebbe essere necessario fare passare una stampante non XPSDrv per una stampante XPSDrv. A tale scopo, aggiungere Pipelineconfig.xml all'elenco di file nella seguente chiave del Registro di sistema del computer che esegue l'applicazione:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Environments\Windows NT x86\Drivers\Version-3\<PseudoXPSPrinter>\DependentFiles
in cui <PseudoXPSPrinter> è una coda di stampa qualsiasi. Riavviare il computer.
In questo modo, sarà possibile passare true come parametro finale del metodo AddJob(String, String, Boolean) senza causare un'eccezione, tuttavia poiché <PseudoXPSPrinter> non è realmente una stampante XPSDrv, verrà stampato contenuto privo di significato.
Nota Per semplicità, nell'esempio viene utilizzata la presenza di un'estensione xps per stabilire se un file è XPS. I file XPS non devono necessariamente avere questa estensione. isXPS.exe (strumento di conformità isXPS) rappresenta un modo per stabilire la validità dei file XPS.
Vedere anche
Attività
Riferimenti
Concetti
Threading gestito e non gestito
isXPS.exe (strumento di conformità isXPS)
Cenni preliminari sulla stampa