none
印刷ジョブの監視をしたいのですが、どうしたら良いでしょうか? RRS feed

  • 質問

  •  

    インターフェースファイルを取り込み、エクセルファイルを作成して印刷を行う機能を作成しているのですが、

    印刷が正常に終了したかどうかの判断を行いたいと思っています。

     

    VB2008にて開発を行っていますので、

    ”PrintQueue”を使用すれば良いのでは無いかと思うのですが、

    どのように使用すれば良いかわかりません。

     

    ご存じの方がいましたら、ご教授いただければと思います。

     

    宜しくお願い致します。

     

    開発環境

    Windows XP (SP3)

    Visual Basic 2008

    .NET Framework 3.5

    2008年8月6日 1:52

すべての返信

  • だいぶ昔のですが、私は次のようなコードで印刷開始を待機する処理を作成しました。(.NET 4.0ですが)

    最後の、 JobStatusの判定部分を変更すれば印刷完了まで待てるはずです。

        ''' <summary>
        ''' 指定したドキュメントの印刷が開始されるまで待機します。
        ''' </summary>
        ''' <param name="printerName">印刷を行うプリンタ名。</param>
        ''' <param name="timeOut">タイムアウト(ms)。0を指定すると無制限に待機します。</param>
        ''' <param name="fileName">印刷の開始を待機するドキュメント名を指定します。</param>
        ''' <param name="extention">印刷の開始を待機するドキュメントの拡張子を指定します。大文字・小文字は区別されません。</param>
        ''' <param name="includes">印刷の開始を待機するドキュメント名に含まれる文字列を指定します。アルファベットが含まれる場合、大文字・小文字は区別されます。</param>
        ''' <remarks>
        ''' ジョブ名と <paramref name="fileName" /> が完全に一致するか、ジョブ名に <paramref name="includes" /> で指定した文字列が全て含まれているジョブの印刷開始を待機します。
        ''' </remarks>
        Private Sub WaitForPrint(ByVal printerName As String, ByVal timeOut As Long, ByVal fileName As String, ByVal extention As String, ByVal ParamArray includes() As String)
            Dim logid As Integer = Now.Millisecond
    
            Dim includesString As String = String.Empty
            For Each include As String In includes
                If (includesString.Length > 0) Then includesString += ", "
                includesString += include
            Next
            Dim arguments As String = String.Empty
            arguments += String.Format("printername : {0}", printerName) & vbCrLf
            arguments += String.Format("timeOut : {0}", timeOut) & vbCrLf
            arguments += String.Format("fileName : {0}", fileName) & vbCrLf
            arguments += String.Format("extention : {0}", extention) & vbCrLf
            arguments += String.Format("includes : {0}", includesString) & vbCrLf
    
            Try
                Me.LogWrite("プリンタ:{0} の印刷開始を待機します。(タイムアウト:{1} ms)" & vbCrLf & "引数 : {2}", printerName, timeOut, arguments)
    
                ' プリンタのキューを取得し、指定されたジョブが開始されるまで待機
                Using queue As PrintQueue = GetPrintQueue(printerName)
    
                    ' タイムアウト計測用タイマ
                    Dim st As New Stopwatch()
    
                    ' 印刷が開始されたことを示すフラグ
                    Dim spooling As Boolean = False
                    Dim printing As Boolean = False
    
                    ' タイムアウトが設定されていればタイマをスタート
                    If (timeOut > 0) Then st.Start()
    
                    Dim jobFound As Boolean = False
                    Dim targetJob As PrintSystemJobInfo = Nothing
    
                    Do Until (printing = True)
                        ' CPUリソースを占有しないようにスリープ
                        System.Threading.Thread.Sleep(QUEUE_POLLING_INTERVAL)
                        Application.DoEvents()
    
                        ' タイムアウト判定
                        If (st.ElapsedMilliseconds > timeOut) Then
                            If (jobFound = True) Then
                                Try
                                    targetJob.Cancel()
                                Catch ex As Exception
                                    ' ジョブキャンセル時の例外は無視
                                End Try
                            End If
                            Throw New TimeoutException("操作がタイムアウトしました。", New Exception(arguments))
                        End If
    
                        ' まずはキューからジョブを検索する
                        If (jobFound = False) Then
                            ' キュー内のジョブを列挙
                            queue.Refresh()
                            Dim jobs As PrintJobInfoCollection = queue.GetPrintJobInfoCollection()
    
                            Me.LogWrite("ジョブの列挙を開始します。")
    
                            For Each job As PrintSystemJobInfo In jobs
                                If (job IsNot Nothing AndAlso job.Submitter = Environment.UserName) Then
    
                                    Me.LogWrite("{0} : {1}", job.Name, job.JobStatus)
    
                                    ' 拡張子 および ファイル名に含まれる文字列から、監視対象のジョブを特定する
                                    If (String.IsNullOrEmpty(extention) = True OrElse job.Name.ToLower.EndsWith(extention.ToLower) = True) Then
                                        Dim includesFound As Boolean = True
                                        For Each match As String In includes
                                            If (job.Name.Contains(match) = False) Then
                                                includesFound = False
                                                Exit For
                                            End If
                                        Next
    
                                        ' ジョブ名と fileName の一致を確認
                                        Dim fileNameFound As Boolean = job.Name.Trim.Equals(fileName.Trim)
    
                                        ' ジョブ名と fileName が完全に一致するか、ジョブ名に includes で指定した文字列が全て含まれていればOK
                                        jobFound = (includesFound Or fileNameFound)
    
                                    Else
                                        jobFound = False
                                    End If
                                    If (jobFound = True) Then
                                        targetJob = job
                                        Me.LogWrite("印刷対象のジョブ「{0}」が見つかりました。ステータス:{1}", job.Name, job.JobStatus)
                                        Exit For
                                    End If
                                End If
                            Next
                            Me.LogWrite("ジョブの列挙が終了しました。")
                        End If
    
                        If (jobFound = True) Then
                            targetJob.Refresh()
                            Me.LogWrite("印刷対象のジョブ「{0}」を監視しています。ステータス:{1}", targetJob.Name, targetJob.JobStatus)
    
                            If ((targetJob.JobStatus And PrintJobStatus.Retained) = PrintJobStatus.Retained OrElse
                                (targetJob.JobStatus And PrintJobStatus.Completed) = PrintJobStatus.Completed OrElse
                                (targetJob.JobStatus And PrintJobStatus.Deleted) = PrintJobStatus.Deleted
                                ) Then
                                ' 印刷が開始された
                                printing = True
                                Me.LogWrite("プリンタ:{0} で {1} の印刷が開始されました。JobStatus:{2}", printerName, targetJob.Name, targetJob.JobStatus)
    
                            ElseIf ((targetJob.JobStatus And PrintJobStatus.Error) = PrintJobStatus.Error) Then
                                Throw New ApplicationException("印刷中にエラーが発生しました。")
    
                            ElseIf ((targetJob.JobStatus And PrintJobStatus.Spooling) = PrintJobStatus.Spooling) Then
                                spooling = True
    
                            ElseIf (targetJob.JobStatus = PrintJobStatus.None AndAlso spooling = True) Then
                                ' 一度 Spooling 状態となってから None になったジョブは、
                                ' 「スプール済みでプリンタの都合で待たされている」と判断できるため 印刷開始とみなす。
                                printing = True
                                Me.LogWrite("プリンタ:{0} で {1} の印刷が開始されました。JobStatus:{2}", printerName, targetJob.Name, targetJob.JobStatus)
    
                            End If
                        End If
                    Loop
                End Using
            Catch ex As Exception
                Me.LogWrite(ex)
                Throw
            End Try
    
        End Sub
    2012年7月13日 14:35
  • おっと

    GetPrintQueueは以下のような簡単なメソッドです。

        ''' <summary>
        ''' 指定したプリンタのキューを取得します。
        ''' </summary>
        ''' <param name="printerName">プリンタ名</param>
        ''' <returns>指定したプリンタのキューを表す <see cref="System.Printing.PrintQueue" /> 。</returns>
        ''' <remarks></remarks>
        Private Function GetPrintQueue(ByVal printerName As String) As PrintQueue
            Dim server As New LocalPrintServer()
            Return New PrintQueue(server, printerName, 2)
        End Function

    2012年7月13日 14:36