Comment : déterminer si un travail d'impression peut être imprimé à cette heure de la journée

Les files d'attente à l'impression ne sont pas toujours disponibles 24 heures sur 24. Elles ont des propriétés d'heures de début et de fin qui peuvent être définies pour les rendre non disponibles à certaines heures de la journée. Cette fonctionnalité peut être utilisée, par exemple, pour réserver une imprimante en vue de l'utilisation exclusive d'un département après 17 heures. Ce département aurait pour les services de l'imprimante une file d'attente différente de celle des autres départements. La file d'attente pour les autres départements serait définie comme étant non disponible après 17 heures, alors que pour le département privilégié la file d'attente serait définie pour être disponible tout le temps.

De plus, les travaux d'impression eux-mêmes seraient définis pour être imprimables uniquement pendant un intervalle de temps spécifié.

Les classes PrintQueue et PrintSystemJobInfo exposées dans les APIs de Microsoft .NET Framework offrent le moyen de vérifier à distance si un travail d'impression donné peut être imprimé sur une file d'attente spécifique à l'heure actuelle. 

Exemple

L'exemple suivant est un exemple qui peut diagnostiquer des problèmes concernant un travail d'impression.

Il existe deux étapes majeures pour ce genre de fonction, comme suit.

  1. Lisez les propriétés StartTimeOfDay et UntilTimeOfDay de la PrintQueue pour déterminer si l'heure actuelle se situe entre les deux.

  2. Lisez les propriétés StartTimeOfDay et UntilTimeOfDay de la PrintSystemJobInfo pour déterminer si l'heure actuelle se situe entre les deux.

Mais les complications naissent du fait que ces propriétés ne sont pas des objets DateTime. Ce sont plutôt des objets Int32 qui expriment l'heure du jour en tant que nombre de minutes depuis minuit. De plus, il ne s'agit pas de minuit dans le fuseau actuel, mais minuit en temps UTC (Coordinated Universal Time).

Le premier exemple de code présente la méthode statique ReportQueueAndJobAvailability, qui reçoit une PrintSystemJobInfo et appelle les méthodes d'assistance afin de déterminer si le travail peut être imprimé à l'heure actuelle et, sinon, à quelle heure il peut être imprimé. Notez qu'une PrintQueue n'est pas passée à la méthode. Cela tient au fait que PrintSystemJobInfo inclut une référence vers la file d'attente dans sa propriété HostingPrintQueue.

Les méthodes subordonnées incluent la méthode ReportAvailabilityAtThisTime surchargée qui peut prendre PrintQueue ou PrintSystemJobInfo en tant que paramètre. Il y a aussi une TimeConverter.ConvertToLocalHumanReadableTime. Toutes ces méthodes sont passées en revue ci-dessous.

La méthode ReportQueueAndJobAvailability commence par vérifier si la file d'attente ou le travail d'impression n'est pas disponible à cette heure. Si l'un des deux n'est pas disponible, elle vérifie alors si la file d'attente n'est pas disponible. Si elle n'est pas disponible, alors la méthode signale ce fait et l'heure à laquelle la file d'attente redeviendra disponible. Elle vérifie ensuite le travail et si celui-ci n'est pas disponible, elle signale le prochain intervalle pendant lequel elle pourra imprimer. Enfin, la méthode signale la première heure à laquelle le travail pourra être imprimé. Il s'agit de l'heure la plus tardive des deux suivantes.

  • L'heure à laquelle la file d'attente à l'impression sera disponible la prochaine fois.

  • L'heure à laquelle le travail d'impression sera disponible la prochaine fois.

Lors de l'indication des heures de la journée, la méthode ToShortTimeString est également appelée car la méthode supprime les heures, les mois et les jours de la sortie. Vous ne pouvez pas restreindre la disponibilité de la file d'attente ou d'un travail d'impression en fonction d'années, de mois ou de jours particuliers.

        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());
      }

   }
};

Les deux surcharges de la méthode ReportAvailabilityAtThisTime sont identiques sauf pour le type qui leur est passé, ce qui fait que seule la version PrintQueue est présentée ci-dessous.

RemarqueRemarque

Le fait que les méthodes soient identiques sauf pour le type soulève la question de savoir pourquoi l'exemple ne crée pas une méthode générique ReportAvailabilityAtThisTime<T>.La raison est qu'il aurait fallu restreindre une telle méthode à une classe qui a les propriétés StartTimeOfDay et UntilTimeOfDay que la méthode appelle, mais une méthode générique peut seulement être restreinte à une seule classe et la seule classe commune aux deux PrintQueue et PrintSystemJobInfo est l'arborescence d'héritage PrintSystemObject qui ne possède pas de telles propriétés.

La méthode ReportAvailabilityAtThisTime (présentée dans l'exemple de code ci-dessous) commence par initialiser une variable sentinelle Boolean à true. Elle sera réinitialisée à false, si la file d'attente n'est pas disponible.

Ensuite, la méthode vérifie si les heures de début et « jusqu'à » sont identiques. Si c'est le cas, la file d'attente est toujours disponible, alors la méthode retourne true.

Si la file d'attente est non disponible tout le temps, la méthode utilise la propriété UtcNow statique pour obtenir l'heure actuelle en tant qu'objet DateTime. (Nous n'avons pas besoin de l'heure locale car les propriétés StartTimeOfDay et UntilTimeOfDay sont elles-mêmes en heure UTC.)

Cependant, ces deux propriétés ne sont pas des objets DateTime. Il s'agit de Int32s qui expriment l'heure en tant que nombre de minutes après UTC et minuit. Nous devons donc convertir notre objet DateTime en minutes après minuit. Une fois cela fait, la méthode vérifie simplement si « maintenant » se situe entre les heures de début et « jusqu'à » de la file d'attente, affecte à la sentinelle la valeur False si « maintenant » ne se situe pas entre les deux heures, et retourne la sentinelle.

        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;
};

La méthode TimeConverter.ConvertToLocalHumanReadableTime (présentée dans l'exemple de code ci-dessous) n'utilise aucune méthode introduite avec Microsoft .NET Framework, ce qui fait que la description est brève. La méthode a une double tâche de conversion : elle doit prendre un entier exprimant des minutes après minuit et le convertir en heure explicite, puis convertir cette valeur en heure locale. Pour ce faire, elle crée d'abord un objet DateTime qui a la valeur UTC minuit, puis utilise la méthode AddMinutes pour ajouter les minutes passées à la méthode. Cela retourne une nouvelle DateTime exprimant l'heure d'origine passée à la méthode. La méthode ToLocalTime convertit ensuite cette valeur en heure locale.

    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;
   };
};

Voir aussi

Référence

DateTime

PrintSystemJobInfo

PrintQueue

Concepts

Documents dans WPF

Vue d'ensemble de l'impression