Compartir a través de


Cómo: Detectar si se puede imprimir un trabajo de impresión en este momento del día

Las colas de impresión no siempre están disponibles las 24 horas del día. Tienen propiedades de hora de inicio y finalización que se pueden establecer para que no estén disponibles en determinadas horas del día. Esta característica se puede usar, por ejemplo, para reservar una impresora para el uso exclusivo de un determinado departamento después de las 5 P.M.. Ese departamento tendría una cola de servicio diferente para la impresora que la que usan otros departamentos. La cola de los demás departamentos se establecería como no disponible después de las 5 p.m., mientras que la cola para el departamento preferido podría estar disponible en todo momento.

Además, los propios trabajos de impresión se pueden establecer para que solo se puedan imprimir dentro de un intervalo de tiempo especificado.

Las clases PrintQueue y PrintSystemJobInfo expuestas en las API de Microsoft .NET Framework proporcionan un medio para comprobar de forma remota si un trabajo de impresión determinado puede imprimirse en una cola dada en el momento actual.

Ejemplo

El ejemplo siguiente es un ejemplo que puede diagnosticar problemas con un trabajo de impresión.

Hay dos pasos principales para este tipo de función como se indica a continuación.

  1. Lea las StartTimeOfDay propiedades y UntilTimeOfDay de PrintQueue para determinar si la hora actual está entre ellas.

  2. Lea las StartTimeOfDay propiedades y UntilTimeOfDay de PrintSystemJobInfo para determinar si la hora actual está entre ellas.

Pero las complicaciones surgen del hecho de que estas propiedades no DateTime son objetos. En su lugar, son Int32 objetos que expresan la hora del día como el número de minutos desde la medianoche. Además, esto no es medianoche en la zona horaria actual, pero medianoche UTC (hora universal coordinada).

El primer ejemplo de código presenta el método estático ReportQueueAndJobAvailability, al cual se le pasa un parámetro PrintSystemJobInfo y llama a métodos auxiliares para determinar si el trabajo se puede imprimir en el momento actual y, si no es así, cuándo se puede imprimir. Tenga en cuenta que no se pasa un PrintQueue al método. Esto se debe a que PrintSystemJobInfo incluye una referencia a la cola en su HostingPrintQueue propiedad .

Los métodos auxiliares incluyen el método ReportAvailabilityAtThisTime sobrecargado, que puede tomar como parámetro uno de los dos: PrintQueue o PrintSystemJobInfo. También hay un TimeConverter.ConvertToLocalHumanReadableTime. A continuación se describen todos estos métodos.

El método ReportQueueAndJobAvailability comienza comprobando si la cola o el trabajo de impresión no están disponibles en este momento. Si alguno de ellos no está disponible, comprueba si la cola no está disponible. Si no está disponible, el método notifica este hecho y la hora en que la cola volverá a estar disponible. A continuación, comprueba el trabajo y, si no está disponible, notifica el próximo intervalo de tiempo en que se pueda imprimir. Por último, el método informa el momento más temprano en que el trabajo se puede imprimir. Este es el más tardío de los siguientes dos momentos.

  • La hora a la que la cola de impresión estará disponible nuevamente.

  • Hora en la que el trabajo de impresión estará disponible la próxima vez.

Cuando se informan horas del día, también se invoca el método ToShortTimeString 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 un trabajo de impresión a determinados años, meses o días.

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

Las dos sobrecargas del método ReportAvailabilityAtThisTime son idénticas excepto por el tipo que se les pasa, por lo que solo se presenta la PrintQueue versión a continuación.

Nota:

El hecho de que los métodos sean idénticos excepto para el tipo genera la pregunta de por qué el ejemplo no crea un método genérico ReportAvailabilityAtThisTime<T>. La razón es que este método tendría que estar restringido a una clase que tenga las propiedades StartTimeOfDay y UntilTimeOfDay a las que llama el método, pero un método genérico solo puede estar restringido a una sola clase y la única clase común a y PrintQueuePrintSystemJobInfo en el árbol de herencia es PrintSystemObject que no tiene estas propiedades.

El método ReportAvailabilityAtThisTime (presentado en el ejemplo de código siguiente) comienza inicializando una Boolean variable sentinel en true. Se restablecerá a false, si la cola no está disponible.

A continuación, el método comprueba si las horas de inicio y "hasta" son idénticas. Si lo son, la cola está siempre disponible, por lo tanto, el método devuelve true.

Si la cola no está disponible todo el tiempo, el método usa la propiedad estática UtcNow para obtener la hora actual como un DateTime objeto . (No necesitamos hora local porque las StartTimeOfDay propiedades y UntilTimeOfDay se encuentran en hora UTC).

Sin embargo, estas dos propiedades no son objetos DateTime. Expresan Int32la hora como el número de minutos después de la medianoche UTC. Por lo tanto, tenemos que convertir nuestro DateTime objeto a minutos después de la medianoche. Cuando haya terminado, el método simplemente comprueba si "now" está entre las horas de inicio y "hasta" de la cola, establece el sentinel en false si "now" no está entre las dos veces y devuelve el sentinel.

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

El método TimeConverter.ConvertToLocalHumanReadableTime (presentado en el ejemplo de código siguiente) no usa ningún método introducido con Microsoft .NET Framework, por lo que la discusión es breve. El método tiene una tarea de conversión doble: debe tomar un entero que expresa minutos pasados de la medianoche y convertirlo en un tiempo legible por humanos y luego convertirlo a la hora local. Para ello, primero crea un DateTime objeto que se establece en medianoche UTC y, a continuación, usa el AddMinutes método para agregar los minutos que se pasaron al método . Esto devuelve una nueva DateTime que expresa la hora original que se pasó al método. A continuación, el ToLocalTime método lo convierte en 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 también