現在オフラインです。再接続するためにインターネットの接続を待っています

プリンタと印刷ジョブの状態の取得方法

この記事は、以前は次の ID で公開されていました: JP160129
概要
プリンタと印刷ジョブの状態は、ジョブを印刷する (スプールから取り出す) ときに、Win32 スプーラによって更新されます。それ以外の場合、プリンタが印刷しないままで状態情報が報告されないときは、プリンタはアイドル状態で印刷可能であると見なされます。
詳細
Win32 API では、"プリンタ" とは、プリンタ ドライバ、プリント キュー、およびプリンタ装置との入出力の経路から構成されます。オペレーティング システムは、プリンタ装置を、単にこのシステムの "プリンタ" によって生成され、転送される印刷ジョブの出力先と見なします。この資料での "プリンタ" は、このシステムのプリンタを意味します。

プリンタの中でユーザーから見えやすい部分は、プリント キューです。これは、プリント マネージャまたは Windows 95 スタイルのユーザー インターフェイスの場合はプリンタ フォルダによって管理されます。プリンタ ドライバは、アプリケーションがプリンタ DC を経由して印刷ジョブを作成するためのインターフェイスです。プリンタの入出力の経路は、システム コードのいくつかの階層によって構成され、その最下層はポート モニタです。

ポート モニタは、システム プリンタのダウンストリームの最下端にあるプリンタ装置とのインターフェイスで、プリンタ装置との接続が存在する場合は常に印刷ジョブのデータ転送を担当します。双方向通信のプリンタの場合、ポート モニタは、プリンタ装置との間でのデータ転送を担当します。エラーが発生するのは、この接続とプリンタ装置です。そのエラーを報告するのもポート モニタの仕事です。

スプーラは、プリンタが接続されるプリンタ装置の状態を監視しません。その代わり、印刷ジョブが成功するかどうかは、印刷ジョブがポート モニタを経由してプリンタ装置に送信されたときに、そのジョブの状態によって決まります。このときのプロセスでエラーが発生すると、ポート モニタによってエラーが報告され、印刷ジョブの状態情報として記録されます。その後、スプーラが適切なエラー情報をプリント キューに伝えます。

したがって、システムのプリンタは、そのプリント キューにジョブがないときには状態を報告しません。この状態のとき、プリンタは印刷ジョブの受け入れが可能と見なされます。プリンタ装置がオフラインなどのエラー状態のときでも、これは有効な動作です。オペレーティング システムは、何らかの理由で、物理的なプリンタ装置へのジョブの転送を完了させることができなくても、印刷ジョブを受け入れることはできると判断します。オペレーティング システムは、このような状況はユーザーによって解決される必要があるエラーであって、印刷ジョブのスプールを正常に完了させることができるアプリケーションに報告するエラーではないと判断します。

プリンタ装置の状態の判断

プリンタ装置の状態を判断する際に、1 つ重要なことがあります。それは、スプーラが、プリンタ装置に印刷ジョブの送信を試みる必要があるということです。送信してみないと、ポート モニタからプリンタの状態が報告されません。また、ポート モニタによっては JOB_INFO 構造体のメンバの値を直接設定できる場合があるため、最も意味のある情報はこれらのメンバによって報告されることがあります。

JOB_INFO 構造体には、Status メンバと pStatus メンバがあります。これらのメンバは、ポート モニタによって報告された印刷ジョブの状態情報を含んでいます。Status メンバは、事前に定義されている値を含む、状態のビット フィールドであるのに対し、pStatus メンバは、任意の状態を含むことができる文字列のポインタです。これらの値については、Win32 SDK と WinSpool.h ヘッダー ファイルで定義されています。pStatus メンバは、状態を表す文字列に設定される場合がありますが、必ずそのように設定されるとは限りません。この文字列の内容は、各ポート モニタによって定義されます。

JOB_INFO 構造体は、GetJob と EnumJobs の 2 つの API 関数によって取得できます。EnumJobs は、呼び出し側でプリント キュー内の特定のジョブを参照しなくても、JOB_INFO 構造体を配列で返します。現在印刷中の印刷ジョブが状態情報を含んでいます。配列の中から、このジョブを見つけるためには、JOB_INFO 構造体の Status メンバに JOB_STATUS_PRINTING ビットが設定されているジョブを探します。

プリンタの状態をより簡単に判断する方法は、PRINTER_INFO 構造体の Status メンバを確認することです。この構造体は、GetPrinter 関数によって取得できます。しかし、PRINTER_INFO 構造体には、より詳細または広範な状態情報を提供する pStatus 文字列メンバがないという短所があります。一方で、ポート モニタは、PRINTER_INFO 構造体に、より広範なプリンタの状態ビットを設定できるという長所があります。ただし、通常、Windows のデフォルトのポート モニタは、プリンタの Status メンバの PRINTER_STATUS_ERROR ビット以上の情報を設定しません。

どちらの構造体の Status メンバも、厳密にはプリンタ装置に関連しない状態情報を含みます。たとえば、PRINTER_INFO 構造体の Status メンバは、プリント キューに厳密に関連する PRINTER_STATUS_PAUSED や PRINTER_STATUS_PENDING_DELETION で設定される場合があります。また、JOB_INFO 構造体の Status メンバは、特定の印刷ジョブにのみ関連する JOB_STATUS_PAUSED や JOB_STATUS_DELETING の状態値を含む場合があります。また、印刷ジョブは印刷後、JOB_STATUS_PRINTED の状態でプリント キューに残すことも可能です。

これらの個々の関数は、プリンタを特定するためにプリンタのハンドルを必要とします。このハンドルは、OpenPrinter 関数でプリンタ名を指定して取得できます。プリンタ名には、ローカル プリンタ名やネットワーク プリンタの UNC 共有名のいずれでも使用できます。

以下のサンプル コードは、JOB_INFO 構造体を取得する EnumJobs 関数の適切な使用方法と、PRINTER_INFO 構造体を取得する GetPrinter 関数の使用方法を示しています。

サンプル コード

   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;   }				
: Windows NT でプリンタ プールが有効になっている場合は、状態を報告するプリント キューから複数の印刷ジョブが印刷されることがあります。このサンプル コードでは、この状況は考慮されていません。
関連情報
Win32 スプーラ機能の呼び出しの一般的な使用方法の関連情報を参照するには、以下の「サポート技術情報」 (Microsoft Knowledge Base) をクリックしてください。
158828 SDK32:Win32 スプーラの列挙 API の呼び出し方
関連情報
この資料は米国 Microsoft Corporation から提供されている Knowledge Base の Article ID 160129 (最終更新日 2005-05-19) を基に作成したものです。

この資料に含まれているサンプル コード/プログラムは英語版を前提に書かれたものをありのままに記述しており、日本語環境での動作は確認されておりません。
GdiSpool
プロパティ

文書番号:160129 - 最終更新日: 09/26/2005 09:03:00 - リビジョン: 4.0

Microsoft Win32 Application Programming Interface

  • kbhowto kbfaq KB160129
フィードバック
createElement('meta');m.name='ms.dqp0';m.content='true';document.getElementsByTagName('head')[0].appendChild(m);" onload="var m=document.createElement('meta');m.name='ms.dqp0';m.content='false';document.getElementsByTagName('head')[0].appendChild(m);" src="http://c1.microsoft.com/c.gif?">