2009年3月17日火曜日

.NET OpenFileDialogやSaveFileDialogでカレントディレクトリが変更される事がある

OpenFileDialogやSaveFileDialogでカレントディレクトリが変更される事があります。
かなり有名な問題なのですが、いつも忘れてしまうのでメモしておきます。

ちなみにこの問題はVISTAでは発生しません。XPでは発生します。

現象を確認するため以下のコードをXPで実行します。
1回目のCurrentDirectoryは実行パスのディレクトリが返ります。
2回目のCurrentDirectoryはOpenFileDialogで指定した保存先パスのディレクトリが返ります。
'現在のカレントディレクトリ
Console.WriteLine(System.IO.Directory.GetCurrentDirectory)

'ファイルを開くダイアログ
Dim path As String = String.Empty
Using dialog As New OpenFileDialog
If dialog.ShowDialog = Windows.Forms.DialogResult.OK Then
path = dialog.FileName
End If
End Using

'現在のカレントディレクトリ
Console.WriteLine(System.IO.Directory.GetCurrentDirectory)


たとえば、このような現象で問題になるのは以下のようなコードがあります。
Dim asbl As System.Reflection.Assembly
asbl = System.Reflection.Assembly.LoadFrom("ClassLibrary.dll")

相対パスでアセンブリをロードしているのですが、通常はカレントディレクトリが実行パスのディレクトリであるため
実行パスのディレクトリからClassLibrary.dllを探します。
しかしOpenFileDialogやSaveFileDialogを使用した後、カレントディレクトリが保存先のディレクトリに変更されるため
保存先のディレクトリからClassLibrary.dllを探し、ClassLibrary.dllが見つからないのでエラーになります。



この問題を回避するため、OpenFileDialogやSaveFileDialogではRestoreDirectoryプロパティをTrueに設定するようにします。
RestoreDirectoryプロパティはダイアログ ボックスを閉じる前に、現在のディレクトリを復元するかどうかを示す値を取得または設定します。
デフォルトはFalseです。
'現在のカレントディレクトリ
Console.WriteLine(System.IO.Directory.GetCurrentDirectory)

'ファイルを開くダイアログ
Dim path As String = String.Empty
Using dialog As New OpenFileDialog
dialog.RestoreDirectory = True
If dialog.ShowDialog = Windows.Forms.DialogResult.OK Then
path = dialog.FileName
End If
End Using

'現在のカレントディレクトリ
Console.WriteLine(System.IO.Directory.GetCurrentDirectory)



一応このプロパティを設定することで問題は起きないはずです。
しかし、そもそもの原因はカレントディレクトリが実行パスのディレクトリだという事を前提にしたプログラムが一番の問題なのだと思います。
実行パスのディレクトリからClassLibrary.dllを探したいのなら、Application.StartupPathを指定しましょう。
Dim asblNm As String = System.IO.Path.Combine(Application.StartupPath, "ClassLibrary.dll")
Dim asbl As System.Reflection.Assembly
asbl = System.Reflection.Assembly.LoadFrom(asblNm)

0 件のコメント: