引数のこと
プログラムの起動時に引数を取り、それによってプログラムの挙動を変えることができると、ひとつのプログラムをリコンパイルせずに複数の処理をするプログラムにすることができたり、あるいは起動後にデータをいちいち指定しなくても、あらかじめデータを読み込むことができたり、なにかと小回りが利くようになる。コマンドラインのプログラムだけでなく、FormやWPFでも同様だと思う。
たとえば、テキストビューアーが引数でファイル名をとれれば、データアイコンをexeアイコンにドラッグするだけで、異なるテキストを読むことができる。拡張子次第では、データファイルをダブルクリックするだけでもよい。
経路案内のソフトなら、引数に「銀座 新宿」としてそのそれぞれを出発点と到着点としてとれば、起動してから出発点と到着点を指定しなくてもよくなる。
プログラムに条件を渡す方法は、引数以外にもいろいろな方法があるけれど、引数はもっとも手軽なもののひとつだ。
引数を処理する場所はすくなくとも4つある。
ひとつめは、Main関数。Field。WPF/Formの場合、3つめはコンストラクタ。4つめはLoad時。5つめはコンストラクタかロードで指定したタイマーで。6つめは同様にバックグラウンド処理をして、というものだ。
実行の順番は、Main-Field-コンストラクタ-ロード-タイマーorバックグラウンドとなる。早めに実行したほうがよいかというと、必ずしもそういうわけでもない。というのは、Main関数と、WPF/Formではそもそもクラスが異なるため、Main関数で受けとった引数をWPF/Formで使うにはもう一度引数として渡す必要があるので手間がかかるし、そもそもWPFではMain関数を見つけるのがむずかしいので、Main関数で引数を受けとるという処理じたいを書きにくい。
using System;
using System.Windows.Forms;
namespace agentMail {
static class Program {
[STAThread]
static void Main(string[] args) {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
static void Main() {
を
static void Main(string[] args) {
とすれば、Mainで引数を取得できる。
using System;
using System.IO;
using System.Text;
using System.Windows;
namespace ToDoManager {
public partial class MainWindow : Window {
string[] args = Environment.GetCommandLineArgs();
string FilePath = "";
public MainWindow() {
InitializeComponent();
if (1<args.Length)
FilePath = string.Join(" ", args, 1, args.Length - 1).Trim();
}
}
}
こちらはWPFの場合。Fieldで取得して、コンストラクタでなかみの処理を書いている。
処理の場所
コンストラクタで処理するか、Loadで処理するかは、好き好きだ。処理にすこし時間がかかる場合、コンストラクタで処理すると、ウィンドウが出るまで待たされる。Loadedの場合は、ウィンドウは開くが、なかを描画しないで待たされる。どちらが待たされる感じがあるかというのは個人の感覚なので、なんともいえない。
待ち時間が長くなる場合には、コンストラクタかLoadedでタイマーやバックグラウンド処理をする。その場合、UIである画面と、タイマーやバックグラウンドでは、Threadが異なる場合があって、直接アクセスできなくなるので注意が必要だ。コード的にもやや複雑になり、扱いにくさは微増する。
Loaded
Loadedでなければならないことのひとつは、たとえば引数でウィンドウの位置やサイズを指定して処理するような場合だ。そもそもLoadedしないかぎり画面にはウィンドウが存在しないので、ウィンドウの位置に応じた処理を書くようなことはできない。
コンストラクタで引数を処理して、さらにClose();で終了するのも、Loadedがあると問題になる。コンストラクタで終了したあとにLoadすると、ウィンドウがそもそも存在しない(終了している)ので、オブジェクトが見つからないとnullのエラーになるのだ。
もうひとつ。Main関数で取得する場合、args[0]にはひとつめの引数が入る。いっぽう、System.Environment.GetCommandLineArgs()の場合は、引数のひとつめはexeファイル自身のフルパスである。引数はargs[1]からだ。
fullpath
自身のフルパスをとれるということは、ひとつのプログラムの名前を変えて別の動作をすることができる、ということである。たとえばfputとfgetのように。自分自身を引数とできることでバリエーションが広がるのである。
option
もうひとつ考えたいことは、引数でオプションなどを指定する場合に、そのオプションの先頭文字をどうするかである。よくあるのは、「/」、「-」、「--」などだ。すべてに対応してしまう、という方法もある。
pathに空白を使用できるので、引数の区切り文字が空白とは限らないことも対応が必要な項目のひとつである。
いろいろ考えるところはあるが、引数で容易に挙動を変えることができるので、ぜひ対応したいものである。