m2

カレントディレクトリでハマる

以下の記事を参考に、iTextSharp で PDF を作成しようとしてハマりました。

CodeZine:iTextSharpを利用して.NETでPDF帳票を出力する(PDF, .NET, 帳票, 印刷)
http://codezine.jp/a/article.aspx?aid=462

そこに書かれているコードはそのまま動くのだけど、いざ SaveFileDialog で保存ファイルを指定すると動かない。原因を絞り込むとこんな感じ*1

using System;
  :
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace PDFTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            BaseFont.AddToResourceSearch("iTextAsian-1.0.dll");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            SaveFileDialog d = new SaveFileDialog();
            d.ShowDialog(); // ←ファイルを指定すると↓でエラー
            BaseFont.CreateFont("HeiseiMin-W3", "UniJIS-UCS2-H", false); 
        }
    }
}

もう何時間もハマってしまったよ…。


原因は SaveFileDialog でファイルを指定すると、デフォルトではそのファイルのあるディレクトがカレントディレクトリになるため、相対パスで指定している iTextAsian-1.0.dll が見つからなくなるからでした。

これを回避するには FileDialogRestoreDirectorytrue にする、もしくは BaseFont.AddToResourceSearch()絶対パスを指定します(または環境変数 PATH から辿れるところに置く)。
前者だとどこかでカレントディレクトリが変更された時点でアウトなので、私は後者を選びました。こんな感じ。

BaseFont.AddToResourceSearch(Path.Combine(Application.StartupPath, "iTextAsian-1.0.dll"));

それにしてもファイル選択でカレントディレクトリが変わるなんて、Java プログラマは予想もしませんよ*2。なんで RestoreDirectory のデフォルトは false なんだか。

*1:C#スーパーpre記法の指定って「csp」でいいんだろうか?「cs」だったみたい。じゃあ「csp」ってなんだろ? 「Communicating Sequential Processes」とのこと(コメント参照)。

*2:おかげで Assembly.Load とか的外れなことやってた。しかしそれでロードしてもフォントを見つけてくれなかったんだよなあ。