Condividi tramite


Procedura: individuare se è possibile eseguire o meno un processo di stampa all'orario indicato

Le code di stampa non sempre sono disponibili 24 ore al giorno. È possibile impostare le proprietà relative all'ora di inizio e di fine per renderle non disponibili in determinati orari del giorno. Questa funzione può essere utilizzata, ad esempio, per riservare l'uso esclusivo di una stampante per un determinato reparto dopo le 17.00. In tal modo, il reparto avrebbe una coda di stampa diversa rispetto a quella degli altri reparti. La coda per gli altri reparti sarebbe impostata come non disponibile dopo le 17.00 mentre quella per il reparto selezionato sarebbe impostata come disponibile per tutto il tempo.

Inoltre, gli stessi processi di stampa possono essere impostati come stampabili solo entro un intervallo di tempo specificato.

Le classi PrintQueue e PrintSystemJobInfo esposte nelle APIs di Microsoft .NET Framework consentono di controllare in remoto se un determinato processo di stampa può essere eseguito su una determinata coda all'ora corrente. 

Esempio

L'esempio riportato di seguito consente di diagnosticare i problemi di un processo di stampa.

Di seguito vengono riportati i due passaggi principali di questo tipo di funzione.

  1. Leggere le proprietà StartTimeOfDay e UntilTimeOfDay di PrintQueue per determinare se comprendono l'ora corrente.

  2. Leggere le proprietà StartTimeOfDay e UntilTimeOfDay di PrintSystemJobInfo per determinare se comprendono l'ora corrente.

Tuttavia, i problemi scaturiscono dal fatto che queste proprietà non sono oggetti DateTime ma oggetti Int32 che esprimono l'orario come numero di minuti a partire dalla mezzanotte. Inoltre, non si tratta della mezzanotte del fuso orario corrente ma della mezzanotte ora UTC (Coordinated Universal Time).

Il primo esempio di codice presenta il metodo statico ReportQueueAndJobAvailability a cui viene passato PrintSystemJobInfo e che chiama i metodi di supporto per stabilire se il processo può essere stampato all'ora corrente o, in caso contrario, quando può essere stampato. Si noti che PrintQueue non viene passato al metodo perché PrintSystemJobInfo include un riferimento alla coda nella relativa proprietà HostingPrintQueue.

I metodi subordinati includono il metodo di overload ReportAvailabilityAtThisTime che può utilizzare PrintQueue o PrintSystemJobInfo come parametro. È disponibile anche TimeConverter.ConvertToLocalHumanReadableTime. Tutti questi metodi vengono esaminati di seguito.

Il metodo ReportQueueAndJobAvailability verifica innanzitutto se la coda o il processo di stampa sono disponibili in quel preciso momento. Se uno dei due non è disponibile, viene verificata la disponibilità della coda. Se la coda non è disponibile, il metodo segnala questa situazione insieme all'ora in cui sarà nuovamente disponibile la coda. Quindi, il metodo verifica il processo di stampa e, nel caso in cui non fosse disponibile, segnala il successivo intervallo di tempo in cui può essere stampato. Infine, segnala il primo orario disponibile in cui il processo può essere stampato. Si tratta della seconda condizione riportata di seguito.

  • Il primo orario in cui è disponibile la coda di stampa.

  • Il primo orario in cui è disponibile il processo di stampa.

Per il report degli orari, viene chiamato anche il metodo ToShortTimeString che elimina gli anni, i mesi e i giorni dall'output. Non è possibile limitare la disponibilità di una coda o di un processo di stampa ad anni, mesi o giorni specifici.

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

   }
};

I due overload del metodo ReportAvailabilityAtThisTime sono identici ad eccezione del tipo ricevuto. Di seguito, viene quindi presentata solo la versione PrintQueue.

NotaNota

Il fatto che i metodi siano identici ad eccezione del tipo, pone la questione del perché l'esempio non crea un metodo ReportAvailabilityAtThisTime<T> generico.Il motivo è che questo metodo dovrebbe essere limitato a una classe con le proprietà StartTimeOfDay e UntilTimeOfDay chiamate dal metodo, ma un metodo generico può essere limitato a una sola classe e l'unica classe comune a PrintQueue e a PrintSystemJobInfo nella struttura ad albero di ereditarietà è PrintSystemObject che non dispone di tali proprietà.

Il metodo ReportAvailabilityAtThisTime, illustrato nell'esempio di codice di seguito, avvia l'inizializzazione di una variabile sentinel Boolean su true. Se la coda non è disponibile, verrà reimpostata su false.

Quindi, il metodo verifica se l'ora di inizio e l'ora di fine coincidono. In tal caso, la coda è sempre disponibile e il metodo restituisce true.

Se la coda non è disponibile per tutto il tempo, il metodo utilizza la proprietà statica UtcNow per ottenere l'ora corrente come oggetto DateTime. L'ora locale non è necessaria perché le proprietà StartTimeOfDay e UntilTimeOfDay sono in formato UTC.

Tuttavia, queste due proprietà non sono oggetti DateTime ma oggetti Int32 che esprimono l'orario come numero di minuti dopo la mezzanotte ora UTC. È quindi necessario convertire l'oggetto DateTime in minuti dopo la mezzanotte. Quindi, il metodo verifica se "now" si trova tra l'ora di inizio e l'ora di fine della coda, imposta sentinel su false se "now" non è compreso tra i due orari e quindi restituisce sentinel.

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

Il metodo TimeConverter.ConvertToLocalHumanReadableTime, illustrato nell'esempio di codice di seguito, non utilizza alcun metodo introdotto con Microsoft .NET Framework. Il metodo deve eseguire una doppia attività di conversione: deve convertire un numero intero che esprime i minuti dopo la mezzanotte in un orario leggibile e quindi convertire quest'ultimo nell'ora locale. A tale scopo, viene creato prima un oggetto DateTime, impostato sulla mezzanotte ora UTC, quindi viene utilizzato il metodo AddMinutes per aggiungere i minuti passati al metodo. Viene restituito un nuovo oggetto DateTime che esprime l'ora originale passata al metodo. Quindi, il metodo ToLocalTime la converte nell'ora 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;
   };
};

Vedere anche

Riferimenti

DateTime

PrintSystemJobInfo

PrintQueue

Concetti

Documenti in WPF

Cenni preliminari sulla stampa