Yazıcının ve yazdırma işinin durumunu alma
Bu makalede, Win32 Biriktiricisi'ni kullanarak yazıcının ve yazdırma işinin durumunun nasıl alındığı anlatılır.
Orijinal ürün sürümü: Win32 Biriktiricisi
Özgün KB numarası: 160129
Yazıcıların ve yazdırma işlerinin durumu, yazdırma işinin biriktiricisi sırasında Win32 Biriktiricisi tarafından güncelleştirilir. Diğer tüm durumlarda, yazıcının biriktiricisi kaldırılmadığında ve durum bilgisi bildirmiyorsa, yazıcı hazır ve boşta olarak kabul edilir.
Win32 API'sinin başvurduğu gibi, bir yazıcı yazıcı sürücüsünden, yazdırma kuyruğundan ve fiziksel yazıcının giriş/çıkış yolundan oluşur. İşletim sistemi, fiziksel yazıcıyı yalnızca tarafından oluşturulan ve bu makalenin geri kalanında Yazıcı olarak adlandırılan bir sistem Yazıcısı aracılığıyla geçirilen yazdırma işinin hedefi olarak kabul eder.
Yazıcının en görünür kısmı yazdırma kuyruğudur. Windows 95 stili kullanıcı arabirimlerindeki Print Manager veya Yazıcı klasörleri tarafından yönetilir. Yazıcı sürücüsü, yazıcı DC'leri aracılığıyla yazdırma işleri oluşturmak için uygulamalar tarafından kullanılan Yazıcı arabirimidir. Yazıcının G/Ç yolu, bağlantı noktası izleyicisi ile sonuçlandıran çeşitli sistem kodu katmanlarından oluşur.
Bağlantı noktası izleyicisi, bir sistem Yazıcısı'nın aşağı akış ucundaki fiziksel yazıcının arabirimidir ve yazdırma işinin verilerini fiziksel yazıcıya var olan her bağlantıda aktarmaktan sorumludur. çift yönlü yazıcılar söz konusu olduğunda, bağlantı noktası izleyicisi fiziksel yazıcıya ve fiziksel yazıcıdan veri aktarmaktan sorumlu olacaktır. Bu bağlantı ve fiziksel yazıcı hataların oluştuğu yerdir. Bu hataları bildirmek bağlantı noktası izleyicisinin işidir.
Biriktirici, yazıcının bağlı olduğu fiziksel bir yazıcının durumunu sorgulamaz. Bunun yerine, fiziksel yazıcının durumu, yazdırma işinin bağlantı noktası izleyicisi üzerinde biriktirildiğinde başarılı olduğunu belirler. Bu işlemde bir hata oluşursa, hata bağlantı noktası izleyicisi tarafından bildirilir ve yazdırma işinin durum bilgilerine kaydedilir. Biriktirici de makul hata bilgilerini Yazıcı Kuyruğu'na yayılım.
Sonuç olarak, bir sistem Yazıcısı, Yazıcı kuyruğu boş olduğunda durum bildirmez. Bu durumda, Yazıcının yazdırma işlerini kabul etmeye hazır olduğu varsayılır. Fiziksel yazıcı devre dışı gibi bir hata durumunda olsa bile bu geçerli bir varsayımdır. İşletim sistemi, yazıcının fiziksel yazıcıya teslimini tamamlayamıyor olsa bile Yazıcı'nın yazdırma işlerini kabul etmeye hazır olduğunu düşünmektedir. Böyle bir durum, işletim sisteminde kullanıcı tarafından ele alınması gereken bir hata durumu olarak kabul edilir. Yazdırma işinin biriktirilmesi başarıyla tamamlanmasına izin verilen uygulamaya raporlanabilir bir hata olarak kabul edilmez.
Fiziksel yazıcının durumunu belirleme
Fiziksel yazıcının durumunu belirlemek için doğru olması gereken temel bir şirket vardır: Biriktirici fiziksel yazıcıya yazdırma işi göndermeye çalışmalıdır. Bu, yazıcının durumunun bağlantı noktası izleyicisi tarafından bildirildiği tek zamandır. Ayrıca, bazı bağlantı noktası izleyicileri bu değerleri doğrudan ayarlayacağından, söz konusu yazdırma işi için bir JOB_INFO
yapının durum üyelerinde en anlamlı bilgiler bildirilebilir.
Yapılar JOB_INFO
bir Status
üye ve bir pStatus
üye içerir. Her iki üye de bağlantı noktası izleyicisi tarafından bildirilen yazdırma işinin durum bilgilerini içerir. Bu iki üye, üyenin Status
önceden belirlenmiş değerler içeren bir bit durum alanı olması açısından farklılık gösterirken pStatus
, üye hemen hemen her şeyi içerebilen bir dizeye yönelik bir işaretçidir. Bu değerler Win32 SDK ve WinSpool.h üst bilgi dosyası tarafından belgelenir. Üye pStatus
bazen açıklayıcı bir durum dizesine ayarlanır ancak her zaman ayarlanmaz. Bu dizenin içeriği her bağlantı noktası izleyicisi tarafından tanımlanır.
JOB_INFO
yapıları iki API işlevi tarafından döndürülür: GetJob
ve EnumJobs
. EnumJobs
çağıranın JOB_INFO
Yazıcı kuyruğundaki belirli bir işe başvurmasını gerektirmeden bir yapı dizisi döndürür. Şu anda biriktirici (yazdırma) olan yazdırma işi durum bilgilerini içerir. Dizide bu işi bulmak için, üyesi bit kümesine sahip yazdırma işini Status
bulmak için yapı dizisini JOB_INFO
JOB_STATUS_PRINTING
arayın.
Yazıcı durumunu belirlemenin daha kolay bir yöntemi, bir PRINTER_INFO
yapının üyesini Status
incelemektir. Bu yapı işlevi tarafından GetPrinter
döndürülür. Bu yaklaşımın dezavantajı, daha ayrıntılı veya kapsamlı durum bilgileri sağlayabilecek bir PRINTER_INFO
yapıda dize üyesi olmamasıdırpStatus
. Ancak, bağlantı noktası izleyicisinin yapının daha kapsamlı yazıcı durumu bitlerinden PRINTER_INFO
bazılarını ayarlayabileceğinin bir avantajı vardır. Ancak, Windows için varsayılan bağlantı noktası izleyicisinin Yazıcı'nın Status
üyesinin PRINTER_STATUS_ERROR
bitinden daha fazlasını ayarlamaması gerekir.
Not
Her Status
iki yapı kümesinin üyeleri, fiziksel yazıcıyla kesinlikle ilgili olmayan durum bilgileri içerebilir. Örneğin, Status
yapıların PRINTER_INFO
üyesi, Yazdırma Kuyruğu ile kesinlikle ilgili olan veya PRINTER_STATUS_PENDING_DELETION
ile PRINTER_STATUS_PAUSED
ayarlanabilir. Ayrıca, Status
yapının üyesi JOB_INFO
yalnızca belirli bir yazdırma işiyle ilgili olan veya JOB_STATUS_DELETING
için JOB_STATUS_PAUSED
durum değerleri içerebilir. Yazdırma işleri, biriktirildikten sonra yazdırma kuyruğunda birikebilir ve durumu JOB_STATUS_PRINTED
olarak bırakılabilir.
Bu işlevlerin her biri, istenen Yazıcıyı tanımlamak için bir yazıcı tutamacı gerektirir. Bu tanıtıcı, yazıcının OpenPrinter
adını içeren bir dizeyi kabul eden işlevinden alınır. Bu ad, yazıcının yerel adı veya ağ yazıcısının UNC paylaşım adı olabilir.
Aşağıdaki örnek kodda, yapıları almak JOB_INFO
için işlevin düzgün bir şekilde çağrılmaya EnumJobs
ve yapıları almak PRINTER_INFO
için işlevin nasıl çağrılmaya çalışılmaya çalışılmaya çalışılarak GetPrinter
gösterildiği gösterilmiştir:
Örnek Kod
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;
}
Not
Windows NT'da yazıcı havuzu etkinleştirildiğinde, durumu bildirecek bir Yazıcı kuyruğundan birden fazla yazdırma işi biriktiriliyor olabilir. Bu örnek kod bu durumu dikkate almaz.