Практическое руководство. Определение возможности печати в заданное время суток
Обновлен: Ноябрь 2007
Очереди печати не всегда доступны 24 часа в сутки. У них есть свойства времени начала и окончания, установка которых делает очереди печати недоступными в определенные часы. Эта возможность может быть использована, например, чтобы зарезервировать принтер для монопольного использования определенным отделом после 17.00. Этому отделу необходимо иметь отличную от других отделов очередь обслуживания принтера. Для других отделов очередь станет недоступной после 17.00, в то время как очередь для привилегированного отдела может быть доступна круглосуточно.
Кроме того, сами задания печати могут быть доступны для печати только в указанный промежуток времени.
Классы PrintQueue и PrintSystemJobInfo, представленные в API-интерфейсыMicrosoft .NET Framework, предоставляют средства для удаленной проверки возможности печати данного задания из данной очереди в текущий момент.
Пример
Ниже приведен пример приложения, выполняющего диагностику проблем с заданиями печати. Полный пример см. в разделе Пример диагностики неполадок при выполнении заданий печати.
Для этого типа функций существуют два основных действия, которые показаны ниже.
Считайте значения свойств StartTimeOfDay и UntilTimeOfDay для PrintQueue, чтобы определить, находится ли текущее время в интервале между ними.
Считайте значения свойств StartTimeOfDay и UntilTimeOfDay для PrintSystemJobInfo, чтобы определить, находится ли текущее время в интервале между ними.
Сложности возникают из-за того, что эти свойства не являются объектами DateTime. Они являются объектами Int32, представляющими время суток как число минут после полуночи. Кроме того, под полночью подразумевается полночь не в текущем часовом поясе, а полночь по Гринвичу (UTC).
В первом примере кода представлен статический метод ReportQueueAndJobAvailability, которому передается PrintSystemJobInfo и который вызывает вспомогательные методы для определения, можно ли напечатать задание в текущий момент, и если нет — время возможной печати. Обратите внимание, что PrintQueue не передается методу. Это происходит потому, что PrintSystemJobInfo содержит ссылку на очередь в своем свойстве HostingPrintQueue.
Подчиненные методы включают перегруженный метод ReportAvailabilityAtThisTime, который может принимать в качестве параметра либо PrintQueue, либо PrintSystemJobInfo. Также имеется TimeConverter.ConvertToLocalHumanReadableTime. Все эти методы рассматриваются ниже.
Метод ReportQueueAndJobAvailability начинается с проверки доступности очереди или задания печати в текущий момент. Если хотя бы одно из них недоступно, то проверяется доступность очереди. Если она недоступна, то метод выдает отчет об этом факте и времени, когда очередь вновь станет доступной. Затем проверяется задание и, в случае его недоступности, выводится следующий промежуток времени, когда оно может быть напечатано. Наконец, метод сообщает ближайшее время, когда задание можно напечатать. Это наиболее позднее время из двух следующих вариантов.
Время, когда в очередь печати вновь будет доступна.
Время, когда задание печати вновь будет доступно.
При сообщении времени суток также вызывается метод 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
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());
}
}
};
Два перегруженных метода ReportAvailabilityAtThisTime идентичны, за исключением передаваемого в них типа, поэтому ниже рассматривается только версия PrintQueue. (Полный пример см. в разделе Пример диагностики неполадок при выполнении заданий печати).
Примечание. |
---|
Тот факт, что методы идентичны за исключением типа, вызывает вопрос, почему в примере не создается универсальный метод ReportAvailabilityAtThisTime<T>. Причиной является то, что такой метод был бы ограничен классом значений свойств StartTimeOfDay и UntilTimeOfDay, которые вызывает метод, но универсальный метод может быть ограничен только одним классом, и единственным общим для PrintQueue и PrintSystemJobInfo классом в дереве наследования является PrintSystemObject, который не имеет таких свойств. |
Метод ReportAvailabilityAtThisTime (представлен в следующем примере кода) начинается с инициализации сигнальной переменной Boolean в значение true. Если очередь недоступна, значение будет изменено на false,.
Затем метод проверяет совпадение времени начала и завершения. Если они идентичны, то очередь доступна всегда, поэтому метод возвращает true.
Если очередь все время не доступна, то метод использует статическое свойство UtcNow для получения текущего времени в виде объекта DateTime. (Локальное время не требуется, поскольку свойства StartTimeOfDay и UntilTimeOfDay используют формат UTC).
Однако эти два свойства не являются объектами DateTime. Они являются объектами Int32, задающими время как число минут после полуночи в формате UTC. Поэтому необходимо преобразовать объект DateTime в минуты после полуночи. После этого метод осуществляет проверку попадания текущего времени в интервал между началом и завершением очереди, устанавливает флаг в «false», если текущее время не принадлежит этому интервалу, и возвращает этот флаг.
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
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;
};
Метод TimeConverter.ConvertToLocalHumanReadableTime (представлен в следующем примере кода) не использует методы, которые используются с Microsoft .NET Framework, поэтому изложение будет кратким. Данный метод имеет задачу двойного преобразования. Он должен принимать число, выраженное числом минут после полуночи, и преобразовывать его в удобный для восприятия вид, а затем к местному времени. Для этого сначала создается объект DateTime, который имеет значение полночи по Гринвичу, и затем используется метод AddMinutes для добавления минут, которые были переданы в метод. При этом возвращается новый объект DateTime, содержащий исходное время, которое было передано в метод. Затем метод ToLocalTime преобразует его к местному времени.
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
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;
};
};
См. также
Основные понятия
Документы в Windows Presentation Foundation