エクセルのCOMアドインからヘルプを開きたい

エクセルのアドインをC#で作っていて、ヘルプをワードで書いてPDFで保存して用意したのだけど、アドインをセットアップしたときに、PDFファイルがどこに保存されているのかわからないので、PDFファイルを開けない。




なんとも間の抜けた話だが、アドインのセットアップを「発行」つまりClickOnceで実行しているので、いつもと様子が違うのだ。

普通のセットアップだとインストールしたファイルは Programe Files フォルダの下にはいるのだが、ClickOnceだと、どこにはいるのだろう?

そもそもPDFファイルはインストールできるのか


アドインの「発行」ではインストールするファイルを選択することができない。PDFファイルをそもそもインストールすることができるのか。

これは、プロジェクトにPDFファイルを追加して、プロパティを「コンテンツ」にすればOKだった。

発行先のフォルダの「Application Files\ExcelAddin_X_X_X_XXX」フォルダの下を見れば、PDFファイルらしきものが含まれているのがわかる。

ということで、あとはPDFファイルのインストール先のパスがわかれば、ファイルを開けるわけだ。

アドインのDLLの実行パスを調べる

アドインはDLLなので実行中のパスを調べれば、どこで動いているのかはわかるはず。コードを書いてみる。

  1. using System.Reflection;
  2.  
  3. Assembly asm = Assembly.GetExecutingAssembly();
  4. string p1 = asm.Location;

その結果、以下のようなフォルダ名がゲットできた。

C:\Users\XXX\AppData\Local\assembly\dl3\R1NMCHXM.3BO\W1777BQJ.9YD\42693b50\cc850222_7ca7d201

なにこれ?

フォルダを見ると、DLLといっしょに .ini ファイルもある。開いてみると、パスが書いてあった。

全角で書いてあるように見えるが、半角英字で間に空白が挟まっている。これはユニコードだね。中に「file:///」で始まるパスがあるので、そこを開いてみたいが、まずはきちんとしたパスにしないと開きようがない。

ということで、コードを書いてみる。

  1.           string p2 = System.IO.Path.GetDirectoryName(p1) + "\\" + "__AssemblyInfo__.ini";
  2.           if (System.IO.File.Exists(p2))
  3.           {
  4.               System.IO.StreamReader rd = new System.IO.StreamReader(p2, Encoding.Unicode);
  5.               refPath = rd.ReadLine();
  6.               rd.Close();
  7.           }
  8.           int n = refPath.IndexOf("file:///");
  9.           if (n > 0)
  10.           {
  11.               refPath = refPath.Substring(n, refPath.Length - n - 1);
  12.               refPath = refPath.Replace("file:///", "").Replace("/", "\\");
  13.               refPath = System.IO.Path.GetDirectoryName(refPath);
  14.           }

エンコードをユニコードで指定して読み込んで、「file:///」で始まるパスを、ローカルパスに書き換えている。べたべたですな。

ゲットできたパスが下記の通り。意味不明。

C:\Users\XXX\AppData\Local\Apps\2.0\BRBX20N6.35Q\0JQ5A65E.MG1\mm60..vsto_3aba3d5660836e46_0006.0000_e62396caed0d6103

中を見ると、PDFファイルがある。


これで目的は達成できそう。

もっとセンスの良い解決手順

アセンブラ情報にはCodeBaseプロパティがあって、そこにインストール先フォルダのパスがあるらしい。しかも「file:///」はUrlクラスを使えば、簡単にローカルパスの形式に変換してくれる。文字列探して切り出して、、、なんてコードを書いていたのが、本当に悲しい。

  1.         /// アドインの参照ファイルがインストールされるフォルダのパスを得る
  2.         /// </summary>
  3.         /// <returns></returns>
  4.         string getAddinInstallFolderPath()
  5.         {
  6.             try
  7.             {
  8.                 Assembly asm = Assembly.GetExecutingAssembly();
  9.                 Uri uri = new Uri(asm.CodeBase);
  10.                 string p = System.IO.Path.GetDirectoryName(uri.LocalPath);
  11.                 return p;
  12.             }
  13.             catch (Exception)
  14.             {
  15.                 return "";
  16.             }
  17.         }




コメント

このブログの人気の投稿

varchar をデータ型 numeric に変換中に、算術オーバーフロー エラーが発生しました。