プログラムは動かすときに、さまざまなデータや情報を使います。
プログラムそのものですべての情報を持つことは、1つにまとまる反面、融通が利かなくなったりしてしまいます。
プログラムは、起動したときにいろいろなデータや情報を集めて動作します。
起動パスを取得する理由
プログラムが使う設定ファイルなどのファイルを読み込む処理は、通常下記のような方法で読めるはずです。
StreamReader sr = new StreamReader("settei.txt", Encoding.GetEncoding("Shift_JIS")); string text = sr.ReadToEnd(); sr.Close();
・・・が、この書き方だとファイル”settei.txt”の正確な場所は分かりません。
コードはちょっと手を加えて下記のようにしておきます。
string file_path; file_path = "settei.txt"; if (System.IO.File.Exists(file_path)) { // ファイルが存在したら読む System.IO.StreamReader sr = new System.IO.StreamReader(file_path, Encoding.GetEncoding("Shift_JIS")); string text = sr.ReadToEnd(); sr.Close(); }
この場合、”settei.txt”というファイルを読む場所は「プログラム(exeファイル)があるフォルダ」だけではないんです。
たしかにVisual Studioなどでデバッグしているときは、プログラム(exeファイル)があるフォルダに”settei.txt”を置くとアクセスできます。
ところが、同じVisual Studioでデバッグしていても、プロジェクトのプロパティにある「作業ディレクトリ」のパスを変えると「プログラム(exeファイル)があるフォルダ」に”settei.txt”があってもファイルにはアクセスできません。
ただ、この「作業ディレクトリ」は、ショートカットなどでも設定ができるのでプログラムを他の人にも変えることが可能です。
だからといって「作業ディレクトリ」を使うのが悪いということではありません(デバッグを行うときなどには、便利です)。
ちなみに「作業ディレクトリ」は下記のようにして取得できます。
string s = System.Environment.CurrentDirectory;
プログラムは、どこで起動しているか
実は、プログラム自身がどこで起動しているかも調べなければ判りません。
Windowsフォームアプリケーションであれば、”System.Windows.Forms.Application.StartupPath”プロパティで取得することができます。
コンソールアプリケーションの場合、”System.Windows.Forms”は参照されていません。
(“System.Windows.Forms”を参照してもよいのですが、”System.Windows.Forms”は、Windowsのフォームなどのクラスを持つもので、コンソールアプリケーションでは通常”Windowsフォーム”は使わないので、あまりお勧めできません)
“System.Windows.Forms.Application.StartupPath”プロパティを使わずに起動パスを知る方法
“System.Windows.Forms.Application.StartupPath”プロパティを使わずに自分の起動パスを知る方法は大きく2つ方法があり
- System.Environment.CommandLineプロパティを使う方法
- System.Reflection.Assemblyクラスを使う方法
があります。
System.Environment.CommandLineプロパティを使う方法
「System.Environment.CommandLineプロパティ」はプログラムを起動するときに使用する「コマンドライン」の文字列から起動パスを取得する方法です。
「コマンドライン」はプログラムを実行する限りは必ず使用されるものです。
System.Environment.CommandLineプロパティを使う方法の例は下記の通りです。
static void Main(string[] args) { // System.Environment.CommandLineで起動パスを取得 string s = System.Environment.CommandLine; System.IO.FileInfo fi = new System.IO.FileInfo(s.Replace("\"", "")); string startup_path = fi.Directory.FullName; string file_path; file_path = System.IO.Path.Combine(startup_path, "settei.txt"); if (System.IO.File.Exists(file_path)) { // ファイルが存在する場合はファイルの中身を読み込む System.IO.StreamReader sr = new System.IO.StreamReader(file_path, Encoding.GetEncoding("Shift_JIS")); string text = sr.ReadToEnd(); sr.Close(); } }
System.Reflection.Assemblyクラスを使う方法
System.Reflection.Assemblyクラスといってもその中の「現在実行しているアセンブリ(=いま実行している自分のプログラム)」の情報から起動パスを取得する方法です。
static void Main(string[] args) { // System.Reflection.Assemblyで起動パスを取得 string s = System.Reflection.Assembly.GetExecutingAssembly().Location; System.IO.FileInfo fi = new System.IO.FileInfo(s); string startup_path = fi.Directory.FullName; string file_path; file_path = System.IO.Path.Combine(startup_path, "settei.txt"); if (System.IO.File.Exists(file_path)) { // ファイルが存在する場合はファイルの中身を読み込む System.IO.StreamReader sr = new System.IO.StreamReader(file_path, Encoding.GetEncoding("Shift_JIS")); string text = sr.ReadToEnd(); sr.Close(); } }
この2つの方法ですが、どちらを使っても得られる結果は同じです。
また、ソースコードも非常によく似たものになっていますが、1つだけ大きな違いがあります。
それは、System.Environment.CommandLineプロパティで取得したコマンドラインは、’”’(ダブルクオーテーション)で括られているので、そこから起動パスとするにはこの「ダブルクオーテーションを取り除く」という処理が必要になります。