Ottenere lo stato di una stampante e di un processo di stampa
Questo articolo illustra come ottenere lo stato di una stampante e un processo di stampa usando lo Spooler Win32.
Versione originale del prodotto: Win32 Spooler
Numero KB originale: 160129
Lo stato delle stampanti e dei processi di stampa viene aggiornato dallo Spooler Win32 durante la spooling di un processo di stampa. In qualsiasi altro momento, quando la stampante non viene despooling e non segnala informazioni sullo stato, la stampante viene considerata pronta e inattiva.
Come indicato dall'API Win32, una stampante è costituita dal driver della stampante, dalla coda di stampa e dal percorso di input/output della stampante fisica. Il sistema operativo considera una stampante fisica semplicemente come destinazione di un processo di stampa generato da e passato attraverso una stampante di sistema, indicata nel resto di questo articolo come stampante.
La parte più visibile di una stampante è una coda di stampa. È gestito da Gestione stampa o dalle cartelle Stampante nelle interfacce utente in stile Windows 95. Il driver della stampante è l'interfaccia della stampante usata dalle applicazioni per creare processi di stampa tramite controller di dominio della stampante. Il percorso di I/O per una stampante è costituito da diversi livelli di codice di sistema che culminano con un monitoraggio delle porte.
Il monitoraggio della porta è l'interfaccia con la stampante fisica all'estremità inferiore del flusso di una stampante di sistema ed è responsabile del trasferimento dei dati di un processo di stampa attraverso qualsiasi connessione esistente alla stampante fisica. Nel caso di stampanti bidirezionali, il monitoraggio delle porte sarà responsabile del trasferimento dei dati da e verso la stampante fisica. Questa connessione e la stampante fisica sono i casi in cui si verificano errori. È compito del monitoraggio delle porte segnalare tali errori.
Lo Spooler non esegue query sullo stato di una stampante fisica a cui è connessa una stampante. Al contrario, lo stato di una stampante fisica determina l'esito positivo di un processo di stampa nel momento in cui viene despoolato sul monitoraggio delle porte. Se si verifica un errore in questo processo, l'errore viene segnalato dal monitoraggio delle porte e registrato nelle informazioni sullo stato di un processo di stampa. Lo Spooler, a sua volta, propaga informazioni di errore ragionevoli alla coda della stampante.
Di conseguenza, una stampante di sistema non segnala lo stato quando la coda della stampante è vuota. In questo stato, si presuppone che la stampante sia pronta ad accettare i processi di stampa. Si tratta di un presupposto valido anche se la stampante fisica si trova in uno stato di errore, ad esempio fuori linea. Il sistema operativo considera la stampante pronta ad accettare i processi di stampa anche se, per qualche motivo, non riesce a completare il recapito alla stampante fisica. Tale circostanza è considerata uno stato di errore nel sistema operativo che deve essere risolto dall'utente. Non è considerato un errore segnalabile all'applicazione che può completare correttamente lo spooling del processo di stampa.
Determinare lo stato di una stampante fisica
Esiste una premessa fondamentale che deve essere vera per determinare lo stato di una stampante fisica: lo Spooler deve tentare di inviare un processo di stampa alla stampante fisica. Questa è l'unica volta in cui lo stato della stampante viene segnalato dal monitoraggio delle porte. Inoltre, le informazioni più significative possono essere segnalate nei membri di stato di una JOB_INFO
struttura per quel particolare processo di stampa perché alcuni monitor di porta avranno impostato direttamente questi valori.
Le JOB_INFO
strutture contengono un Status
membro e un pStatus
membro. Entrambi i membri contengono informazioni sullo stato di un processo di stampa segnalato dal monitoraggio delle porte. Questi due membri sono diversi in quanto il Status
membro è un campo bit di stati che contiene valori predeterminati, mentre il pStatus
membro è un puntatore a una stringa che potrebbe contenere praticamente qualsiasi elemento. Questi valori sono documentati dall'SDK Win32 e dal file di intestazione WinSpool.h. Il pStatus
membro è talvolta, ma non sempre, impostato su una stringa di stato descrittiva. Il contenuto di questa stringa è definito da ogni monitoraggio delle porte.
JOB_INFO
le strutture vengono restituite da due funzioni API: GetJob
e EnumJobs
. EnumJobs
restituisce una matrice di JOB_INFO
strutture senza richiedere che il chiamante faccia riferimento a un processo specifico nella coda Stampante. Il processo di stampa attualmente in fase di despooling (stampa) contiene le informazioni sullo stato. Per trovare questo processo nella matrice, cercare la matrice di JOB_INFO
strutture per individuare il processo di stampa il cui Status
membro ha il JOB_STATUS_PRINTING
bit impostato.
Un metodo più semplice per determinare lo stato della stampante consiste nell'esaminare il Status
membro di una PRINTER_INFO
struttura. Questa struttura viene restituita dalla GetPrinter
funzione . Questo approccio presenta uno svantaggio perché non esiste alcun pStatus
membro stringa in una PRINTER_INFO
struttura che potrebbe fornire informazioni sullo stato più dettagliate o complete. Tuttavia, esiste un vantaggio in quanto un monitoraggio delle porte può impostare alcuni dei bit di stato della stampante più estesi della PRINTER_INFO
struttura. Tuttavia, il monitoraggio delle porte predefinito per Windows non imposta più del PRINTER_STATUS_ERROR
bit del membro di Status
una stampante.
Nota
I Status
membri di entrambi i set di strutture possono contenere informazioni sullo stato non strettamente correlate alla stampante fisica. Ad esempio, il Status
membro delle PRINTER_INFO
strutture può essere impostato con PRINTER_STATUS_PAUSED
o PRINTER_STATUS_PENDING_DELETION
, che sono strettamente rilevanti per la coda di stampa. Inoltre, il Status
membro della JOB_INFO
struttura può contenere valori di stato per JOB_STATUS_PAUSED
o JOB_STATUS_DELETING
, rilevanti solo per quel particolare processo di stampa. I processi di stampa possono accumularsi in una coda di stampa dopo aver eseguito il despooling e potrebbero essere lasciati con uno stato di JOB_STATUS_PRINTED
.
Ognuna di queste funzioni richiede un handle per una stampante per identificare la stampante desiderata. Questo handle viene ottenuto dalla OpenPrinter
funzione , che accetta una stringa contenente il nome della stampante. Questo nome può essere il nome locale della stampante o un nome di condivisione UNC per una stampante di rete.
Il codice di esempio seguente illustra come chiamare correttamente la EnumJobs
funzione per recuperare JOB_INFO
le strutture e come chiamare la GetPrinter
funzione per recuperare PRINTER_INFO
le strutture:
Codice di esempio
BOOL GetJobs(HANDLE hPrinter, /* Handle to the printer. */
JOB_INFO_2 **ppJobInfo, /* Pointer to be filled. */
int *pcJobs, /* Count of jobs filled. */
DWORD *pStatus) /* Print Queue status. */
{
DWORD cByteNeeded,
nReturned,
cByteUsed;
JOB_INFO_2 *pJobStorage = NULL;
PRINTER_INFO_2 *pPrinterInfo = NULL;
/* Get the buffer size needed. */
if (!GetPrinter(hPrinter, 2, NULL, 0, &cByteNeeded))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
return FALSE;
}
pPrinterInfo = (PRINTER_INFO_2 *)malloc(cByteNeeded);
if (!(pPrinterInfo))
/* Failure to allocate memory. */
return FALSE;
/* Get the printer information. */
if (!GetPrinter(hPrinter,
2,
(LPSTR)pPrinterInfo,
cByteNeeded,
&cByteUsed))
{
/* Failure to access the printer. */
free(pPrinterInfo);
pPrinterInfo = NULL;
return FALSE;
}
/* Get job storage space. */
if (!EnumJobs(hPrinter,
0,
pPrinterInfo->cJobs,
2,
NULL,
0,
(LPDWORD)&cByteNeeded,
(LPDWORD)&nReturned))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
free(pPrinterInfo);
pPrinterInfo = NULL;
return FALSE;
}
}
pJobStorage = (JOB_INFO_2 *)malloc(cByteNeeded);
if (!pJobStorage)
{
/* Failure to allocate Job storage space. */
free(pPrinterInfo);
pPrinterInfo = NULL;
return FALSE;
}
ZeroMemory(pJobStorage, cByteNeeded);
/* Get the list of jobs. */
if (!EnumJobs(hPrinter,
0,
pPrinterInfo->cJobs,
2,
(LPBYTE)pJobStorage,
cByteNeeded,
(LPDWORD)&cByteUsed,
(LPDWORD)&nReturned))
{
free(pPrinterInfo);
free(pJobStorage);
pJobStorage = NULL;
pPrinterInfo = NULL;
return FALSE;
}
/*
* Return the information.
*/
*pcJobs = nReturned;
*pStatus = pPrinterInfo->Status;
*ppJobInfo = pJobStorage;
free(pPrinterInfo);
return TRUE;
}
BOOL IsPrinterError(HANDLE hPrinter)
{
JOB_INFO_2 *pJobs;
int cJobs,
i;
DWORD dwPrinterStatus;
/*
* Get the state information for the Printer Queue and
* the jobs in the Printer Queue.
*/
if (!GetJobs(hPrinter, &pJobs, &cJobs, &dwPrinterStatus))
return FALSE;
/*
* If the Printer reports an error, believe it.
*/
if (dwPrinterStatus &
(PRINTER_STATUS_ERROR |
PRINTER_STATUS_PAPER_JAM |
PRINTER_STATUS_PAPER_OUT |
PRINTER_STATUS_PAPER_PROBLEM |
PRINTER_STATUS_OUTPUT_BIN_FULL |
PRINTER_STATUS_NOT_AVAILABLE |
PRINTER_STATUS_NO_TONER |
PRINTER_STATUS_OUT_OF_MEMORY |
PRINTER_STATUS_OFFLINE |
PRINTER_STATUS_DOOR_OPEN))
{
free( pJobs );
return TRUE;
}
/*
* Find the Job in the Queue that is printing.
*/
for (i=0; i < cJobs; i++)
{
if (pJobs[i].Status & JOB_STATUS_PRINTING)
{
/*
* If the job is in an error state,
* report an error for the printer.
* Code could be inserted here to
* attempt an interpretation of the
* pStatus member as well.
*/
if (pJobs[i].Status &
(JOB_STATUS_ERROR |
JOB_STATUS_OFFLINE |
JOB_STATUS_PAPEROUT |
JOB_STATUS_BLOCKED_DEVQ))
{
free( pJobs );
return TRUE;
}
}
}
/*
* No error condition.
*/
free( pJobs );
return FALSE;
}
Nota
Quando il pool di stampanti è abilitato in Windows NT, potrebbe essere presente più processi di stampa che despooling da una coda della stampante che segnalerà uno stato. Questo codice di esempio non considera tale circostanza.