2011年4月30日土曜日

Adobe Acrobat か Reader の実行ファイルパスをレジストリから取得する

PDFファイルを印刷したいという要望があり、それの補助用メソッドです。

  1. public static string GetPdfViewerPath()  
  2. {  
  3.     string path = String.Empty;  
  4.     Microsoft.Win32.RegistryKey rKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Acrobat.exe");  
  5.     if (rKey == null) rKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\AcroRd32.exe");  
  6.   
  7.     try  
  8.     {  
  9.         // レジストリから読み込み  
  10.         path = rKey.GetValue("").ToString();  
  11.     }  
  12.     catch (System.Security.SecurityException) { throw; } //レジストリキーからの読み取りに必要なアクセス許可がユーザーにありません。  
  13.     catch (System.UnauthorizedAccessException) { throw; } //必要なレジストリ権限がユーザーにありません。  
  14.     //catch (System.ObjectDisposedException) { throw; } //破棄されたキーを参照した場合  
  15.     //catch (System.IO.IOException) { throw; }  
  16.     catch  
  17.     {  
  18.         throw new ApplicationException("AdobeR AcrobatR もしくは ReaderR がインストールされていないため、PDFファイルの印刷ができません。");  
  19.     }  
  20.     finally  
  21.     {  
  22.         rKey.Close();  
  23.         rKey = null;  
  24.     }  
  25.   
  26.     return path;  
  27. }  

途中、try-catchでSystem.ObjectDisposedExceptionとSystem.IO.IOExceptionの捕捉をコメントにしているのは、その2つの例外が発生した場合にもインストールされていないと判断するためです。


以下余談

Adobe Reader単体でコマンド引数を使用して直接印刷をかけるのは止めたほうがいいと個人的には思う。
何故かというと、Adobe Readerに直接PDFファイルのパスを渡して印刷する方法だと、Adobe Reader自体の画面表示させないように設定してもバックグラウンドで動かなかったり、印刷完了しても画面が閉じられずプロセスが残ってしまうことがあるからです。
印刷はできるけどね。

こればかりは何ともいえないところですが、回避策としてとりあえず2点。
1. タイムアウトを指定して、印刷されたであろう時間が経過した後にプロセスをkillする
2. プリンタのキューを監視してプリンタへの印刷指示が完了したことを確認後プロセスをkillする


出来れば、Adobe Acrobat SDKでそれ用のプログラムを作成することをおすすめする。

なんかいい方法ないもんかね。