프린터 및 인쇄 작업의 상태 가져오기

이 문서에서는 Win32 스풀러를 사용하여 프린터 및 인쇄 작업의 상태 가져오는 방법을 소개합니다.

원래 제품 버전: Win32 스풀러
원본 KB 번호: 160129

프린터 및 인쇄 작업의 상태 인쇄 작업의 디풀 중에 Win32 스풀러에 의해 업데이트됩니다. 다른 시간에는 해당 프린터가 풀링되지 않고 상태 정보를 보고하지 않으면 프린터가 준비되고 유휴 상태로 간주됩니다.

Win32 API에서 참조하는 프린터는 프린터 드라이버, 인쇄 큐 및 실제 프린터에 대한 입력/출력 경로로 구성됩니다. 운영 체제는 실제 프린터를 이 문서의 나머지 부분에 프린터라고 하는 시스템 프린터를 통해 생성되고 전달된 인쇄 작업의 대상으로만 취급합니다.

프린터에서 가장 눈에 띄는 부분은 인쇄 큐입니다. Windows 95 스타일 사용자 인터페이스의 인쇄 관리자 또는 프린터 폴더에서 관리됩니다. 프린터 드라이버는 프린터 DC를 통해 인쇄 작업을 만드는 데 애플리케이션에서 사용하는 프린터에 대한 인터페이스입니다. 프린터의 I/O 경로는 포트 모니터로 끝나는 여러 시스템 코드 계층으로 구성됩니다.

포트 모니터는 시스템 프린터의 다운 스트림 끝에 있는 실제 프린터에 대한 인터페이스이며 실제 프린터에 존재하는 모든 연결에서 인쇄 작업의 데이터를 전송하는 일을 담당합니다. 양방향 프린터의 경우 포트 모니터는 실제 프린터로 데이터를 전송하는 작업을 담당합니다. 이 연결 및 실제 프린터는 오류가 발생하는 위치입니다. 이러한 오류를 보고하는 것은 포트 모니터의 작업입니다.

스풀러는 프린터가 연결된 실제 프린터의 상태를 쿼리하지 않습니다. 대신 실제 프린터의 상태는 포트 모니터를 통해 디풀될 때 인쇄 작업의 성공을 결정합니다. 이 프로세스에서 오류가 발생하면 포트 모니터에서 오류를 보고하고 인쇄 작업의 상태 정보에 기록됩니다. 스풀러는 적절한 오류 정보를 프린터 큐에 전파합니다.

따라서 프린터 큐가 비어 있을 때 시스템 프린터는 상태 보고하지 않습니다. 이 상태에서 프린터는 인쇄 작업을 수락할 준비가 된 것으로 간주됩니다. 실제 프린터가 오프라인과 같은 오류 상태에 있더라도 유효한 가정입니다. 운영 체제에서는 프린터가 실제 프린터로 배달을 완료할 수 없는 경우에도 인쇄 작업을 수락할 준비가 된 것으로 간주합니다. 이러한 상황은 사용자가 해결해야 하는 운영 체제의 오류 상태로 간주됩니다. 인쇄 작업의 스풀링을 성공적으로 완료할 수 있는 애플리케이션에 보고할 수 있는 오류로 간주되지 않습니다.

실제 프린터의 상태 확인

실제 프린터의 상태를 확인하려면 true여야 하는 한 가지 기본 전제가 있습니다. 스풀러는 인쇄 작업을 실제 프린터로 보내려고 시도해야 합니다. 포트 모니터에서 프린터 상태를 보고하는 유일한 시간입니다. 또한 일부 포트 모니터에서 이러한 값을 직접 설정했기 때문에 가장 의미 있는 정보는 특정 인쇄 작업에 대한 구조체의 JOB_INFO 상태 멤버에 보고될 수 있습니다.

구조체에는 JOB_INFO 멤버와 멤버가 pStatus 포함 Status 됩니다. 두 멤버 모두 포트 모니터에서 보고한 인쇄 작업의 상태 정보를 포함합니다. 이러한 두 멤버는 멤버가 Status 미리 결정된 값을 포함하는 상태의 비트 필드인 반면 pStatus 멤버는 거의 모든 것을 포함할 수 있는 문자열에 대한 포인터라는 점에서 다릅니다. 이러한 값은 Win32 SDK 및 WinSpool.h 헤더 파일에 의해 문서화됩니다. 멤버가 pStatus 설명적인 상태 문자열로 설정된 경우도 있지만 항상 그렇지는 않습니다. 이 문자열의 내용은 각 포트 모니터에 의해 정의됩니다.

JOB_INFO구조체는 및 EnumJobs의 두 API 함수에 의해 반환됩니다GetJob. EnumJobs 는 호출자가 프린터 큐에서 JOB_INFO 특정 작업을 참조할 필요 없이 구조체 배열을 반환합니다. 현재 디풀링(인쇄)하는 인쇄 작업에는 상태 정보가 포함됩니다. 배열에서 이 작업을 찾으려면 구조체 배열 JOB_INFO 을 검색하여 멤버 JOB_STATUS_PRINTING 에 비트 집합이 있는 Status 인쇄 작업을 찾습니다.

프린터 상태 결정하는 더 쉬운 방법은 구조체의 멤버를 Status 검사하는 것입니다PRINTER_INFO. 이 구조체는 함수에서 반환됩니다 GetPrinter . 구조체에 더 상세하거나 광범위한 상태 정보를 제공할 수 있는 문자열 멤버 PRINTER_INFO 가 없다는 pStatus 측면에서 이 접근 방식에는 단점이 있습니다. 그러나 포트 모니터가 구조의 더 광범위한 프린터 상태 비트를 설정할 수 있다는 장점이 PRINTER_INFO 있습니다. 그러나 Windows의 기본 포트 모니터는 프린터 Status 멤버의 비트보다 PRINTER_STATUS_ERROR 더 많이 설정되지 않습니다.

참고

두 구조체 집합의 멤버는 Status 물리적 프린터와 엄격하게 관련되지 않은 상태 정보를 포함할 수 있습니다. 예를 들어 구조체의 멤버는 Status 인쇄 큐와 엄격하게 관련된 또는 PRINTER_STATUS_PENDING_DELETIONPRINTER_STATUS_PAUSED 설정할 수 PRINTER_INFO 있습니다. 또한 구조체의 멤버는 Status 특정 인쇄 작업과 JOB_STATUS_PAUSED 만 관련된 또는 JOB_STATUS_DELETING의 상태 값을 포함할 수 JOB_INFO 있습니다. 인쇄 작업은 디풀된 후 인쇄 큐에 누적될 수 있으며 상태는 JOB_STATUS_PRINTED입니다.

이러한 각 함수에는 원하는 프린터를 식별하기 위해 프린터 핸들이 필요합니다. 이 핸들은 프린터 이름을 포함하는 문자열을 허용하는 함수에서 OpenPrinter 가져옵니다. 이 이름은 프린터의 로컬 이름이거나 네트워크 프린터에 대한 UNC 공유 이름일 수 있습니다.

다음 샘플 코드에서는 함수를 올바르게 호출 EnumJobs 하여 구조를 검색 JOB_INFO 하는 방법과 함수를 호출 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 프린터 풀링을 사용하도록 설정하면 프린터 큐에서 상태 보고하는 인쇄 작업이 둘 이상 해제될 수 있습니다. 이 샘플 코드는 해당 상황을 고려하지 않습니다.