【Vb.net】プリンタジョブの取得

このQ&Aのポイント
  • vb.netにて、印刷処理を実行し、印刷ジョブを監視するプログラムを作成しました。しかし、印刷処理が早く終わってしまい、印刷ジョブを取得できないことが問題です。
  • ジョブが消える前にジョブを取得する方法はあるのでしょうか?
  • また、印刷処理が正常に終了するまで待つ方法を教えてください。
回答を見る
  • ベストアンサー

【Vb.net】プリンタジョブの取得

http://jehupc.exblog.jp/8603528/ 上記のページを参考にさせて頂きvb.netにて、印刷処理を実行し、印刷ジョブを監視するプログラムを作成しました。 印刷処理を実行した時、印刷は実行されるのですが、どうも印刷の処理自体が早く、プリンタジョブを取得する前にジョブが終了してしまっているようです。 ジョブを監視しようにも、ジョブが既に消えてしまっているので、監視しているループから抜けだせません。 (ジョブが溜まっているときは上手くジョブを取得出来るのでプログラムの処理自体は問題ないと思います。) どうにか、消えてしまう前にジョブを取得できないでしょうか? 下記が該当のプログラムです。 処理自体はバックグラウンド処理でファイルの個数分ループしています。 -------------------------------------------------------------------------------------- '印刷処理 ShellExecute(IntPtr.Zero, "print", 【ファイルパス】, "", "", 0) 'プリントサーバの情報取得 Dim prtSv As New LocalPrintServer() '印刷キュー取得 Dim que As PrintQueue = prtSv.DefaultPrintQueue '処理フラグ T:正常 F:異常 Dim blnRtn As Boolean = True 'ジョブ番号 Dim intJobNum As Integer 'ループ内での時間カウント Dim intCnt As Integer = 0 '下記のループで待つ時間をミリ秒単位で指定 Dim intWatiMiliTime As Integer = 10 '印刷がキューに入るまで待つ。 While True '指定ミリ秒待つ Threading.Thread.Sleep(intWatiMiliTime) intCnt += intWatiMiliTime '1分以上たっていたら、印刷に問題があったことにして処理異常フラグを立てる If intCnt > 60000 Then blnRtn = False Exit While End If 'キューが1つ以上 If que.NumberOfJobs > 0 Then Dim jobList As New List(Of PrintSystemJobInfo)() '印刷ジョブコレクション取得 For Each ps As PrintSystemJobInfo In que.GetPrintJobInfoCollection jobList.Add(ps) Next '最新ジョブ名に印刷ファイル名が含まれるとき、このプログラムから印刷キューに入れたと判断する。 If jobList(jobList.Count - 1).Name.EndsWith(【ファイルパス】, True, Nothing) Then intJobNum = jobList(jobList.Count - 1).JobIdentifier Exit While End If End If End While intCnt = 0 '指定されたジョブが印刷完了するまで待つ While blnRtn '指定ミリ秒待つ Threading.Thread.Sleep(intWatiMiliTime) intCnt += intWatiMiliTime Dim jobNow As PrintSystemJobInfo Try jobNow = que.GetJob(intJobNum) Catch ex As Exception '(すでに印刷が完了してジョブが破棄されたとき対策) '異常フラグ立てループ終了 blnRtn = False End Try If jobNow.JobStatus = PrintJobStatus.Completed _ OrElse jobNow.JobStatus = PrintJobStatus.Deleted _ OrElse jobNow.JobStatus = PrintJobStatus.Deleting _ OrElse jobNow.JobStatus = PrintJobStatus.Printed _ OrElse jobNow.JobStatus = PrintJobStatus.Printing _ OrElse jobNow.JobStatus = PrintJobStatus.Retained Then 'ループ終了 Exit While End If 'ジョブがなんらかのエラか、タイムアウト(1分)したなら処理異常終了 If jobNow.JobStatus = PrintJobStatus.Error _ OrElse jobNow.JobStatus = PrintJobStatus.Offline _ OrElse jobNow.JobStatus = PrintJobStatus.PaperOut _ OrElse jobNow.JobStatus = PrintJobStatus.UserIntervention _ OrElse intCnt > 60000 Then '異常フラグ立てループ終了 blnRtn = False End If End While

質問者が選んだベストアンサー

  • ベストアンサー
  • nicotinism
  • ベストアンサー率70% (1019/1452)
回答No.3

『続き』のことに触れられていなかったので、見落としているのかな? と思いレスしただけです。 VB.Net ・・さっぱり分かりません。 あの『続き』のなかで、 http://msdn.microsoft.com/ja-jp/library/aa970685.aspx が紹介されていますが、各Queueを個別にRefreshせんとダメっぽいですね。 タイミングとしては、While の直後か End While の直前ではないですかね? 何分サッパリわかりませんので・・・

その他の回答 (2)

  • nicotinism
  • ベストアンサー率70% (1019/1452)
回答No.2

質問者さんが参考にされたサイトには、下の方に続きがありますけど・・・。 追記:この方法ではジョブやキューの状態取得に問題があることが判明しました。 詳しくは(VB.Net)[補足2].NetからのPDFファイル印刷方法を参照。 http://jehupc.exblog.jp/8650821/

rigard1225
質問者

お礼

ご回答ありがとうございます。 該当のページは既に見させていただいてました。 記事中のRefresh()を試してみたのですが、いまいちどこに入れていいか分からず、入れて実行してもRefresh()でエラーが発生してしまいました。 何か解決策はありますでしょうか?

  • todo36
  • ベストアンサー率58% (728/1234)
回答No.1

.NETのライブラリで動かないなら、WinAPIですね。 CodeProjectのサンプルが良さそう。 http://q.hatena.ne.jp/1315385978

rigard1225
質問者

お礼

ご回答ありがとうございます。 なんか難しそうで、理解に時間がかかりそうです。 でも、参考にさせて頂きます。

関連するQ&A

  • Excel2002 配列の取得

    いつもお世話になっております。 Excelのデータを行単位で配列に書き換える処理を VBAで記述しています。 '****************************************************** '*** 行のループ処理(見出し行を含まず2行目から) For intCnt = 1 To intRow '*** 列のループ処理 For intCnt2 = 1 To 58  '*** セル範囲を配列変数に格納する varUPDT = wsWS.cells(intCnt, 1).Resize(intCnt, 58).Value  If intCnt2 = 1 Then  varDATA = "('" & varUPDT(intCnt, intCnt2) & "'" Else If varUPDT(intCnt, intCnt2) = Empty Then  varUPDT(intCnt, intCnt2) = 0 Else End If '*** テキスト型の列を指定  If intCnt2 = 2 Then  varDATA = varDATA & ",'" & varUPDT(intCnt, intCnt2) & "'" Else  varDATA = varDATA & "," & varUPDT(intCnt, intCnt2) End If End If Next intCnt2 varDATA = varDATA & ")" Next intCnt '****************************************************** 取得した結果を見ると、なぜか奇数行のみが 取得されています。 行の変数(IntCnt)は1ずつ増えていっているのに不思議です。 間違いをご指摘いただきたく存じます。 どうぞよろしくお願いいたします。

  • VB2008で0ページの印刷ジョブを削除したい

    プリンターの印刷ジョブを確認すると、N/Aとなっている印刷ジョブが存在します。 実際には0ページなのですが、必要があって保留状態でスプールに蓄積しています。 これを、VBのPrintSystemJobInfoを使ってキャンセルできないかと考えたのですが 指定のプリンターにある0ページの印刷ジョブをどうやってキャンセルしていいかわかりません。 Public Property JobSize As Integer '使用 Dim instance As PrintSystemJobInfo Dim value As Integer value = instance.JobSize if value = 0 then instance.cancel end if とやればできそうなのですが、プリンタ内にある全てのジョブで やるには、どのようにループさせればいいのでしょうか?

  • アクセス フォームが存在するかを一発で取得したい

    フォームが50個くらいあるのですが 該当のフォームが存在するかvbaで取得したいのですが If CurrentProject.AllForms("フォーム1").IsLoaded Then のように、一発で取得する方法はありますか? 今は Sub Sample1() Dim DB As DAO.Database Dim f As DAO.Document Set DB = CurrentDb Dim strForm As String Dim flg As Boolean strForm = "Fメインメニュー" For Each f In DB.Containers!Forms.Documents If strForm = f.Name Then flg = True Exit For End If Next If flg = False Then MsgBox strForm & "は存在しません" End If End Sub のような感じで、すべてのフォームをループしているのですが 無駄が多い気がします。 改善策があればお願いします。

  • CSV出力に関して

    開発環境:Visual Basic 2008 教えて下さい。 あるホームページを参考に、CSV出力のプログラム(下記)を作成していますが、その際に、 どうやらデータは出力されているももの、ファイルを開いてもデータの中身が見れません。 メモ帳で開くとデータは存在しています。 何か記述漏れ等ありますでしょうか? 初歩的なトラブルで申し訳ありませんが、教えて下さい。 よろしくお願いします。 《記述内容》 Dim dt As DataTable = CType(G_DATA.DataSource, DataTable) '保存先のCSVファイルのパス Dim csvPath As String = "C:\test1.csv" 'CSVファイルに書き込むときに使うEncoding Dim enc As System.Text.Encoding = _ System.Text.Encoding.GetEncoding("Shift_JIS") '開く Dim sr As New System.IO.StreamWriter(csvPath, False, enc) Dim colCount As Integer = dt.Columns.Count Dim lastColIndex As Integer = colCount - 1 'ヘッダを書き込む Dim i As Integer For i = 0 To colCount - 1 'ヘッダの取得 Dim field As String = dt.Columns(i).Caption '"で囲む必要があるか調べる If field.IndexOf(ControlChars.Quote) > -1 OrElse _ field.IndexOf(","c) > -1 OrElse _ field.IndexOf(ControlChars.Cr) > -1 OrElse _ field.IndexOf(ControlChars.Lf) > -1 OrElse _ field.StartsWith(" ") OrElse _ field.StartsWith(ControlChars.Tab) OrElse _ field.EndsWith(" ") OrElse _ field.EndsWith(ControlChars.Tab) Then If field.IndexOf(ControlChars.Quote) > -1 Then '"を""とする field = field.Replace("""", """""") End If field = """" + field + """" End If 'フィールドを書き込む sr.Write(field) 'カンマを書き込む If lastColIndex > i Then sr.Write(","c) End If Next i '改行する sr.Write(ControlChars.Cr + ControlChars.Lf) 'レコードを書き込む Dim row As DataRow For Each row In dt.Rows For i = 0 To colCount - 1 'フィールドの取得 Dim field As String = row(i).ToString() '"で囲む必要があるか調べる If field.IndexOf(ControlChars.Quote) > -1 OrElse _ field.IndexOf(","c) > -1 OrElse _ field.IndexOf(ControlChars.Cr) > -1 OrElse _ field.IndexOf(ControlChars.Lf) > -1 OrElse _ field.StartsWith(" ") OrElse _ field.StartsWith(ControlChars.Tab) OrElse _ field.EndsWith(" ") OrElse _ field.EndsWith(ControlChars.Tab) Then If field.IndexOf(ControlChars.Quote) > -1 Then '"を""とする field = field.Replace("""", """""") End If field = """" + field + """" End If 'フィールドを書き込む sr.Write(field) 'カンマを書き込む If lastColIndex > i Then sr.Write(","c) End If Next i '改行する sr.Write(ControlChars.Cr + ControlChars.Lf) Next row '閉じる sr.Close()

  • VB.netでの二分探索

    今VB.netで二分探索のプログラムを作ろうとしています。 普通の二分探索のプログラムを作ることはできたのですが再帰を使っての二分探索を行うプログラムを作ろうとして悩んでいます。 再帰を行うために普通の二分探索の一部をプロシージャとして分けるところまではできました。再帰をどこに入れればいいのか分からないのですがご教授願えますでしょうか? よろしくお願いします。下に現在できているコードを載せておきます。 Private Sub butSarch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butSarch.Click '捜索 Dim intS, intCnt, intL, intR As Integer intS = InputBox("探索したい数値を入力してください", "数値入力") intCnt = 1 intL = 0 intR = 9 fucTansaku(intS, intCnt, intL, intR) End Sub Private Function fucTansaku(ByVal intS2 As Integer, ByVal intCnt2 As Integer, ByVal intL2 As Integer, ByVal intR2 As Integer) As Integer Dim intM As Integer intM = (intL2 + intR2) \ 2 Do While intL2 <= intR2 If intA(intM) = intS2 Then Exit Do End If If intA(intM) < intS2 Then intL2 = intM + 1 Else intR2 = intM - 1 End If intM = (intL2 + intR2) \ 2 intCnt2 = intCnt2 + 1 Loop If intL2 <= intR2 Then MsgBox(intCnt2 & "回目の探索で見つかりました", MsgBoxStyle.OkOnly, "結果") Else MsgBox("見つかりませんでした", MsgBoxStyle.OkOnly, "結果") End If End Function

  • 数値かどうかを取得したい IsNumberではダメ

    Sub Macro2() Dim mystr As String mystr = "1" If IsDate(mystr) = False Then MsgBox "NO" End If End Sub これなら日付型かどうかを取得できるのに、 Sub Macro1() Dim mystr As String mystr = "1" If IsNumber(mystr) = False Then MsgBox "NO" End If End Sub だと、IsNumberがコンパイルエラーになります。 変数に入っている値が数値として評価できるかを取得する方法を教えてください。

  • JIS codeでの文字数・桁数制限

    Access97を使用しております。 VBのカテゴリに近いと思い質問させて下さい。 >JIS codeでの文字数・桁数制限を行いたいのですが、 条件がきつく困ってます。 条件.(JIS)20文字で改行 MAXが25桁まで入力可能 >>一応行数は改行数を数えることで、取得できてます。 Dim i As Integer Dim strChk As String Dim intCnt As Integer '2桁取得し改行を認識させる。 For i = 1 To Len(Me.内容) - 1 strChk = Mid$(Me.内容, i, 2) If strChk = Chr(13) & Chr(10) Then intCnt = intCnt + 1 End If Next i Me.txtGyo = intCnt + 1 Exit Sub 文字数は通常1行であれば↓のようなコードですみますが、両方って・・・・; >改行マーク「Chr(13)&Chr(10)」迄が1行と考えるって事なんでしょうが初 心者には難しいくご教授お願い致します。 Dim strMoji As String Dim strChck As String strMoji = Me.内容 strChck = LenB(StrConv(strMoji, vbFromUnicode)) Me.txtMsg = "" If strChck >= 33 Then Me.txtMsg = "文字数がOverしてます。" Else Exit Sub   End If

  • ファイルが既に開いているかどうかを取得するには

    Sub Sample1() Dim App As Object Dim MyFileName As String Set App = CreateObject("Excel.Application") MyFileName = "C:\Users\test.xlsm" With App .Workbooks.Open Filename:=MyFileName .Visible = True If .ReadOnly Then MsgBox "既に開いています" App.Quit '既に開いているのなら、閉じる End If End With End Sub このようなコードを作ったのですが、どうやらIf .ReadOnly Thenの部分が間違っているようです。 エラーになります。 既にファイルが開いているか、読み取り専用かどうかを取得するコードをご教授ください。

  • シートAとシートBの得意先コードが一致したら、該当行をシートCにコピー

    シートAとシートBの得意先コードが一致したら、該当行をシートCにコピーするVBAを組みたいのですが、上手く行きません。加えてシートAの該当行は削除しておきたいです。 XPでExcel2003を使用しています。 Const strMasSheet = "A" Const strMasSheet2 = "B" Const strSrhSheet = "C" Dim strSrhCode As Long 'シートAの得意先コード Dim strSrhCode2 As Long 'シートBの得意先コード Dim intRow As Long Dim intRow2 As Long Dim intCnt As Long Dim maxgyo As Long 'シートAの最終行 Dim maxgyo2 As Long 'シートBの最終行 Sub データを分ける() maxgyo = Sheets(strMasSheet).Cells(Rows.Count, 1).End(xlUp).Row 'シートAの最終行を取得 For intRow = 2 To maxgyo '2行から始めて最終行まで(1upで) strSrhCode = Sheets(strMasSheet).Cells(intRow, 2) '検索値 B列= 得意先CDを取得 maxgyo2 = Sheets(strMasSheet2).Cells(Rows.Count, 1).End(xlUp).Row 'シートBの最終行を取得 For intRow2 = 2 To maxgyo '2行から始めて最終行まで(1upで) strSrhCode2 = Sheets(strMasSheet).Cells(intRow, 8) '検索値 H列 = 得意先CDを取得 intCnt = 2 '2行から If strSrhCode = strSrhCode2 Then 'もし検索値と検索対象シートの得意先CDが一致したら intCnt = intCnt + 1 With Sheets(strSrhSheet) .Cells(intCnt, 1) = Cells(intRow, 1) .Cells(intCnt, 2) = Cells(intRow, 2) .Cells(intCnt, 3) = Cells(intRow, 3) .Cells(intCnt, 4) = Cells(intRow, 4) .Cells(intCnt, 5) = Cells(intRow, 5) .Cells(intCnt, 6) = Cells(intRow, 6) .Cells(intCnt, 7) = Cells(intRow, 7) .Cells(intCnt, 8) = Cells(intRow, 8) .Cells(intCnt, 9) = Cells(intRow, 9) .Cells(intCnt, 10) = Cells(intRow, 10) .Cells(intCnt, 11) = Cells(intRow, 11) End With End If Next intRow2 Next intRow MsgBox "処理終了" End Sub 言葉足らずの所があればごめんなさい。 追記いたしますので、教えて下さい。 よろしくお願い致します。

  • プリンタの印刷ジョブを削除したい。

    プリンタの印刷ジョブを削除したい。 現在、VB.NET(Visual Studio 2008)で開発を行っています。 SetPrinter関数を使用して、印刷ジョブを全て削除したいのですがSetPrinterに失敗してしまいます。 GetLastErrorの戻り値は「5」でアクセス拒否のようです。 SetPrinterの前にOpenPrinterは成功しており、プリンタの印刷ジョブの情報は取得できています。 なお、同環境でVB6.0で同様のプログラムを作成し実行したところジョブの削除ができました。 類似した現象・解決方法等ご存知でしたら教えてください。 開発環境はWindowsXP、Visual Studio 2008です。 以下、ソースの抜粋です。 '宣言 Private Const DEF_INIT_BUFFER_PERFORM As Integer = 100 Public Const STANDARD_RIGHTS_REQUIRED = &HF0000 Public Const PRINTER_ACCESS_ADMINISTER = &H4 Public Const PRINTER_ACCESS_USE = &H8 Public Const PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or _ PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE) Public Structure PRINTER_DEFAULTS Public pDatatype As IntPtr Public pDevMode As IntPtr Public DesiredAccess As Integer End Structure <DllImport("winspool.drv", CharSet:=CharSet.Auto, SetLastError:=True)> _ Private Shared Function OpenPrinter( _ ByVal pPrinterName As String, _ ByRef hPrinter As IntPtr, _ ByVal pDefault As PRINTER_DEFAULTS _ ) As Boolean End Function <DllImport("winspool.drv", CharSet:=CharSet.Auto, SetLastError:=True)> _ Private Shared Function SetPrinter( _ ByVal hPrinter As IntPtr, _ ByVal Level As Long, _ ByVal pDefault As IntPtr, _ ByVal Command As Long _ ) As Boolean End Function '実行部 Dim pd As New PRINTER_DEFAULTS pd.DesiredAccess = PRINTER_ALL_ACCESS Dim printerHandle As IntPtr Dim ret As Boolean = OpenPrinter("プリンタ名", printerHandle, pd) Dim err As Integer = Marshal.GetLastWin32Error() 'Falseが返る ret = SetPrinter(printerHandle, CLng(0), IntPtr.Zero, CLng(3)) '5が返る err = Marshal.GetLastWin32Error()

専門家に質問してみよう