Como: Descobrir se um trabalho de impressão pode ser impresso a esta hora do dia
As filas de impressão nem sempre estão disponíveis 24 horas por dia. Eles têm propriedades de hora de início e término que podem ser definidas para torná-los indisponíveis em determinados momentos do dia. Este recurso pode ser usado, por exemplo, para reservar uma impressora para uso exclusivo de um determinado departamento após as 17h. Esse departamento teria uma fila de manutenção da impressora diferente da que outros departamentos usam. A fila para os outros departamentos seria definida para ficar indisponível após as 17h, enquanto a fila para o departamento favorecido poderia ser definida para estar disponível em todos os momentos.
Além disso, os próprios trabalhos de impressão podem ser configurados para serem imprimíveis apenas dentro de um período de tempo especificado.
As classes PrintQueue e PrintSystemJobInfo expostas nas APIs do Microsoft .NET Framework fornecem um meio para verificar remotamente se um determinado trabalho de impressão pode imprimir em uma determinada fila no momento atual.
Exemplo
O exemplo abaixo é um exemplo que pode diagnosticar problemas com um trabalho de impressão.
Existem dois passos principais para este tipo de função, como se segue.
Leia as propriedades StartTimeOfDay e UntilTimeOfDay dos PrintQueue para determinar se a hora atual está entre as duas.
Leia as propriedades StartTimeOfDay e UntilTimeOfDay dos PrintSystemJobInfo para determinar se a hora atual está entre eles.
Mas as complicações surgem do fato de que essas propriedades não são objetos DateTime. Em vez disso, são objetos Int32 que expressam a hora do dia como o número de minutos desde a meia-noite. Além disso, não se trata de meia-noite no fuso horário atual, mas sim meia-noite UTC (Tempo Universal Coordenado).
O primeiro exemplo de código apresenta o método estático ReportQueueAndJobAvailability, que recebe um PrintSystemJobInfo e chama métodos auxiliares para determinar se a tarefa pode imprimir no momento atual e, se não, quando poderá imprimir. Observe que um PrintQueue não é passado para o método. Isso ocorre porque o PrintSystemJobInfo inclui uma referência à fila em sua propriedade HostingPrintQueue.
Métodos subordinados incluem o método ReportAvailabilityAtThisTime sobrecarregado, que pode aceitar um PrintQueue ou um PrintSystemJobInfo como parâmetro. Existe também 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 não está disponível no momento. Se qualquer um deles estiver indisponível, verifica então se a fila está indisponível. Se não estiver disponível, o método relata esse fato e a hora em que a fila ficará disponível novamente. Em seguida, verifica o trabalho e, se ele não estiver disponível, informa o próximo período de tempo em que pode imprimir. Finalmente, o método informa o primeiro momento em que o trabalho pode ser impresso. Esta é a última das duas vezes seguintes.
A hora em que a fila de impressão ficará disponível novamente.
A hora em que o trabalho de impressão estará disponível novamente.
Ao relatar horas do dia, o método ToShortTimeString também é chamado porque esse método suprime os anos, meses e dias da saída. Não é possível restringir a disponibilidade de uma fila de impressão ou de um trabalho de impressão a anos, meses ou dias específicos.
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
As duas sobrecargas do método ReportAvailabilityAtThisTime são idênticas, exceto pelo tipo passado para as mesmas, por isso apenas a versão PrintQueue é apresentada abaixo.
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>. A razão é que tal método teria de ser restrito a uma classe que possua 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 ambos PrintQueue e PrintSystemJobInfo na árvore de herança é PrintSystemObject, a qual não possui essas propriedades.
O método false
, caso a fila não esteja disponível.
Em seguida, o método verifica se os horários de início e "até" são idênticos. Se estiverem, a fila estará sempre disponível, portanto, o método retornará true
.
Se a fila não estiver disponível o tempo todo, o método usará a propriedade UtcNow estática para obter a hora atual como um objeto DateTime. (Não precisamos da hora local porque as propriedades StartTimeOfDay e UntilTimeOfDay estão no horário UTC.)
No entanto, essas duas propriedades não são objetos DateTime. Eles são Int32expressando o tempo como o número de minutos após a meia-noite UTC. Por isso, temos de converter o nosso objeto DateTime em minutos-depois-meia-noite. Quando isso é feito, o método simplesmente verifica se "agora" está entre o início e o término do intervalo de tempo da fila, define o sentinela como false se "agora" não estiver entre estes dois momentos e retorna o sentinela.
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
O método
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
Ver também
- DateTime
- PrintSystemJobInfo
- PrintQueue
- documentos no WPF
- Visão geral da impressão
.NET Desktop feedback