방법: 인쇄 작업을 현재 인쇄할 수 있는지 확인
인쇄 대기열을 늘 하루 24시간 동안 사용할 수 있는 것은 아닙니다. 하루 중 인쇄 대기열에는 특정 시간에 사용할 수 없도록 설정될 수 있는 시작 및 종료 시간 속성이 있습니다. 예를 들어, 오후 5시 이후에 특정 부서에서만 사용하도록 프린터를 예약할 때 이 기능을 사용할 수 있습니다. 해당 부서의 프린터 사용 대기열은 다른 부서에서 사용하는 것과 다를 것입니다. 다른 부서의 대기열은 오후 5시 이후에 사용할 수 없도록 설정되지만 선호하는 부서의 대기열은 항상 사용할 수 있도록 설정할 수 있을 것입니다.
또한 인쇄 작업 자체는 지정된 시간 범위 내에서만 인쇄가 가능하도록 설정할 수 있습니다.
Microsoft .NET Framework의 API에 노출되는 PrintQueue 및 PrintSystemJobInfo 클래스를 통해 지정된 인쇄 작업이 현재 지정된 대기열에서 인쇄할 수 있는지 여부를 원격으로 확인할 수 있습니다.
예제
아래 예제는 인쇄 작업의 문제를 진단할 수 있는 샘플입니다.
이 종류의 기능에는 다음 두 가지 주요 단계가 있습니다.
PrintQueue의 StartTimeOfDay 및 UntilTimeOfDay 속성을 읽어 현재 시간이 이 둘 사이인지 확인합니다.
PrintQueue의 StartTimeOfDay 및 UntilTimeOfDay 속성을 읽어 현재 시간이 이 둘 사이인지 확인합니다.
그러나 이러한 속성이 DateTime 개체가 아니라는 사실에서 문제가 발생합니다. 이러한 속성은 자정 이후 시간(분)으로 시간을 표현하는 Int32 개체입니다. 게다가 현재 표준 시간대의 자정이 아니라 자정 UTC(협정 세계시)입니다.
첫 번째 코드 예제는 PrintSystemJobInfo로 전달되는 정적 메서드 ReportQueueAndJobAvailability를 제시하고 도우미 메서드를 호출하여 작업이 현재 시간에 인쇄할 수 있는지 여부와 인쇄할 수 있는 시점을 확인합니다. PrintQueue는 메서드로 전달되지 않습니다. PrintSystemJobInfo는 그 HostingPrintQueue 속성에 대기열 참조가 포함되기 때문입니다.
하위 메서드에는 PrintQueue 또는 PrintSystemJobInfo를 매개변수로 사용할 수 있는 오버로드된 ReportAvailabilityAtThisTime 메서드가 포함됩니다. TimeConverter.ConvertToLocalHumanReadableTime도 있습니다. 이 모든 방법이 아래에 설명되어 있습니다.
ReportQueueAndJobAvailability 메서드는 현재 대기열 또는 인쇄 작업을 사용할 수 없는지 여부를 확인하는 것으로 시작합니다. 둘 중 하나를 사용할 수 없는 경우 대기열을 사용할 수 없는지 확인합니다. 사용할 수 없는 경우 이 메서드는 이 사실과 대기열을 다시 사용할 수 있게 되는 시간을 보고합니다. 그런 다음 작업을 확인하고 작업을 사용할 수 없는 경우 인쇄할 수 있는 다음 시간 범위를 보고합니다. 마지막으로 이 메서드는 작업을 인쇄할 수 있는 가장 빠른 시간을 보고합니다. 이것은 다음 두 시간 중 나중 시간입니다.
다음에 인쇄 대기열을 사용할 수 있는 시간입니다.
다음에 인쇄 작업을 사용할 수 있는 시간입니다.
하루 중 시간을 보고할 때 ToShortTimeString 메서드도 호출되는데 그 이유는 출력에 연, 월, 일을 표시하지 않기 때문입니다. 인쇄 대기열 또는 인쇄 작업의 사용 가능성을 특정 연, 월, 일로 제한할 수 없습니다.
static void ReportQueueAndJobAvailability (PrintSystemJobInfo^ theJob)
{
if (!(ReportAvailabilityAtThisTime(theJob->HostingPrintQueue) && ReportAvailabilityAtThisTime(theJob)))
{
if (!ReportAvailabilityAtThisTime(theJob->HostingPrintQueue))
{
Console::WriteLine("\nThat queue is not available at this time of day." + "\nJobs in the queue will start printing again at {0}", TimeConverter::ConvertToLocalHumanReadableTime(theJob->HostingPrintQueue->StartTimeOfDay).ToShortTimeString());
// TimeConverter class is defined in the complete sample
}
if (!ReportAvailabilityAtThisTime(theJob))
{
Console::WriteLine("\nThat job is set to print only between {0} and {1}", TimeConverter::ConvertToLocalHumanReadableTime(theJob->StartTimeOfDay).ToShortTimeString(), TimeConverter::ConvertToLocalHumanReadableTime(theJob->UntilTimeOfDay).ToShortTimeString());
}
Console::WriteLine("\nThe job will begin printing as soon as it reaches the top of the queue after:");
if (theJob->StartTimeOfDay > theJob->HostingPrintQueue->StartTimeOfDay)
{
Console::WriteLine(TimeConverter::ConvertToLocalHumanReadableTime(theJob->StartTimeOfDay).ToShortTimeString());
} else
{
Console::WriteLine(TimeConverter::ConvertToLocalHumanReadableTime(theJob->HostingPrintQueue->StartTimeOfDay).ToShortTimeString());
}
}
};
internal static void ReportQueueAndJobAvailability(PrintSystemJobInfo theJob)
{
if (!(ReportAvailabilityAtThisTime(theJob.HostingPrintQueue) && ReportAvailabilityAtThisTime(theJob)))
{
if (!ReportAvailabilityAtThisTime(theJob.HostingPrintQueue))
{
Console.WriteLine("\nThat queue is not available at this time of day." +
"\nJobs in the queue will start printing again at {0}",
TimeConverter.ConvertToLocalHumanReadableTime(theJob.HostingPrintQueue.StartTimeOfDay).ToShortTimeString());
// TimeConverter class is defined in the complete sample
}
if (!ReportAvailabilityAtThisTime(theJob))
{
Console.WriteLine("\nThat job is set to print only between {0} and {1}",
TimeConverter.ConvertToLocalHumanReadableTime(theJob.StartTimeOfDay).ToShortTimeString(),
TimeConverter.ConvertToLocalHumanReadableTime(theJob.UntilTimeOfDay).ToShortTimeString());
}
Console.WriteLine("\nThe job will begin printing as soon as it reaches the top of the queue after:");
if (theJob.StartTimeOfDay > theJob.HostingPrintQueue.StartTimeOfDay)
{
Console.WriteLine(TimeConverter.ConvertToLocalHumanReadableTime(theJob.StartTimeOfDay).ToShortTimeString());
}
else
{
Console.WriteLine(TimeConverter.ConvertToLocalHumanReadableTime(theJob.HostingPrintQueue.StartTimeOfDay).ToShortTimeString());
}
}//end if at least one is not available
}//end ReportQueueAndJobAvailability
Friend Shared Sub ReportQueueAndJobAvailability(ByVal theJob As PrintSystemJobInfo)
If Not(ReportAvailabilityAtThisTime(theJob.HostingPrintQueue) AndAlso ReportAvailabilityAtThisTime(theJob)) Then
If Not ReportAvailabilityAtThisTime(theJob.HostingPrintQueue) Then
Console.WriteLine(vbLf & "That queue is not available at this time of day." & vbLf & "Jobs in the queue will start printing again at {0}", TimeConverter.ConvertToLocalHumanReadableTime(theJob.HostingPrintQueue.StartTimeOfDay).ToShortTimeString())
' TimeConverter class is defined in the complete sample
End If
If Not ReportAvailabilityAtThisTime(theJob) Then
Console.WriteLine(vbLf & "That job is set to print only between {0} and {1}", TimeConverter.ConvertToLocalHumanReadableTime(theJob.StartTimeOfDay).ToShortTimeString(), TimeConverter.ConvertToLocalHumanReadableTime(theJob.UntilTimeOfDay).ToShortTimeString())
End If
Console.WriteLine(vbLf & "The job will begin printing as soon as it reaches the top of the queue after:")
If theJob.StartTimeOfDay > theJob.HostingPrintQueue.StartTimeOfDay Then
Console.WriteLine(TimeConverter.ConvertToLocalHumanReadableTime(theJob.StartTimeOfDay).ToShortTimeString())
Else
Console.WriteLine(TimeConverter.ConvertToLocalHumanReadableTime(theJob.HostingPrintQueue.StartTimeOfDay).ToShortTimeString())
End If
End If 'end if at least one is not available
End Sub
ReportAvailabilityAtThisTime 메서드의 두 오버로드는 동일하지만 이에 전달되는 형식만 다르므로 PrintQueue 버전만 아래에 표시됩니다.
참고
두 메서드가 동일하지만 형식만 달라 이 샘플에서는 제네릭 메서드 ReportAvailabilityAtThisTime<T>를 만들지 않는 이유에 대한 의문이 제기됩니다. 그 이유는 이러한 메서드는 메서드가 호출하지만 제네릭 메서드가 단일 클래스로 제한될 수 있는 StartTimeOfDay 및 UntilTimeOfDay 속성이 있는 클래스로 제한해야 하지만 제네릭 메서드는 단일 클래스로 제한될 수 있으며 상속 트리에서 PrintQueue와 PrintSystemJobInfo에만 공통되는 클래스는 이러한 속성이 없는 PrintSystemObject이기 때문입니다.
ReportAvailabilityAtThisTime 메서드(아래 코드 예제에 다옴)는 Boolean sentinel 변수를 true
로 초기화하는 것으로 시작합니다. 대기열을 사용할 수 없는 경우 false
로 다시 설정됩니다.
다음으로 이 메서드는 시작 시간과 "끝" 시간이 같은지 확인합니다. 같으면 대기열을 항상 사용할 수 있어 메서드가 true
를 반환합니다.
대기열을 항상 사용할 수 없는 경우 메서드는 정적 UtcNow 속성을 사용하여 현재 시간을 DateTime 개체로 가져옵니다. (StartTimeOfDay 및 UntilTimeOfDay 속성은 UTC 시간이므로 현지 시간이 필요하지 않습니다.)
그러나 이 두 속성은 DateTime 개체가 아닙니다. 이 둘은 시간을 UTC-자정 이후의 분 수로 표현하는 Int32다. 따라서 DateTime 개체를 자정 이후 분으로 변환해야 합니다. 이 작업이 완료되면 메서드는 단순히 "지금"이 대기열의 시작 시간과 "끝" 시간 사이인지 확인하고, "지금"이 두 시간 사이에 있지 않으면 sentinel을 false로 설정하고, sentinel을 반환합니다.
static Boolean ReportAvailabilityAtThisTime (PrintQueue^ pq)
{
Boolean available = true;
if (pq->StartTimeOfDay != pq->UntilTimeOfDay)
{
DateTime utcNow = DateTime::UtcNow;
Int32 utcNowAsMinutesAfterMidnight = (utcNow.TimeOfDay.Hours * 60) + utcNow.TimeOfDay.Minutes;
// If now is not within the range of available times . . .
if (!((pq->StartTimeOfDay < utcNowAsMinutesAfterMidnight) && (utcNowAsMinutesAfterMidnight < pq->UntilTimeOfDay)))
{
available = false;
}
}
return available;
};
private static Boolean ReportAvailabilityAtThisTime(PrintQueue pq)
{
Boolean available = true;
if (pq.StartTimeOfDay != pq.UntilTimeOfDay) // If the printer is not available 24 hours a day
{
DateTime utcNow = DateTime.UtcNow;
Int32 utcNowAsMinutesAfterMidnight = (utcNow.TimeOfDay.Hours * 60) + utcNow.TimeOfDay.Minutes;
// If now is not within the range of available times . . .
if (!((pq.StartTimeOfDay < utcNowAsMinutesAfterMidnight)
&&
(utcNowAsMinutesAfterMidnight < pq.UntilTimeOfDay)))
{
available = false;
}
}
return available;
}//end ReportAvailabilityAtThisTime
Private Shared Function ReportAvailabilityAtThisTime(ByVal pq As PrintQueue) As Boolean
Dim available As Boolean = True
If pq.StartTimeOfDay <> pq.UntilTimeOfDay Then ' If the printer is not available 24 hours a day
Dim utcNow As Date = Date.UtcNow
Dim utcNowAsMinutesAfterMidnight As Int32 = (utcNow.TimeOfDay.Hours * 60) + utcNow.TimeOfDay.Minutes
' If now is not within the range of available times . . .
If Not((pq.StartTimeOfDay < utcNowAsMinutesAfterMidnight) AndAlso (utcNowAsMinutesAfterMidnight < pq.UntilTimeOfDay)) Then
available = False
End If
End If
Return available
End Function 'end ReportAvailabilityAtThisTime
TimeConverter.ConvertToLocalHumanReadableTime 메서드(아래 코드 예제에 나옴)는 Microsoft .NET Framework에 도입된 메서드를 사용하지 않으므로 여기서는 간단하게 다룹니다. 이 메서드에는 이중 변환 작업이 있어 자정 이후 분을 표현하는 정수를 사람이 읽을 수 있는 시간으로 변환해야 하며 이를 현지 시간으로 변환해야 합니다. 먼저 UTC 자정으로 설정된 DateTime 개체를 만든 다음 AddMinutes 메서드를 사용하여 메서드에 전달된 분을 추가하여 이 작업을 수행합니다. 그러면 메서드에 전달된 원래 시간을 표현하는 새 DateTime가 반환됩니다. 그런 다음 ToLocalTime 메서드가 이를 현지 시간으로 변환합니다.
private ref class TimeConverter {
internal:
static DateTime ConvertToLocalHumanReadableTime (Int32 timeInMinutesAfterUTCMidnight)
{
// Construct a UTC midnight object.
// Must start with current date so that the local Daylight Savings system, if any, will be taken into account.
DateTime utcNow = DateTime::UtcNow;
DateTime utcMidnight = DateTime(utcNow.Year, utcNow.Month, utcNow.Day, 0, 0, 0, DateTimeKind::Utc);
// Add the minutes passed into the method in order to get the intended UTC time.
Double minutesAfterUTCMidnight = ((Double)timeInMinutesAfterUTCMidnight);
DateTime utcTime = utcMidnight.AddMinutes(minutesAfterUTCMidnight);
// Convert to local time.
DateTime localTime = utcTime.ToLocalTime();
return localTime;
};
};
class TimeConverter
{
// Convert time as minutes past UTC midnight into human readable time in local time zone.
internal static DateTime ConvertToLocalHumanReadableTime(Int32 timeInMinutesAfterUTCMidnight)
{
// Construct a UTC midnight object.
// Must start with current date so that the local Daylight Savings system, if any, will be taken into account.
DateTime utcNow = DateTime.UtcNow;
DateTime utcMidnight = new DateTime(utcNow.Year, utcNow.Month, utcNow.Day, 0, 0, 0, DateTimeKind.Utc);
// Add the minutes passed into the method in order to get the intended UTC time.
Double minutesAfterUTCMidnight = (Double)timeInMinutesAfterUTCMidnight;
DateTime utcTime = utcMidnight.AddMinutes(minutesAfterUTCMidnight);
// Convert to local time.
DateTime localTime = utcTime.ToLocalTime();
return localTime;
}// end ConvertToLocalHumanReadableTime
}//end TimeConverter class
Friend Class TimeConverter
' Convert time as minutes past UTC midnight into human readable time in local time zone.
Friend Shared Function ConvertToLocalHumanReadableTime(ByVal timeInMinutesAfterUTCMidnight As Int32) As Date
' Construct a UTC midnight object.
' Must start with current date so that the local Daylight Savings system, if any, will be taken into account.
Dim utcNow As Date = Date.UtcNow
Dim utcMidnight As New Date(utcNow.Year, utcNow.Month, utcNow.Day, 0, 0, 0, DateTimeKind.Utc)
' Add the minutes passed into the method in order to get the intended UTC time.
Dim minutesAfterUTCMidnight As Double = CType(timeInMinutesAfterUTCMidnight, Double)
Dim utcTime As Date = utcMidnight.AddMinutes(minutesAfterUTCMidnight)
' Convert to local time.
Dim localTime As Date = utcTime.ToLocalTime()
Return localTime
End Function ' end ConvertToLocalHumanReadableTime
End Class
참고 항목
.NET Desktop feedback