Como: Discover Whether a Print Job Can Be Printed At This Time of Day
Filas de impressão nem sempre estão disponíveis 24 horas por dia. Elas têm propriedades de horários de início e fim que podem ser definidas para torná-las indisponíveis em certas horas do dia. Essa característica pode ser utilizada, por exemplo, para reservar uma impressora para uso exclusivo de um certo departamento após 5 P.M. Aquele departamento poderia ter uma fila diferente oferecendo serviço de impressão que outros departamentos utilizam. A fila para outros departamentos poderia ser definida como indisponível após 5 P.M., enquanto a fila para o departamento favorecido poderia ser definida como disponível a toda hora.
Além disso, os próprios trabalhos de impressão podem ser definidos para serem impressos apenas numa determinada faixa de tempo.
As classes PrintQueue e PrintSystemJobInfo expostas nas APIs do Microsoft .NET Framework fornecem um meio de verificar remotamente se um determinado trabalho de impressão pode ser impresso numa dada fila no momento atual.
Exemplo
O exemplo abaixo é tirado de uma aplicação de exemplo que pode diagnosticar problemas com um trabalho de impressão. Para o exemplo completo, veja Diagnosticar problemáticos trabalho de Imprimir exemplo.
Há dois passos principais para esse tipo de função, como segue.
Ler as propriedades StartTimeOfDay e UntilTimeOfDay do PrintQueue para determinar se o horário atual está entre eles.
Ler as propriedades StartTimeOfDay e UntilTimeOfDay do PrintSystemJobInfo para determinar se o horário atual está entre eles.
Mas complicaçoes surgem do fato que essas propriedades não são objetos DateTime. Em vez disso, são objetos Int32 que expressam a hora do dia como número de minutos desde a meia-noite. Além disso, não é meia-noite na zona de horário atual, mas meia-noite UTC (Coordinated Universal Time).
O primeiro código de exemplo apresenta o método estático ReportQueueAndJobAvailability, a que é passado um PrintSystemJobInfo e chama métodos auxiliares para determinar se um trabalho pode ser impresso no horário atual e, se não, quando pode ser impresso. Observe que um PrintQueue não é passado para o método. Isso ocorre porque o PrintSystemJobInfo inclui uma referência à fila na sua propriedade HostingPrintQueue.
Os métodos subordinados incluem o método sobrecarregado ReportAvailabilityAtThisTime que pode receber um PrintQueue ou um PrintSystemJobInfo como parâmetro. Também há um TimeConverter.ConvertToLocalHumanReadableTime. Todos esses métodos são discutidos abaixo.
O método ReportQueueAndJobAvailability começa verificando se a fila ou o trabalho de impressão está indisponível neste momento. Se cada um deles estiver indisponível, verifica então para ver se a fila está indisponível. Se não estiver disponível, então o método relata o fato e a hora em que a fila estará disponível novamente. Então verifica o trabalho e, se estiver indisponível, relata a próxima faixa de horário em que pode ser impresso. Finalmente, o método relata o horário mais cedo em que o trabalho pode ser impresso. Isso é o mais tarde dos dois horários seguintes.
O horário em que a fila de impressão estará disponível.
O horário em que a fila de impressão estará disponível.
Ao reportar horários do dia, o método ToShortTimeString também é chamado porque esse método suprime os anos, meses e dias da saída. Você não pode restringir a disponibilidade de uma fila de impressão ou trabalho de impressão a anos, meses ou dias particulares.
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());
}
}
};
As duas sobrecargas do método ReportAvailabilityAtThisTime são idênticas, exceto pelo tipo passado a elas, então apenas a versão PrintQueue é apresentada a seguir. Para o exemplo completo, veja Diagnosticar problemáticos trabalho de Imprimir exemplo.
Observação: |
---|
O fato de que os métodos são idênticos, exceto para o tipo levanta a questão de por que a amostra não cria um método genérico ReportAvailabilityAtThisTime <t>. O motivo é que um tal método teria que ser restrito a uma classe que tem as propriedades StartTimeOfDay e UntilTimeOfDay que o método chama, mas um método genérico só pode ser restrito a uma única classe e a única classe comum a bmaos PrintQueue e PrintSystemJobInfo na árvore de herança é PrintSystemObject, que não tem tais propriedades. |
O método ReportAvailabilityAtThisTime (apresentado no código de exemplo abaixo) começa inicializando uma variável de sentinela Boolean como true. Será redefinido como false se a fila não estiver disponível.
Em seguida, o método verifica se os horários de início de "até" são idênticos. Se forem, a fila sempre estará disponível, e então o método retorna true.
Se a fila não estiver disponível o tempo todo, o método utiliza a propriedade estática UtcNow para obter o horário atual como um objeto DateTime. (Não precisamos do tempo local porque as propriedades StartTimeOfDay e UntilTimeOfDay são elas próprias em horário UTC.)
Entretanto, essas duas propriedades não são objetos DateTime. Elas são Int32s expressando o horário como o número de minutos após a meia-noite-UTC. Então temos que converter nosso objeto DateTime em minutos-após-meia-noite. Quando isso é feito, o método simplesmente verifica para ver se "agora" está entre os horários de início e "até" da fila, define a sentinela como falso se "agora" não estiver entre os dois horários, e retorna a sentinela.
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;
};
O método TimeConverter.ConvertToLocalHumanReadableTime (apresentado no código de exemplo abaixo) não utiliza quaisquer métodos introduzidos com o Microsoft .NET Framework, então a discussão é breve. O método tem uma tarefa de conversão dupla: Ele deve fazer um número inteiro expressar meia minutos depois-noite e convertê-lo em um horário legível e ele deve converter isso para a time local. Realiza isso criando primeiro um objeto DateTime definido como meia-noite UTC e então utiliza o método AddMinutes para acrescentar os minutos que foram passados ao método. Isso retorna um novo DateTime expressando o horário original que foi passado ao método. O método ToLocalTime converte isso então para o horário local.
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;
};
};
Consulte também
Conceitos
Documentos em Windows Presentation Foundation