###前提・実現したいこと
今、vb.netでプリンタのスプーラのジョブを監視し、紙に印字されたかもしくは紙に印字される前にジョブをキャンセルされるかが判断するまで、ウェイトをかける(次の処理を待つ)プログラムを作成しています。(また、この時スプーラにジョブを残して再印刷するなどは今回は考慮していません)
ソースの参考にしたURL
https://social.msdn.microsoft.com/Forums/vstudio/ja-JP/0f697287-9643-4434-acf5-acc00b2e9a86?forum=vbgeneralja
###発生している問題
下記の判定で良いかどうかの裏付けを取りたいのでPrintSystemJobInfo.JobStatusが印刷完了しスプーラのジョブが削除されるまでにはどのように状態遷移するかの資料を探しています。
###印刷時の判定内容
紙に印刷された事を判定するのに、targetJob.JobStatus が PrintJobStatus.Completed を含む時、フラグを立て(printing=true)、targetJob.JobStatus が PrintJobStatus.Deleted を含む時、printing=trueかで印刷が完了したかの判断をしています。
###追伸
下記のソースコードを使ってプリンタに印刷しテストを行い、そのときの経験的に下記の紙に印刷された時の判定を決めました。
###該当のソースコード
vb.net
1 Dim QUEUE_POLLING_INTERVAL As Integer = 2 2 ''' <summary> 3 ''' 指定したドキュメントの印刷が開始されるまで待機します。 4 ''' </summary> 5 ''' <param name="printerName">印刷を行うプリンタ名。</param> 6 ''' <param name="timeOut">タイムアウト(ms)。0を指定すると無制限に待機します。</param> 7 ''' <param name="fileName">印刷の開始を待機するドキュメント名を指定します。</param> 8 ''' <param name="extention">印刷の開始を待機するドキュメントの拡張子を指定します。大文字・小文字は区別されません。</param> 9 ''' <param name="includes">印刷の開始を待機するドキュメント名に含まれる文字列を指定します。アルファベットが含まれる場合、大文字・小文字は区別されます。</param> 10 ''' <remarks> 11 ''' ジョブ名と <paramref name="fileName" /> が完全に一致するか、ジョブ名に <paramref name="includes" /> で指定した文字列が全て含まれているジョブの印刷開始を待機します。 12 ''' </remarks> 13 Private Function WaitForPrint(ByVal printerName As String, ByVal timeOut As Long, ByVal fileName As String, ByVal extention As String, ByVal ParamArray includes() As String) As Boolean 14 Dim isComprete As Boolean = False '紙に印字されたらTrue 15 Dim logid As Integer = Now.Millisecond 16 17 Dim includesString As String = String.Empty 18 includesString = String.Join(", ", includes) 19 20 Dim arguments As New System.Text.StringBuilder() 21 arguments.AppendLine(String.Format("printername : {0}", printerName)) 22 arguments.AppendLine(String.Format("timeOut : {0}", timeOut)) 23 arguments.AppendLine(String.Format("fileName : {0}", fileName)) 24 arguments.AppendLine(String.Format("extention : {0}", extention)) 25 arguments.AppendLine(String.Format("includes : {0}", includesString)) 26 27 Try 28 Me.LogWrite("プリンタ:{0} の印刷開始を待機します。(タイムアウト:{1} ms)" & vbCrLf & "引数 : {2}", printerName, timeOut, arguments.ToString) 29 30 ' プリンタのキューを取得し、指定されたジョブが開始されるまで待機 31 Using queue As PrintQueue = GetPrintQueue(printerName) 32 33 ' タイムアウト計測用タイマ 34 Dim st As New Stopwatch() 35 36 ' 印刷が開始されたことを示すフラグ 37 Dim spooling As Boolean = False 38 Dim printing As Boolean = False 'プリントが完了した場合はtrue(キャンセルで削除された場合もtrue) 39 40 ' タイムアウトが設定されていればタイマをスタート 41 If (timeOut > 0) Then st.Start() 42 43 Dim jobFound As Boolean = False 44 Dim targetJob As PrintSystemJobInfo = Nothing 45 46 Dim OldMessage As String = String.Empty 47 48 Do Until (printing = True) 49 ' CPUリソースを占有しないようにスリープ 50 System.Threading.Thread.Sleep(QUEUE_POLLING_INTERVAL) 51 'Application.DoEvents() 52 53 ' タイムアウト判定 54 If (st.ElapsedMilliseconds > timeOut) Then 55 If (jobFound = True) Then 56 Try 57 targetJob.Cancel() 58 Catch ex As Exception 59 ' ジョブキャンセル時の例外は無視 60 End Try 61 End If 62 Throw New TimeoutException("操作がタイムアウトしました。", New Exception(arguments.ToString)) 63 End If 64 65 ' まずはキューからジョブを検索する 66 If (jobFound = False) Then 67 ' キュー内のジョブを列挙 68 queue.Refresh() 69 Dim jobs As PrintJobInfoCollection = queue.GetPrintJobInfoCollection() 70 71 Me.LogWrite("ジョブの列挙を開始します。") 72 73 For Each job As PrintSystemJobInfo In jobs 74 If (job IsNot Nothing AndAlso job.Submitter = Environment.UserName) Then 75 76 Me.LogWrite("{0} : {1}", job.Name, job.JobStatus) 77 78 ' 拡張子 および ファイル名に含まれる文字列から、監視対象のジョブを特定する 79 If (String.IsNullOrEmpty(extention) = True OrElse job.Name.ToLower.EndsWith(extention.ToLower) = True) Then 80 Dim includesFound As Boolean = True 81 For Each match As String In includes 82 If (job.Name.Contains(match) = False) Then 83 includesFound = False 84 Exit For 85 End If 86 Next 87 88 ' ジョブ名と fileName の一致を確認 89 Dim fileNameFound As Boolean = job.Name.Trim.Equals(fileName.Trim) 90 91 ' ジョブ名と fileName が完全に一致するか、ジョブ名に includes で指定した文字列が全て含まれていればOK 92 jobFound = (includesFound Or fileNameFound) 93 94 Else 95 jobFound = False 96 End If 97 If (jobFound = True) Then 98 targetJob = job 99 Me.LogWrite("印刷対象のジョブ「{0}」が見つかりました。ステータス:{1}", job.Name, job.JobStatus) 100 Exit For 101 End If 102 End If 103 Next 104 Me.LogWrite("ジョブの列挙が終了しました。") 105 106 End If 107 108 If (jobFound = True) Then 109 targetJob.Refresh() 110 Dim nowMessage As String = String.Format("印刷対象のジョブ「{0}」を監視しています。ステータス:{1}", targetJob.Name, targetJob.JobStatus) 111 If OldMessage <> nowMessage Then 112 Me.LogWrite("印刷対象のジョブ「{0}」を監視しています。ステータス:{1}", targetJob.Name, targetJob.JobStatus) 113 OldMessage = nowMessage 114 End If 115 116 If (targetJob.JobStatus And PrintJobStatus.Completed) = PrintJobStatus.Completed Then 117 ' 紙に印字された。 118 isComprete = True 'この後deletedが発行されると考えている 119 ElseIf (targetJob.JobStatus And PrintJobStatus.Deleted) = PrintJobStatus.Deleted Then 120 ' ジョブを削除 121 printing = True 122 Me.LogWrite("プリンタ:{0} で {1} の印刷が開始されました。JobStatus:{2}", printerName, targetJob.Name, targetJob.JobStatus) 123 Return isComprete 124 ElseIf ((targetJob.JobStatus And PrintJobStatus.Error) = PrintJobStatus.Error) Then 125 Throw New ApplicationException("印刷中にエラーが発生しました。") 126 ElseIf ((targetJob.JobStatus And PrintJobStatus.Spooling) = PrintJobStatus.Spooling) Then 127 spooling = True 128 ElseIf (targetJob.JobStatus = PrintJobStatus.None AndAlso spooling = True) Then 129 ' 一度 Spooling 状態となってから None になったジョブは、 130 ' 「スプール済みでプリンタの都合で待たされている」と判断できるため 印刷開始とみなす。 131 printing = True 132 Me.LogWrite("プリンタ:{0} で {1} の印刷が開始されました。JobStatus:{2}", printerName, targetJob.Name, targetJob.JobStatus) 133 Return True 134 End If 135 End If 136 Loop 137 End Using 138 Catch ex As Exception 139 140 Me.LogWrite(ex) 141 142 Throw 143 End Try 144 Throw New NoNullAllowedException("戻り値の処理抜け") 145 End Function 146 147 ''' <summary> 148 ''' 指定したプリンタのキューを取得します。 149 ''' </summary> 150 ''' <param name="printerName">プリンタ名</param> 151 ''' <returns>指定したプリンタのキューを表す <see cref="System.Printing.PrintQueue" /> 。</returns> 152 ''' <remarks></remarks> 153 Private Function GetPrintQueue(ByVal printerName As String) As PrintQueue 154 Dim server As New LocalPrintServer() 155 Return New PrintQueue(server, printerName, 2) 156 End Function 157 158 Private Sub LogWrite(Str As Object) 159 Console.WriteLine(Str) 160 End Sub 161 Private Sub LogWrite(Str As String) 162 Console.WriteLine(Str) 163 End Sub 164 Private Sub LogWrite(format As String, ParamArray arg() As Object) 165 Console.WriteLine(format, arg) 166 End Sub
###補足情報(言語/FW/ツール等のバージョンなど)
言語 vb.net
FW .NET Framework 4.0
ツール VisualStudio 2010
あなたの回答
tips
プレビュー