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_INFOJOB_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_DELETIONile 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_DELETINGiçin JOB_STATUS_PAUSED durum değerleri içerebilir. Yazdırma işleri, biriktirildikten sonra yazdırma kuyruğunda birikebilir ve durumu JOB_STATUS_PRINTEDolarak 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.