Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Las colas de impresión no siempre están disponibles durante las 24 horas del día. Tienen propiedades de hora inicial y final que se pueden establecer para que no estén disponibles en determinados momentos del día. Por ejemplo, esta característica se puede utilizar para reservar una impresora para el uso exclusivo de un departamento determinado a partir de las 5.00 p.m. Ese departamento tendría una cola diferente para dar servicio a la impresora que los demás departamentos. La cola de los demás departamentos se establecería como no disponible después de las 5.00 p.m., mientras que la cola del departamento favorecido podría establecerse de modo que estuviera disponible en todo momento.
Además, se pueden establecer los propios trabajos de impresión para que únicamente puedan imprimirse en un intervalo de tiempo especificado.
Las clases PrintQueue y PrintSystemJobInfo expuestas en las APIs de Microsoft .NET Framework ofrecen un medio de comprobar de manera remota si un trabajo de impresión dado se puede imprimir en una cola determinada en cada momento.
Ejemplo
El ejemplo siguiente es capaz de diagnosticar los problemas con un trabajo de impresión.
Existen dos pasos principales para este tipo de función, que son los siguientes.
Lea las propiedades StartTimeOfDay y UntilTimeOfDay del objeto PrintQueue a fin de determinar si la hora actual se encuentra comprendida entre ellas.
Lea las propiedades StartTimeOfDay y UntilTimeOfDay del objeto PrintSystemJobInfo a fin de determinar si la hora actual se encuentra comprendida entre ellas.
No obstante, las complicaciones surgen del hecho de que estas propiedades no son objetos DateTime. En cambio, se trata de objetos Int32 que expresan la hora del día como el número de minutos transcurridos desde la medianoche. Es más, no se trata de la medianoche en la zona horaria actual, sino de la medianoche según la hora universal coordinada (UTC).
En el primer ejemplo de código se presenta el método estático ReportQueueAndJobAvailability, al que se pasa un objeto PrintSystemJobInfo y que llama a métodos auxiliares para determinar si el trabajo se puede imprimir en este momento y, en caso contrario, cuándo se puede hacer. Observe que PrintQueue no se pasa al método. Esto se debe a que PrintSystemJobInfo incluye una referencia a la cola en su propiedad HostingPrintQueue.
Los métodos subordinados incluyen el método sobrecargado ReportAvailabilityAtThisTime, que puede aceptar PrintQueue o PrintSystemJobInfo como parámetro. También está el método TimeConverter.ConvertToLocalHumanReadableTime. Todos estos métodos se describen más adelante.
El método ReportQueueAndJobAvailability comienza comprobando si la cola o el trabajo de impresión no están disponibles en este momento. Si cualquiera de ellos no está disponible, comprueba si la cola no está disponible. Si no está disponible, el método informa de ello y de la hora a la que la cola estará disponible de nuevo. A continuación, comprueba el trabajo y, si no está disponible, informa del próximo intervalo de tiempo en que se podrá imprimir. Por último, el método informa del momento más próximo en que el trabajo se podrá imprimir. Será el posterior de los dos siguientes.
La próxima hora a la que la cola de impresión esté disponible.
La próxima hora a la que el trabajo de impresión esté disponible.
Al informar sobre las horas del día, se llama al método ToShortTimeString también, porque este método suprime los años, meses y días del resultado. No se puede restringir la disponibilidad de una cola de impresión o de un trabajo de impresión a determinados años, meses o días concretos.
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 'end ReportQueueAndJobAvailability
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());
}
}
};
Las dos sobrecargas del método ReportAvailabilityAtThisTime son idénticas salvo por el tipo que se les pasa, por lo que únicamente se presenta la versión PrintQueue a continuación.
![]() |
---|
El hecho de que los métodos sean idénticos salvo por el tipo, suscita la pregunta de por qué en el ejemplo no se crea un método genérico ReportAvailabilityAtThisTime<T>.La razón es que este tipo de método tendría que estar restringido a una clase que tuviera las propiedades StartTimeOfDay y UntilTimeOfDay a las que el método llama, pero un método genérico únicamente se puede restringir a una sola clase y la única clase común a PrintQueue y PrintSystemJobInfo en el árbol de herencia es PrintSystemObject, que carece de estas propiedades. |
El método ReportAvailabilityAtThisTime (que se presenta en el ejemplo de código siguiente) comienza inicializando una variable centinela Boolean en true. Se restablecerá en false si la cola no está disponible.
Luego, el método comprueba si los momentos de inicio y "hasta" son idénticos. Si lo son, la cola siempre está disponible, por lo que el método devuelve true.
Si la cola no está disponible en todo momento, el método utiliza la propiedad UtcNow estática para obtener la hora actual como un objeto DateTime. (No se necesita la hora local porque las propiedades StartTimeOfDay y UntilTimeOfDay se expresan en hora UTC.)
Sin embargo, estas dos propiedades no son objetos DateTime. Son valores Int32 que expresan la hora como el número de minutos transcurridos desde la medianoche según la hora UTC. Así que es preciso convertir el objeto DateTime en minutos desde la medianoche. Una vez convertidos, el método se limita a comprobar si "ahora" se encuentra entre las horas de inicio y "hasta" de la cola, establece el centinela en false si no es así, y devuelve el centinela.
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
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;
};
El método TimeConverter.ConvertToLocalHumanReadableTime (presentado en el ejemplo de código siguiente) no utiliza ningún método introducido con Microsoft .NET Framework, de modo que su explicación es breve. El método tiene una tarea de conversión doble: debe tomar un entero que expresa minutos transcurridos desde la medianoche y convertirlo en una hora legible, y luego convertir este valor en la hora local. Para ello, en primer lugar crea un objeto DateTime establecido en la medianoche según la hora UTC y, a continuación, utiliza el método AddMinutes para sumar los minutos que se pasaron al método. Esto devuelve un nuevo valor DateTime que expresa la hora original que se pasó al método. A continuación, el método ToLocalTime convierte este valor en la hora local.
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 'end TimeConverter class
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;
};
};