- PR -

(C#)AcrobatReaderを使って印刷した結果が成功か失敗かを取得したい

投稿者投稿内容
EarlyHero
常連さん
会議室デビュー日: 2007/03/16
投稿数: 37
お住まい・勤務地: 福岡県
投稿日時: 2007-03-20 15:17
AcrobatReaderで印刷する際にエラーメッセージが表示された場合、
howfarさんのご意見から
1.対応のAcrobat Readerプロセスのdialogのhandleを取って
2.dialogのメッセージを読み取って、メッセージを分析する
関連してるAPIは、「FindWindow」や「GetWindowText」など、…

を実行してみようと頑張っています。
GetWindowTextだと指定されたウィンドウのタイトルをコピーするだけだったので、
GetDlgItemText(ダイアログ ボックス内のコントロールに関連付けられている
タイトルまたはテキストを取得)を使えば、もしかするとうまくいくのでは
ないかと思っています。

しかし、Webで検索したところ、定義(?)は

[DllImport("user32.dll")]
private static extern int GetDlgItemText(IntPtr hDlg, int nIDDlgItem, StringBuilder lpString, int nMaxCount);

というように記載されていたのですが、
第1引数と第2引数に何をセットすればよいのかがわかりません。

第3引数には、以下の「sb」、第4引数にはsb.Capacityをセットしています。
StringBuilder sb = new StringBuilder(100);

推測すると第1引数には、AcrobatReaderのプロセスのHandleか、
AcrobatReaderのプロセスのMainWindowHandle なのかなと思っています。

第2引数にはAcrobatReaderのダイアログのIDなんだろうなと思うのですが、
やっぱりよくわかりません。

現状、AcrobatReaderのダイアログからエラーメッセージが取得できていません。
もし、GetDlgItemTextの使い方や引数についてご存知の方がいらっしゃったら
教えてください。
よろしくお願いいたします。

[追記]
GetDlgItem:指定されたダイアログ ボックス内のコントロールへのハンドルを取得。
GetDlgCtrlID:指定されたコントロールの識別子を取得。

[DllImport("user32.dll")]
private static extern IntPtr GetDlgItem(IntPtr hWnd, int nIDDlgItem);

[DllImport("user32.dll")]
private static extern int GetDlgCtrlID(IntPtr hWnd);

というのがあったのですが、もしかすると
GetDlgCtrlID → AcrobatReaderのダイアログのIDを取得 (第2引数?)
GetDlgItem → AcrobatReaderのダイアログのHandleを取得 (第1引数?)
になるのでしょうか?
このときのGetDlgCtrlIDの hWnd がAcrobatReaderのプロセスのHandleなのでしょうか?

もうちょっと調べてみます。
もしご存知の方がいらっしゃったらお気軽にご意見ください。
よろしくお願いいたします。


[ メッセージ編集済み 編集者: EarlyHero 編集日時 2007-03-20 15:27 ]
EarlyHero
常連さん
会議室デビュー日: 2007/03/16
投稿数: 37
お住まい・勤務地: 福岡県
投稿日時: 2007-03-20 15:44
以下の方法でHandleやIDを取得しようとしたのですが
やっぱりできませんでした。

// AcrobatReaderのHandleを取得
IntPtr hwnt = p.Handle;

// ダイアログのIDを取得(?)
int id = GetDlgCtrlID(hwnt);

// ダイアログのHandleを取得(?)
IntPtr hwntdlg = GetDlgItem(hwnt, id);

// ダイアログのメッセージ取得用
StringBuilder sb = new StringBuilder(100);

// ダイアログのメッセージ取得
int check = GetDlgItemText(hwntdlg, id, sb, sb.Capacity);

上記でできるかもと思ったのですが、やっぱりできませんでした。

ちなみに、id および hwntdlg は0でした。(取得できていないのかも)
checkは0(取得失敗)でsbも空のままでしたのでうまくいっていません。

何か間違っている箇所があればご意見いただけますでしょうか?
よろしくお願いいたします。

[ メッセージ編集済み 編集者: EarlyHero 編集日時 2007-03-20 15:45 ]
howfar
会議室デビュー日: 2007/03/16
投稿数: 14
投稿日時: 2007-03-20 19:07
EarlyHeroさん:
すみません、前回の返事にはちょっと違いところがあるので、すみません。
「hanld」を取るように、「FindWindow」を使って、「FindWindow」の戻る値は探したいwindowのhanldです。

ーーーーーーーーーーーーーーーーーーーーーーーー

しかし、Webで検索したところ、定義(?)は

[DllImport("user32.dll")]
private static extern int GetDlgItemText(IntPtr hDlg, int nIDDlgItem, StringBuilder lpString, int nMaxCount);
ーーーーーーーーーーーーーーーーーーーーーーーー
そうです、msdnに探す定義はvcの用です、だから、もしも.netに使いたかったら、上記の定義を使わなければならないです。
ーーーーーーーーーーーーーーーーーーーーーーーーーーー
GetDlgItemTextについて

もしAcrobatReaderのhandleを取ったら、このfunctionを使うことができます、今簡単に説明してあげます。

ーーーーーーーーーー
[DllImport("user32.dll")]
private static extern int GetDlgItemText(IntPtr hDlg, int nIDDlgItem, StringBuilder lpString, int nMaxCount);

第一引数「hDlg」は「FindWindow」の戻る値です
第二引数「nIDDlgItem」は取りたいメッセージのコントロールのhandle
第三引数「lpString」は取るメッセージの変数(保存するようです)
第四引数「nMaxCount」はメッセージの桁数である。

第二引数のhandleを取り方法はちょっと忘れました、「DEMO」を作りたいですけど、今出勤中なので[ide]が無いですけど、本当にすみません。

下記のサイトには助ける資料があります。
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfunctions/getwindowtext.asp

ーーーーーーーーーーーーーーーーーーーーーー
FindWindowについて

.netには定義はウェブで調べてください、

第一引数lpClassNameはnullでもいい。
第二引数lpWindowNameはwindowのtitleです。

以上です
残業中T_T
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-03-21 00:29
 誰も AdobeReader の“印刷ダイアログ”を監視しろなんて書いてないと思いますよ?
AdobeReader がやりとりしているメッセージを監視、ってのはありますが。

 んで、howfarさんのは、「プリンタタスクの監視」で、これも印刷ダイアログの監視ではありません。

 ちゃっぴさんの方法で、AdobeReader が残るのは、リリースしていないから。これは、「Excel プロセスが残る」で検索すると、対応方法が見つかります。


 それと、なぜしたいのか。これがあると、あるいは別の、もっと簡単な方法で実現する方法を提示できるかもしれません。


あと、プライベートメッセージで質問されるのは嫌い。
_________________
howfar
会議室デビュー日: 2007/03/16
投稿数: 14
投稿日時: 2007-03-21 01:32
引用:

Jittaさんの書き込み (2007-03-21 00:29) より:
 誰も AdobeReader の“印刷ダイアログ”を監視しろなんて書いてないと思いますよ?
AdobeReader がやりとりしているメッセージを監視、ってのはありますが。

 んで、howfarさんのは、「プリンタタスクの監視」で、これも印刷ダイアログの監視ではありません。

 ちゃっぴさんの方法で、AdobeReader が残るのは、リリースしていないから。これは、「Excel プロセスが残る」で検索すると、対応方法が見つかります。


 それと、なぜしたいのか。これがあると、あるいは別の、もっと簡単な方法で実現する方法を提示できるかもしれません。


あと、プライベートメッセージで質問されるのは嫌い。




印刷失敗の場合は、メッセージが出るので、だから「印刷ダイアログを監視する」という方法ができるかもしれないと思います。

Jittaさんは「あと、プライベートメッセージで質問されるのは嫌い。」ということを言いましたが、Jittaさんは「気持ちが悪い」という感じが持てると思いますが、私は何か失礼なことがあると思います。私は今とても不安です。わたしは日本語を勉強していますから、日本語が下手ですので、そして皆さんの意味を誤解する可能性があるので、もし何か失礼なことがあったら、お許しになってください。

_________________
私は今日本語をべんきょうしていますが、だから日本語がうまくないですから、もし違うところがあったら、ご指導ください^_^
howfar.jp@gmail.com

[ メッセージ編集済み 編集者: howfar 編集日時 2007-03-21 01:33 ]
未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2007-03-21 10:44
引用:
howfarさんのは、「プリンタタスクの監視」で、これも印刷ダイアログの監視ではありません。


howfar さんがプリンタタスクの監視の話を出してきたのは後半ですよ。はじめは「dialogのhandleを取って」とか「FindWindow」「GetWindowText」などのキーワードを出して、現在の EarlyHero さんの取り組みの方向性を示唆していました。これでは、EarlyHero さんが GetDlgItemText に辿り着いてしまうのは仕方がないと思います。(よくあれだけのキーワードで GetDlgItemText まで辿り着いたものだと感心もしています。)

もっと筋の良い方法があると思うのなら、もうちょっと適切なキーワードとともにヒントをお出しになったらどうですか? 「Spy++ みたいなことをします。」なんていじわるな言い方をせずに「グローバルフックで他のプロセスのメッセージを受け取ることができます。」「グローバルフックを作成するために SetWindowsHookEx() API を使用します。」くらい教えてあげたらいいのに。

私は .NET のことは良く知らないので Win32 API でのお話しかできませんけど・・・。

・メッセージを読むなら SetWindowsHookEx()
・印刷ジョブを読むなら FindFirstPrinterChangeNotification()

で検索すれば芋づる式で関連情報が出てくるのではないかと思います。ただ、メッセージにしても印刷ジョブにしても Acrobat Reader に関連するものだけを正確に特定する方法があるかどうかまでは分かりません。

[追記]
誤字訂正
[/追記]

[ メッセージ編集済み 編集者: 未記入 編集日時 2007-03-21 11:01 ]
ひでっち
会議室デビュー日: 2007/03/21
投稿数: 1
投稿日時: 2007-03-21 11:13
そもそも ShellExecute() の "print"  ではダメなのですか?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-03-21 18:42
ここの掲示板の機能で、直接メッセージを送る機能があります。
この機能を使って、回答してくれ、という趣旨のメッセージが送られてきています。

他の人で、質問を直接送ってきた人がいましたが、そのときは丸ごとここに転写して、回答しました。

こういう、直接質問を送ってこられるのは嫌いです。
eメールも同じ。ただし、ブログやサイトのことでの質問は別。こういうのは、逆にeメールなりブログのコメント、トラックバックでするのが本筋だと思っている。


> 「Spy++ みたいなことをします。」なんていじわるな言い方をせずに
 howfarさんの 2007-03-16 17:01 に対して 2007-03-16 17:20 で疑問を出されていますが、これへの返答でした。
 私は反対に、Win32 API 関係はほとんど知らないので、こういう答え方しかできませんでした。意地悪ではなく、知っている限りです。

> もうちょっと適切なキーワードとともにヒントをお出しになったらどうですか?
 はい、出しています。
引用:

acrobat の sdk が、アドビのページに有ったと思いますが、それには目を通しましたか?

基本的に他のアプリケーションなので、公開されていない情報を採ることは出来ません。盗ることは、出来るかもしれませんが。

 先にも書きましたが、公開していない情報を採取することは出来ません。その辺は、SDKのドキュメントに書いてあるはずです、公開しているのですから。

 公開されていない情報を盗るとなると(漢字使い分けているのに注意してね)、相応の知識が必要です。また、バージョンが変わると通用しない可能性もあります。

 で、どこまでしなければならないかは、予算と相談となります。その辺はどうですか?


私は、これが最適な回答だと思っています。特に、最後の行。


引用:

印刷失敗の場合は、メッセージが出るので、だから「印刷ダイアログを監視する」という方法ができるかもしれないと思います。


表示されるすべてのダイアログを監視するのであれば、それも有効だと思います。しかし、特定のアプリケーションの「印刷ダイアログ」だけを監視しても、有効ではないと思います。

 たとえば、私が関わっている製品で、「セキュア プリント」というものがあります。PC とプリンタに生体認証装置をつけ、プリンタ側で入力した生体情報に一致する生体情報を送った PC からの印刷を行う、というものです。これの場合、アプリケーションは印刷成功を返します。しかし、生体認証を行わなければ、一定時間後にデータは消えます。当然、エラーは認証アプリケーションから表示されるので、AdobeReader を監視していてもわかりません。
 こういうことをやっているので、特定のアプリケーションの印刷ダイアログを監視するのは、無駄であると思います。

 こんな装置がどこにでもあるわけではありませんが、ポートモニタの開発に関わっているので、やはり無駄だと判断します。少なくとも、私が関わっている製品では、アプリケーションが成功を返しても、ポートモニタが失敗を返すことがあります。


 そもそも、アプリケーションが成功/失敗を関知できるでしょうか?もし検知できるなら、なぜ、「テスト印刷」は自分で検知せず、ユーザに成功/失敗を入力してもらうのでしょう?
 「失敗」の状態が様々あるわけです。プリンタへのデータ転送が成功しても、プリンタがジャムを起こしているかもしれません。プリンタ側のスプールへ転送は成功したけれど、印刷途中で電源を切られるかもしれません。これらもみな「失敗」です。

 じゃぁ、スプーラへ尋ねればよいか。それも、確定的ではありません。スプーラを使用しない設定になっていれば、スプーラに尋ねることも出来ません。


 そんなわけで、私はほとんどのこころみが無駄だと思っています。なので、
●どこまで検知するのかを明らかにすること
●どこまでコストをかけられるのかを明らかにすること
●SDK で提供されている情報で満足すること
を勧めます。
_________________

スキルアップ/キャリアアップ(JOB@IT)