プリンターと印刷ジョブの状態を取得する
この記事では、Win32 スプーラーを使用してプリンターと印刷ジョブの状態を取得する方法について説明します。
元の製品バージョン: Win32 スプーラー
元の KB 番号: 160129
プリンターと印刷ジョブの状態は、印刷ジョブのデスプール中に Win32 スプーラーによって更新されます。 それ以外の場合でも、そのプリンターがデスプールされておらず、状態情報が報告されない場合、プリンターは準備が整い、アイドル状態であると見なされます。
Win32 API で参照されるように、プリンターはプリンター ドライバー、印刷キュー、および物理プリンターへの入出力パスで構成されます。 オペレーティング システムは、物理プリンターを、この記事の残りの部分でプリンターと呼ばれるシステム プリンターによって生成され、渡される印刷ジョブの宛先として扱います。
プリンターの最も目に見える部分は、印刷キューです。 これは、Windows 95 スタイルのユーザー インターフェイスの印刷マネージャーまたはプリンター フォルダーによって管理されます。 プリンター ドライバーは、プリンター DC を使用して印刷ジョブを作成するためにアプリケーションによって使用されるプリンターへのインターフェイスです。 プリンターの I/O パスは、ポート モニターで最高のシステム コードの複数のレイヤーで構成されます。
ポート・モニターは、システム・プリンターのダウン・ストリーム・エンドにある物理プリンターへのインターフェースであり、物理プリンターに存在する接続を介して印刷ジョブのデータを転送する役割を担います。 双方向プリンターの場合、ポート モニターは、物理プリンターとの間でデータを転送する役割を担います。 この接続と物理プリンターは、エラーが発生する場所です。 これらのエラーを報告するのは、ポート モニターのジョブです。
スプーラーは、プリンターが接続されている物理プリンターの状態を照会しません。 代わりに、物理プリンターの状態によって、ポート モニター経由で印刷ジョブがデスプールされた時点での印刷ジョブの成功が決まります。 このプロセスで何らかのエラーが発生した場合、エラーはポート・モニターによって報告され、印刷ジョブの状況情報に記録されます。 スプーラーは、適切なエラー情報をプリンター キューに伝達します。
そのため、プリンター キューが空の場合、システム プリンターは状態を報告しません。 この状態では、プリンターは印刷ジョブを受け入れる準備ができていると見なされます。 これは、物理プリンターがオフラインなどのエラー状態にある場合でも、有効な想定です。 オペレーティング システムは、何らかの理由で物理プリンターへの配信を完了できない場合でも、プリンターが印刷ジョブを受け入れる準備ができていると見なします。 このような状況は、ユーザーが対処する必要があるオペレーティング システムのエラー状態と見なされます。 印刷ジョブのスプールを正常に完了できるアプリケーションに報告可能なエラーとは見なされません。
物理プリンターの状態を判別する
物理プリンターの状態を判断するには、1 つの基本的な前提として true を指定する必要があります。スプーラーは、印刷ジョブを物理プリンターに送信しようとしている必要があります。 これは、プリンターの状態がポート モニターによって報告される唯一の時間です。 さらに、一部のポート モニターでこれらの値が直接設定されるため、その特定の印刷ジョブの構造体の JOB_INFO
状態メンバーで最も意味のある情報が報告される場合があります。
構造体にはJOB_INFO
、メンバーとメンバーがpStatus
含Status
まれています。 両方のメンバーには、ポート・モニターによって報告された印刷ジョブの状況情報が含まれます。 これら 2 つのメンバーは、メンバーが事前に定義された値を含む状態のビット フィールドであるという点で異なります Status
が、 pStatus
メンバーは何でも含めることができる文字列へのポインターです。 これらの値は、Win32 SDK と WinSpool.h ヘッダー ファイルによって文書化されています。 メンバーは pStatus
、説明的な状態文字列に設定されている場合がありますが、常に設定されるわけではありません。 この文字列の内容は、各ポート モニターによって定義されます。
JOB_INFO
構造体は、 と EnumJobs
の 2 つの API 関数GetJob
によって返されます。 EnumJobs
は、呼び出し元がプリンター キュー内の特定の JOB_INFO
ジョブを参照する必要なく、構造体の配列を返します。 現在デスプール (印刷) されている印刷ジョブには、状態情報が含まれています。 配列内でこのジョブを見つけるには、構造体の JOB_INFO
配列を検索して、メンバーにビットが設定されている Status
印刷ジョブを JOB_STATUS_PRINTING
見つけます。
プリンターの状態を判断する簡単な方法は、構造体のメンバーをStatus
PRINTER_INFO
調べることです。 この構造体は、 関数によって GetPrinter
返されます。 この方法には、より詳細または広範な状態情報をPRINTER_INFO
提供する可能性がある構造体に文字列メンバーが存在しないpStatus
という点で欠点があります。 ただし、ポート モニターは、構造体のより広範なプリンターの状態ビットの一部を PRINTER_INFO
設定する可能性があるという利点があります。 ただし、Windows の既定のポート モニターでは、プリンターStatus
のメンバーのビットを超えるPRINTER_STATUS_ERROR
設定は行われません。
注:
いずれかの構造体のセットのメンバーには Status
、物理的なプリンターに厳密に関連しない状態情報が含まれている場合があります。 たとえば、構造体のStatus
PRINTER_INFO
メンバーは、印刷キューに厳密に関連する または PRINTER_STATUS_PENDING_DELETION
を使用PRINTER_STATUS_PAUSED
して設定できます。 また、構造体のStatus
メンバーには、その特定のJOB_INFO
印刷ジョブにのみ関連する または JOB_STATUS_DELETING
の状態値JOB_STATUS_PAUSED
が含まれている場合があります。 印刷ジョブは、印刷キューがプールされなくなった後に累積され、 の JOB_STATUS_PRINTED
状態のままになる可能性があります。
これらの各機能には、目的のプリンターを識別するためのプリンターへのハンドルが必要です。 このハンドルは、プリンターの名前を OpenPrinter
含む文字列を受け取る 関数から取得されます。 この名前には、プリンターのローカル名、またはネットワーク プリンターの UNC 共有名を指定できます。
次のサンプル コードは、構造体を取得JOB_INFO
するために関数をEnumJobs
適切に呼び出す方法と、関数を呼び出して構造体をGetPrinter
取得PRINTER_INFO
する方法を示しています。
サンプル コード
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でプリンター プールが有効になっている場合、状態を報告するプリンター キューから複数の印刷ジョブがデスプールされている可能性があります。 このサンプル コードでは、その状況は考慮されません。