Freigeben über


Gewusst wie: Ermitteln, ob ein Druckauftrag zu dieser Tageszeit gedruckt werden kann

Aktualisiert: November 2007

Druckwarteschlangen sind nicht immer für 24 Stunden pro Tag verfügbar. Sie verfügen über Eigenschaften zur Start- und Endzeit, anhand derer bestimmte Tageszeiten festgelegt werden können, zu denen die Druckwarteschlangen nicht verfügbar sind. Anhand dieses Features können Sie z. B. einen Drucker zur exklusiven Verwendung durch eine Abteilung nach 17:00 Uhr reservieren. Diese Abteilung würde zum Drucken eine andere Druckwarteschlange als andere Abteilungen verwenden. Die Warteschlange der anderen Abteilungen wird in diesem Fall so eingerichtet, dass sie nach 17:00 nicht mehr verfügbar ist, wohingegen die Warteschlangeneinrichtung der bevorzugten Abteilung eine ständige Verfügbarkeit vorsieht.

Darüber hinaus können auch die Druckaufträge selbst so eingerichtet werden, dass sie nur während einer angegebenen Zeitspanne gedruckt werden können.

Mithilfe der in den APIs von Microsoft .NET Framework enthaltenen Klassen PrintQueue und PrintSystemJobInfo kann remote geprüft werden, ob ein bestimmter Druckauftrag in einer gegebenen Warteschlange zum aktuellen Zeitpunkt gedruckt werden kann.

Beispiel

Das folgende Beispiel stammt aus einer Beispielanwendung, mit der Probleme bei Druckaufträgen diagnostiziert werden können. Das vollständige Beispiel finden Sie unter Beispiel für die Diagnose von Problemen mit Druckaufträgen.

Die zwei wichtigsten Schritte für diese Art von Funktion sind:

  1. Bestimmen Sie anhand der Eigenschaften StartTimeOfDay und UntilTimeOfDay der PrintQueue, ob die aktuelle Zeit in diesen Zeitraum fällt.

  2. Bestimmen Sie anhand der Eigenschaften StartTimeOfDay und UntilTimeOfDay der PrintSystemJobInfo, ob die aktuelle Zeit in diesen Zeitraum fällt.

Es können sich jedoch Komplikationen aufgrund der Tatsache ergeben, dass diese Eigenschaften keine DateTime-Objekte sind. Stattdessen handelt es sich um Int32-Objekte, die die Tageszeit in Minuten seit Mitternacht angeben. Darüber hinaus ist dies nicht die mitternächtliche Zeit der aktuellen Zeitzone, sondern Mitternacht nach UTC-Zeit (koordinierte Weltzeit).

Das erste Codebeispiel veranschaulicht die statische Methode ReportQueueAndJobAvailability, der eine PrintSystemJobInfo übergeben wird und die Hilfsmethoden aufruft, um zu bestimmen, ob der Auftrag zur aktuellen Zeit gedruckt werden kann und, wenn nicht, zu welchem Zeitpunkt er gedruckt werden kann. Beachten Sie, dass keine PrintQueue an die Methode übergeben wird. Das liegt daran, dass PrintSystemJobInfo einen Verweis auf die Warteschlange in seiner HostingPrintQueue-Eigenschaft enthält.

Die untergeordneten Methoden enthalten die überladene ReportAvailabilityAtThisTime-Methode, die entweder PrintQueue oder PrintSystemJobInfo als Parameter übernehmen kann. Außerdem ist eine TimeConverter.ConvertToLocalHumanReadableTime vorhanden. Alle diese Methoden werden nachfolgend erläutert.

Die ReportQueueAndJobAvailability-Methode prüft zunächst, ob zu diesem Zeitpunkt entweder die Warteschlange oder der Druckauftrag nicht zur Verfügung steht. Wenn einer von ihnen nicht verfügbar ist, überprüft sie, ob die Warteschlange nicht verfügbar ist. Wenn dem so ist, meldet die Methode diese Tatsache sowie den Zeitpunkt, ab dem die Warteschlange wieder zur Verfügung steht. Danach prüft sie den Druckauftrag und meldet, sofern dieser nicht zur Verfügung steht, die nächste Zeitspanne, zu der der Auftrag gedruckt werden kann. Schließlich meldet die Methode den frühesten Zeitpunkt, zu dem der Auftrag gedruckt werden kann. Dabei handelt es sich um den späteren Zeitpunkt der folgenden zwei Zeitangaben.

  • Der nächste Zeitpunkt, zu dem die Druckwarteschlange verfügbar ist.

  • Der nächste Zeitpunkt, zu dem der Druckauftrag verfügbar ist.

Beim Melden der Tageszeiten wird außerdem die ToShortTimeString-Methode aufgerufen, da diese Methode die Angaben zu Jahr, Monat und Tag in der Ausgabe unterdrückt. Sie können die Verfügbarkeit einer Druckwarteschlange oder eines Druckauftrags nicht auf bestimmte Jahre, Monate oder Tage einschränken.

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

   }
};

Die beiden Überladungen der ReportAvailabilityAtThisTime-Methode sind mit Ausnahme des an sie übergebenen Typs identisch, sodass in der Folge nur die PrintQueue-Version dargestellt wird. (Das vollständige Beispiel finden Sie unter Beispiel für die Diagnose von Problemen mit Druckaufträgen.)

Tipp

Die Tatsache, dass die Methoden mit Ausnahme des Typs identisch sind, wirft die Frage auf, warum das Beispiel keine generische ReportAvailabilityAtThisTime<T>-Methode erstellt. Der Grund dafür ist, dass eine solche Methode auf eine Klasse beschränkt werden müsste, die die von der Methode aufgerufenen Eigenschaften StartTimeOfDay und UntilTimeOfDay enthält. Eine generische Methode kann jedoch nur auf eine einzelne Klasse beschränkt werden, und die einzige Klasse, die in der Vererbungsstruktur sowohl der PrintQueue als auch der PrintSystemJobInfo gemeinsam ist, ist die PrintSystemObject-Klasse, die keine dieser Eigenschaften enthält.

Die ReportAvailabilityAtThisTime-Methode (im folgenden Codebeispiel dargestellt) initialisiert zunächst eine Boolean-Sentinelvariable auf true. Sie wird auf false zurückgesetzt, wenn die Warteschlange nicht verfügbar ist.

Danach überprüft die Methode, ob Start- und Endzeitpunkt identisch sind. Wenn diese identisch sind, ist die Warteschlange immer verfügbar, und die Methode gibt true zurück.

Steht die Warteschlange nicht jederzeit zur Verfügung, verwendet die Methode die statische UtcNow-Eigenschaft, um die aktuelle Zeit als DateTime-Objekt abzurufen. (Die Ortszeit wird nicht benötigt, da die StartTimeOfDay-Eigenschaft und die UntilTimeOfDay-Eigenschaft selbst in UTC-Zeit geführt werden.)

Diese beiden Eigenschaften sind jedoch keine DateTime-Objekte. Sie sind Int32-Objekte, die die Zeit in Minuten nach Mitternacht UTC ausdrücken. Deshalb muss das DateTime-Objekt in Minuten nach Mitternacht konvertiert werden. Danach prüft die Methode lediglich, ob der aktuelle Zeitpunkt zwischen dem Startzeitpunkt und dem Endzeitpunkt der Warteschlange liegt, setzt den Sentinelwert auf "False", wenn der aktuelle Zeitpunkt nicht zwischen den beiden Zeitangaben liegt, und gibt den Sentinelwert zurück.

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

Die TimeConverter.ConvertToLocalHumanReadableTime-Methode (im folgenden Codebeispiel dargestellt) verwendet keine der mit Microsoft .NET Framework eingeführten Methoden, sodass sie hier lediglich in aller Kürze erläutert wird. Die Methode hat eine doppelte Konvertierungsaufgabe: Sie muss eine ganze Zahl, die die Minuten nach Mitternacht ausdrückt, in eine für den Benutzer lesbare Zeit und in eine Ortszeit konvertieren. Sie erreicht dies, indem sie zuerst ein auf Mitternacht UTC eingestelltes DateTime-Objekt erstellt und danach die AddMinutes-Methode verwendet, um die an die Methode übergebenen Minuten hinzuzufügen. Dies gibt einen neuen DateTime-Wert zurück, der die ursprüngliche Zeit ausdrückt, die an die Methode übergeben wurde. Die ToLocalTime-Methode konvertiert diesen Wert dann in die Ortszeit.

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

Siehe auch

Konzepte

Dokumente in Windows Presentation Foundation

Übersicht über das Drucken

Referenz

DateTime

PrintSystemJobInfo

PrintQueue

Weitere Ressourcen

Beispiele für Drucken