![見出し画像](https://assets.st-note.com/production/uploads/images/101364625/rectangle_large_type_2_28938887535f267089b9c632a840916e.jpeg?width=1200)
どこまで印刷できた?
昔話その2
クラウドチームにいるのにオンプレの昔話ばかりしていていいのか?
前回、印刷系のツールを開発するにあたって、「何か困ってることはありますか?」って聞いてまわったという話をしました。
「プリンターの状態がわからない」という問題があり、これはSNMPを使用することにより解決したというところまで話しました。
「ジャムが発生している」「紙切れ」「そろそろトナーがなくなる」などの状態がわかるようになったという話でした。
どこまで印刷できた?
つぎに言われたのが「途中でジャムったりするとどこまで印刷できたか確認するのが大変。自動的に続きから印刷できないものだろうか?」です。
要望の内容はよく理解できますが、これをPCで実現するのはなかなか難しい。
オフコンの場合は印刷するソフトウェアも制御されるプリンターも自社製なので、どんな制御でも自由に作り込めますが、PCは汎用品でプリンターベンダーも無数にあるので簡単には実現できません。
Windows APIで印刷を行う際にはページという概念はあります。
ただ実際に印刷データをプリンターに送る時はページ毎に区切られているわけではなくて、ひとかたまりのデータ(ストリーム)でしかありません。
PDL(ページ記述言語)によってはページ毎に構造化されているので、ページの概念はありますが、ページの切れ目まで送りつけて、そこで止めておくというわけにはいきません。
どうやって実現しよう
どうやって?ってRDEには「印刷済みページ数取得」機能があるじゃないか?それを使えば?と思った人、正解です。
ただ、この機能はプリンター側が対応したからこそ実現できた機能です。
今回のお話は、プリンター側に機能が追加される前の話です。
RD(C版)の頃ですね。RDEの初期にもこの機能あったっけか?
RD(C版)とは、RDE(Report Director Enterprise) の元になったスプールサーバーで、Windows上でのみ動作するものでした。
これをJavaで書き直すことにより、Windowsだけではなく、Unix/Linuxでも動作するようにしたうえで、大幅に機能拡張をおこなったものがRDEです。
RD(C版)には、印刷開始ページを指定する機能はすでにあるので、どこまで印刷できたか分かれば解決ですね。
SVFの強み
SVF以外の印刷ツールというかSVF以前の印刷ツールかな?はWindows APIを呼び出して印刷データを作っているものが多かったと思います。例外はP1.EXEくらいでしょうか。P1.EXEはなかなか面白い機能を持ったワープロソフトで、文書作成開始前に出力するプリンターを選択します。
選択したプリンターによって使用できる機能が増減します。
プリンターの機能を100%使い切ろうという意欲的なソフトでした。
#「ワープロ」というのが既に死語だな。
P1.EXEは自前で印刷データまで作成していたと思われますが、その他のワープロソフトや、印刷ツールは最終的な印刷データを作成していませんでした。
ページごとにWindows APIを呼び出しているだけで、実際の印刷データを作っているのは各プリンターのWindowsドライバーというわけです。
そのため、最終的にどのような印刷データが作成されるかは印刷ツール側ではわからなかったのではないかと思います。
SVFは最終的にプリンターに渡すPDLを直接生成しています。これが強みとなりました。各ページのデータが何バイトあるかがわかるのです。
プリンターに送信したバイト数がわかれば、どのページまで印刷されているかおおよそわかることになります。
ああ、そうだ。当時のプリンターの動作を書いておかないと、理解できないところがあるかもしれないですね。
当時のプリンターは大量ストレージなどなく、受け取った印刷データをそのまま印刷にまわしていました。
いったんHDDでデータを受けるようになっていたらダメだったでしょうね。これだとたとえジャムってもデータを全部受け取ってしまうと思います。
ジャム発生→受信バッファがあふれる→データを受け取らなくなる
ということが前提の機能です。
昔話ということでちょっと脱線。
当時はプリンター側の受信バッファが小さくて、印刷に時間がかかるため、「プリントバッファ」と呼ばれる外付けのバッファを付けていました。
このプリントバッファで有名だったのが「メルコ」というメーカーで、のちに「バッファロー」という社名になりました。
実にプリントバッファ屋さんらしい名前になったなあと思っていました。
あ、当然こういうプリントバッファが入っている場合もこの機能は使えないのでした。
送信したバイト数がわかれば…
「プリンターに送信したバイト数が分かれば」それがつぎの問題です。
当時の印刷ツールはプリンターにデータを送る部分はWindowsスプーラーに任せていました。そのため、送信済みバイト数はWindowsスプーラーにしかわからなかったのです。
Windowsスプーラーからデータをもらうにはどうすれば良いのだろう?
と、いろいろ検討した結果、ポートモニターを作ることにしました。
ポートモニターは、Windowsスプーラーからデータを受け取ってプリンターに送る処理を行います。
ただ、実際にデータを送る部分を作るのは面倒だったので、データは元々のポートモニターにそのまま横流しすることにしました。
まあ、フィルターみたいな動作になったということですね。
データが渡ってきたらバイト数を数えて、RD(C版)に通知します。
データはそのまま元のポートモニターに渡します。
プリンターは、RDのみで使用されるとは限らないので、RDからの印刷かどうかを判定して、必要な場合のみ通知するようにしました。
RDではプリンターの状態を監視しているので、ジャムが発生したらわかります。
ジャムが発生したら必ず再印刷が必要なわけではありませんが、再印刷指示があった場合は、ポートモニターから通知されたバイト数を使用して「nページまで印刷したはず」という計算を行い、印刷開始ページをガイドします。
結局、印刷済みページ数はわかってませんが…
まあ、バイト数数えてるだけですからね。受信バッファサイズもプリンターによって様々ですから、印刷済みページ数が正確にわかるわけではありません。
一応、バッファサイズの違いを考慮するため、再印刷時に何ページ(何バイト)戻るか?というのは設定できるようになっていました。
丸々再印刷するのは無駄だし、数ページくらいダブってもいいや。という感じでゆるく使用するものでした。
それでも何もないよりは便利だったんですよ。
印刷済みページ数をちゃんと取得しよう
先ほどちょっと触れましたが、RDEには印刷済みページ数を取得する機能があります。
これはプリンター側で印刷済みページ数を管理していて、前回紹介したSNMPを使用してどこまで印刷されたか取得するようになっています。
標準化された機能ではないので、プリンターベンダー毎に作り込みが必要でなため、すべてのプリンターで使用できる機能ではありません。
SNMPにはベンダーが独自オブジェクトを定義できるエリアがあって、そこには実行中のジョブに関する情報や、過去ログのような情報があります。
プリンターのオペパネルとかプリンター自身が提供するWebページで、ジョブの状態を見ることができると思うのですが、それをSNMP経由で取得できると思ってもらえば良いです。
印刷した文書がこの情報のどれなのかをひもづけることがでれば、印刷済みページ数も取得できるということです。
ベンダー固有オブジェクトの詳細は、ベンダーから直接情報をもらっているので、ここで公開することはできませんが、どんな情報が取得できるのか気になった人は、snmp walkなどでオブジェクトをダンプして見ると面白いかもしれません。
また、最近はどんな情報でもネットに転がってたりするので、ベンダー固有のオブジェクトもどこかで公開されているかもしれません。
また、今はもう対応プリンターが売られていませんが、たとえプリンターの電源を落としたとしても印刷済みページ数を正確に取得できるという機能もRDEにはありました。これはプリンター側も気合を入れて作ったはずなのですが、売れなかったんですかね。ここまでの高機能は不要だったのか。
あとは、ページ数=出力された紙の枚数なのか?という話もあります。両面印刷だったり、複数ページを縮小して1ページに印刷したらどうなるのかなど、考えることはいろいろありますし、取得できる情報もベンダー毎に異なるので、仕様を考えるだけで大変です。
ポートモニターその後
フィルターのように動作するポートモニターを作った話をしましたが、実はその後、ちゃんとデータ送信まで行うポートモニターに進化しています。
中断処理とかを考えると全部自前で用意した方が楽だといういことになって、結局はLPRとかRAWとか印刷プロトコルも作ることになりました。
これが後々SVF本体にも流用されて、自前のスプーラーを持つようになりました。
最後に
現在でも「どこまで印刷できたか知りたい」という要望はあると思いますが、紙への印刷が減っていく状況だと新たなプロトコルを追加するとか、印刷済みページ数の取得方法に関して標準化されるとか、そういうことはもうないのではないかと思います。
この記事が気に入ったらサポートをしてみませんか?