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

Le code di stampa non sono sempre disponibili per 24 ore al giorno. Hanno proprietà di ora di inizio e di fine che possono essere impostate per renderle non disponibili in determinati orari del giorno. Questa funzionalità può essere utilizzata, ad esempio, per riservare una stampante per l'uso esclusivo di un determinato reparto dopo le 17.00. Tale reparto avrebbe una manutenzione della coda diversa da quella utilizzata da altri reparti. La coda per gli altri reparti sarebbe impostata su non disponibile dopo le 17.00, mentre la coda per il reparto preferito potrebbe essere impostata per essere sempre disponibile.

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

Le PrintQueue classi e PrintSystemJobInfo esposte nelle API di Microsoft .NET Framework forniscono un mezzo per controllare in remoto se un determinato processo di stampa può essere stampato in una determinata coda al momento corrente.

Esempio

L'esempio seguente è un esempio in grado di diagnosticare i problemi relativi a un processo di stampa.

Esistono due passaggi principali per questo tipo di funzione come indicato di seguito.

  1. Leggere le StartTimeOfDay proprietà e UntilTimeOfDay di PrintQueue per determinare se l'ora corrente è compresa tra di esse.

  2. Leggere le StartTimeOfDay proprietà e UntilTimeOfDay di PrintSystemJobInfo per determinare se l'ora corrente è compresa tra di esse.

Ma le complicazioni derivano dal fatto che queste proprietà non DateTime sono oggetti. Sono invece oggetti che esprimono Int32 l'ora del giorno come numero di minuti dalla mezzanotte. Inoltre, questo non è mezzanotte nel fuso orario corrente, ma mezzanotte UTC (Coordinated Universal Time).

Il primo esempio di codice presenta il metodo statico ReportQueueAndJobAvailability, che viene passato a e PrintSystemJobInfo chiama metodi helper per determinare se il processo può stampare all'ora corrente e, in caso contrario, quando può stampare. Si noti che un PrintQueue oggetto non viene passato al metodo . Ciò è dovuto al fatto che include PrintSystemJobInfo un riferimento alla coda nella relativa HostingPrintQueue proprietà.

I metodi subordinati includono il metodo ReportAvailabilityAtThisTime di overload che può accettare o PrintQueuePrintSystemJobInfo come parametro. È disponibile anche un timeConverter.ConvertToLocalHumanReadableTime. Tutti questi metodi sono illustrati di seguito.

Il metodo ReportQueueAndJobAvailability inizia controllando se la coda o il processo di stampa non è attualmente disponibile. Se uno di essi non è disponibile, verifica se la coda non è disponibile. Se non è disponibile, il metodo segnala questo fatto e l'ora in cui la coda diventerà nuovamente disponibile. Controlla quindi il processo e, se non è disponibile, segnala l'intervallo di tempo successivo quando può stamparlo. Infine, il metodo segnala la prima volta in cui il processo può stampare. Questo è il più tardi dei seguenti due volte.

  • Ora in cui la coda di stampa è disponibile.

  • Ora in cui il processo di stampa è disponibile.

Quando si segnalano orari del giorno, il ToShortTimeString metodo viene chiamato anche perché questo metodo elimina gli anni, i mesi e i giorni dall'output. Non è possibile limitare la disponibilità di una coda di stampa o di un processo di stampa a determinati anni, mesi o giorni.

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

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

Nota

Il fatto che i metodi siano identici, ad eccezione del tipo, pone la domanda sul motivo per cui l'esempio non crea un metodo generico ReportAvailabilityAtThisTime<T>. Il motivo è che tale metodo deve essere limitato a una classe con le proprietà StartTimeOfDay e UntilTimeOfDay che il metodo chiama, ma un metodo generico può essere limitato solo a una singola classe e l'unica classe comune a e PrintQueuePrintSystemJobInfo nell'albero di ereditarietà non PrintSystemObject ha tali proprietà.

Il metodo ReportAvailabilityAtThisTime (presentato nell'esempio di codice seguente) inizia inizializzando una Boolean variabile sentinel su true. Verrà reimpostato su false, se la coda non è disponibile.

Successivamente, il metodo verifica se l'ora di inizio e "until" è identica. In caso affermativo, la coda è sempre disponibile, quindi il metodo restituisce true.

Se la coda non è sempre disponibile, il metodo usa la proprietà statica UtcNow per ottenere l'ora corrente come DateTime oggetto . Non è necessaria l'ora locale perché le proprietà e UntilTimeOfDay si trovano nell'ora StartTimeOfDay UTC.

Tuttavia, queste due proprietà non DateTime sono oggetti . Int32Stanno esprimendo l'ora come numero di minuti dopo-UTC-mezzanotte. È quindi necessario convertire l'oggetto DateTime in minuti dopo mezzanotte. Al termine, il metodo verifica semplicemente se "now" è compreso tra l'inizio della coda e l'ora "fino a", imposta sentinel su false se "now" non è compreso tra le due volte e restituisce la 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

Il metodo TimeConverter.ConvertToLocalHumanReadableTime (presentato nell'esempio di codice seguente) non usa metodi introdotti con Microsoft .NET Framework, quindi la discussione è breve. Il metodo ha un'attività di conversione doppia: deve richiedere un numero intero che esprime minuti dopo la mezzanotte e convertirlo in un'ora leggibile e deve convertirlo nell'ora locale. A tale scopo, crea prima un DateTime oggetto impostato su mezzanotte UTC e quindi usa il AddMinutes metodo per aggiungere i minuti passati al metodo . Viene restituito un nuovo DateTime oggetto che esprime l'ora originale passata al metodo . Il ToLocalTime metodo converte quindi l'oggetto nell'ora locale.

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

Vedi anche