Como descobrir se um trabalho de impressão pode ser impresso nesta hora do dia
As filas de impressão nem sempre estão disponíveis por 24 horas por dia. Eles têm propriedades de hora de início e término que podem ser definidas para torná-las indisponíveis em determinadas horas do dia. Esse recurso pode ser usado, por exemplo, para reservar uma impressora para o uso exclusivo de um determinado departamento após as 17h. Esse departamento teria uma fila diferente para atender a impressora do que outros departamentos usam. A fila para os outros departamentos estaria definida como indisponível após as 17h, enquanto a fila para o departamento favorecido poderia ser definida para estar disponível o tempo todo.
Além disso, os próprios trabalhos de impressão podem ser definidos para serem imprimíveis somente 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 a seguir é um exemplo que pode diagnosticar problemas com um trabalho de impressão.
Há duas etapas principais para esse tipo de função da seguinte maneira.
Leia as propriedades StartTimeOfDay e UntilTimeOfDay do PrintQueue para determinar se a hora atual está entre elas.
Leia as propriedades StartTimeOfDay e UntilTimeOfDay do PrintSystemJobInfo para determinar se a hora atual está entre elas.
Mas as complicações surgem do fato de que essas propriedades não são DateTime objetos. 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, isso não é meia-noite no fuso horário atual, mas meia-noite UTC (Tempo Universal Coordenado).
O primeiro exemplo de código apresenta o método estático ReportQueueAndJobAvailability, que é passado um PrintSystemJobInfo e chama métodos auxiliares para determinar se o trabalho pode imprimir no momento e, caso não possa, 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.
Os métodos subordinados incluem o método ReportAvailabilityAtThisTime sobrecarregado, que pode usar um PrintQueue ou um PrintSystemJobInfo como parâmetro. Há, além disso, 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 neste momento. Se um deles estiver indisponível, ele verificará se a fila está indisponível. Se não estiver disponível, o método relatará esse fato e a hora em que a fila ficará disponível novamente. Em seguida, verifica o trabalho e, se estiver indisponível, relatará o próximo período em que poderá imprimir. Por fim, o método indica o momento mais cedo em que o trabalho pode ser impresso. Esta é a mais recente das duas vezes a seguir.
A hora em que a fila de impressão estará disponível novamente.
A hora em que o trabalho de impressão estará disponível a seguir.
Ao relatar horas do dia, o método ToShortTimeString também é chamado assim porque seu objetivo é suprimir os anos, meses e dias do resultado. Você não pode 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 elas, portanto, somente a versão PrintQueue é apresentada abaixo.
Nota
O fato de que os métodos são idênticos, exceto pelo tipo, levanta a questão de por que o exemplo não cria um método genérico ReportAvailabilityAtThisTime<T>. O motivo é que esse método teria que ser restrito a uma classe que tenha 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 PrintQueue e PrintSystemJobInfo na árvore de herança é PrintSystemObject que não tem essas propriedades.
O método ReportAvailabilityAtThisTime (apresentado no exemplo de código abaixo) começa inicializando uma variável sentinela Boolean para true
. Ele será redefinido para false
, se a fila não estiver 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 de hora local porque as propriedades StartTimeOfDay e UntilTimeOfDay estão em horário UTC.)
No entanto, essas duas propriedades não são objetos DateTime. Eles estão Int32expressando o tempo como o número de minutos após a meia-noite UTC. Portanto, temos que converter nosso objeto DateTime em minutos depois da meia-noite. Quando isso é feito, o método simplesmente verifica se "agora" está entre os horários de início e "até" da fila, define a sentinela como false se "agora" não está entre as duas vezes e retorna a 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 TimeConverter.ConvertToLocalHumanReadableTime (apresentado no exemplo de código abaixo) não usa nenhum método introduzido com o Microsoft .NET Framework, portanto, a discussão é breve. O método tem uma tarefa de conversão dupla: ele deve levar um inteiro expressando minutos após a meia-noite e convertê-lo em um tempo legível por humanos e deve convertê-lo na hora local. Ele faz isso primeiro criando um objeto DateTime que é definido como meia-noite UTC e, em seguida, usa o método AddMinutes para adicionar os minutos que foram passados para o método. Retorna um novo DateTime que expressa o tempo original que foi passado para o método. O método ToLocalTime converte-o em hora local.
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
Consulte também
- DateTime
- PrintSystemJobInfo
- PrintQueue
- documentos no WPF
- Visão geral da impressão
.NET Desktop feedback