方法: 現在、印刷ジョブが印刷可能であるかどうかを検出する

印刷キューは、1 日 24 時間利用できるとは限りません。 開始時刻と終了時刻のプロパティがあり、特定の時間帯に使用できないように設定できます。 この機能を使用すると、たとえば、午後 5 時以降は特定の部署が排他的に使用するようにプリンターを予約することができます。 この部署では、他の部署が使用しているのとは異なるキューを使用します。 他の部署のキューは、午後 5 時以降は使用不可になるように設定されるのに対し、優先される部署のキューは常に使用可能になるように設定できます。

さらに、印刷ジョブ自体を、指定された期間内にのみ印刷できるように設定できます。

Microsoft .NET Framework の API で公開されている PrintQueue クラスと PrintSystemJobInfo クラスにより、特定の印刷ジョブが現在の時刻に特定のキューで印刷できるかどうかをリモートで確認する手段が提供されます。

次の例は、印刷ジョブに関する問題を診断できるサンプルです。

この種の関数には、次の 2 つの主要な手順があります。

  1. PrintQueueStartTimeOfDay プロパティと UntilTimeOfDay プロパティを読み取って、現在の時刻が両者の間にあるかどうかを判断します。

  2. PrintSystemJobInfoStartTimeOfDay プロパティと UntilTimeOfDay プロパティを読み取って、現在の時刻が両者の間にあるかどうかを判断します。

しかし、これらのプロパティが DateTime オブジェクトではないという事実から、複雑な問題が発生します。 これらは、時刻を午前 0 時からの分数として表す Int32 オブジェクトです。 さらに、現在のタイム ゾーンの午前 0 時ではなく、UTC (世界協定時) の午前 0 時です。

最初のコード例は、静的メソッド ReportQueueAndJobAvailability を示しています。これは、PrintSystemJobInfo に渡され、ヘルパー メソッドを呼び出して、現在の時刻にジョブが印刷できるかどうか、できない場合はいつ印刷できるかを判断します。 PrintQueue はメソッドに渡されないことにご注意ください。 これは、PrintSystemJobInfo にはその HostingPrintQueue プロパティのキューへの参照が含まれているためです。

下位メソッドには、オーバーロードされた ReportAvailabilityAtThisTime メソッドが含まれています。このメソッドは、パラメーターとして PrintQueue または PrintSystemJobInfo を受け取ることができます。 TimeConverter.ConvertToLocalHumanReadableTime もあります。 これらのメソッドについては、すべて以下で説明します。

ReportQueueAndJobAvailability メソッドは、最初に、キューまたは印刷ジョブが現時点で使用できないかどうかを確認します。 これらのいずれかが使用できない場合は、次にキューが使用できないかどうかを確認します。 使用できない場合、このメソッドは、この事実と、キューが再び使用可能になる時刻を報告します。 次にジョブを確認し、使用できない場合は、次に印刷できる時間帯を報告します。 最後に、このメソッドは、ジョブが印刷できる最も早い時刻を報告します。 これは、次の 2 つの時刻の遅い方です。

  • 印刷キューが次に使用可能になる時刻。

  • 印刷ジョブが次に使用可能になる時刻。

時刻を報告する場合に、ToShortTimeString メソッドも呼び出されます。このメソッドは、出力に年、月、日が表示されないようにするからです。 印刷キューまたは印刷ジョブの可用性を、特定の年、月、または日に制限することはできません。

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

ReportAvailabilityAtThisTime メソッドの 2 つのオーバーロードは、これらに渡される型を除いて同じです。そのため、PrintQueue バージョンのみを以下に示します。

注意

メソッドは型を除き同一であるため、サンプルでは、なぜジェネリック メソッド ReportAvailabilityAtThisTime<T> が作成されないのかという疑問が生じます。 その理由は、これらのメソッドは、メソッドによって呼び出される StartTimeOfDay および UntilTimeOfDay のプロパティを持つクラスに制限する必要がありますが、ジェネリック メソッドは 1 つのクラスにしか制限できず、継承ツリー内の PrintQueuePrintSystemJobInfo の両方に共通する唯一のクラスは、こうしたプロパティを持たない PrintSystemObject だからです。

(下記のコード例に示されている) ReportAvailabilityAtThisTime メソッドは、まず Boolean sentinel 変数を trueに初期化します。 キューが使用できない場合は、false にリセットされます。

次にこのメソッドは、開始時刻と "until" (終了) 時刻が同じかどうかを確認します。 同じ場合、キューは常に使用可能なので、メソッドは true を返します。

キューが常に利用できない場合、メソッドは静的 UtcNow プロパティを使用して、DateTime オブジェクトとして現在の時刻を取得します (StartTimeOfDay プロパティと UntilTimeOfDay プロパティは UTC 時刻であるため、現地時刻は必要ありません)。

ただし、これら 2 つのプロパティは DateTime オブジェクトではありません。 これらは UTC の午前 0 時からの分数として時刻を表す Int32 です。 そのため、DateTime オブジェクトを午前 0 時からの分数に変換する必要があります。 それが完了すると、メソッドでは "now" (現在の時刻) がキューの開始時刻と "until" (終了) 時刻の間にあるかどうかが確認され、"now" がこの 2 つの時刻の間にない場合は sentinel が false に設定されて、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

(下記のコード例に示されている) TimeConverter.ConvertToLocalHumanReadableTime メソッドは、Microsoft .NET Framework で導入されたメソッドを使用しないため、説明は簡単です。 このメソッドには、2 回の変換タスクがあります。これは、午前 0 時からの分数を表す整数値を取得し、それを人間が判読できる時刻に変換し、それを現地時刻に変換する必要があります。 これを実現するには、最初に UTC の午前 0 時に設定された DateTime オブジェクトを作成し、次に AddMinutes メソッドを使用して、メソッドに渡された分数を加算します。 これにより、メソッドに渡された元の時刻を表す新しい DateTime が返されます。 その後、ToLocalTime メソッドがこれを現地時刻に変換します。

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

関連項目