Windowsでのコマンドラインの解釈 ことのおこりは、私のフリーソフト「WAVREC Version 0.02」について、岩本一樹 さんからメールにてバグレポートをいただいたことです。具体的には「スペースを 含むロングファイル名があると、関連付けが、うまく動作しない」という点でした。 早速、BC++4.0での、WimMainの第三引数szCmdLineの内容を調べてみましたら、 "C:\PROGRAM FILES\WAVREC.EXE" C:\WIN95J\MEDIA\THE MICROSOFT SOUND.WAV のようになっていました。ここで注意すべきは、コマンド名の部分には、ダブルク ォーテーションマークが付いているのに、パラメータの部分には付いていないとい うことです。これではどうしようもないではないか?と思ったのですが、この状態 でも正常動作しているアプリもあるわけです。 (追記:BC++4.0では上の通りですが、最近の32ビットコンパイラでは、そもそも WinMainの第三引数にはコマンド名は含まれないようです。なおこのBC++4.0の WinMainの第三引数は、GetCommandLine()の戻り値と同じ内容になります。) インストーラでインストールされる、一部のアプリは、関連付け自体が C:\WIN95J\PLAY32.EXE "%1" のようになっています。(これは私のマシンでのquicktime movieの設定)しかし、 サウンドレコーダー、メディアプレーヤー等、Windows95標準アクセサリは、そうな っていませんし、ユーザーが自分で関連付けを変更した場合も、「参照」ボタンで 実行ファイルを選ぶだけでは、自動でそのようになるわけではありません。しかし サウンドレコーダーは正常動作するわけです。これはなぜか? 結論。サウンドレコーダー等は、スペースをパラメータのデリミタとしては取り扱 っていないことになります。自分なりに考えた仕様としては、 (1)argv[0]にあたる、コマンドパスの部分を切り出す時のみは、スペースをデリミ タとする。それ以外は、スペースを一般文字として扱う。 (2)スラッシュ'/'は、常にデリミタである。 (3)ただし、ダブルクォーテーションマークの「内部」では、スペースもスラッシュ も、デリミタとしての機能を失う。ダブルクォーテーションマーク自体は、削除 される。 (4)ダブルクォーテーションマーク自体をパラメータに含ませたい場合は、直前に円 マーク'\'をつける。(2バイト文字に注意) (5)切りだした後、各パラメータごとに先頭および末尾のスペースは削除する(ダブル クォーテーションでくくられていない場合のみ) (6)パラメータの先頭がスラッシュである場合、そのパラメータの末尾のデリミタ としてはスペースも認める というものです。ファイル名自体にダブルクォーテーションマークやスラッシュが 含まれることはありえないし、フルパスの先頭や末尾にスペースがつくこともあり えないので、この仕様で特に問題はないと思います。 ただし、この仕様では、複数のファイル名をパラメータで渡す時に困ることになり ます。 COMMANDNAME /I INPUT FILE /O OUTPUT FILE のようなやり方なら使えますが、 COMMANDNAME "INPUT FILE" "OUTPUT FILE" とやっても、二つのパラメータが渡されたとはみなしません。 (サウンドレコーター等は、「ファイル名は高々一個しか渡されない」というのを 前提にしているらしい。) この仕様をもとに作ったのが、以下のソースです。ロングファイル名自体は32ビッ トでしか使えませんが、ソースは16ビットでも同じ仕様で使えるようになっていま す。 /*グローバル変数*/ #define ARGCMAX 16 int argc; char *argv[ARGCMAX]; /************************************************************************* コマンドライン分割処理 *************************************************************************/ #ifdef WIN32 #define _fnthctype nthctype #endif void qu_strncpy(char *dst, char far *src, int n){ int i, j; for (; n>0; ){ if (src[n-1]!=' ')break; n--; } for(i=0,j=0; i=ARGCMAX-1) break; do{ p=i;i++; }while (CmdLin[p]==' '); }else i++; } argc++; } nthctype()は、最近のコンパイラでは_mbsbtype()等に置き換える必要があると思い ます。もし、見落としなどありましたら、指摘してください。また、上記のソース は、そっくりそのまま流用することを許可します。私の名前や引用元をドキュメン トに記す必要はありません。(つまり完全にパブリックドメインにします) 呼び出し側は、16ビットならWinMain()の第三引数をそのまま渡します。32ビットだ と、WinMainの引数がコンパイラによって異なるので、GetCommandLine()の戻り値を 渡してください。 最後になりましたが、岩本一樹さんには、本当にお世話になりました。この場を借り て御礼申し上げます。 ブラウザの「戻る」ボタンで戻ってください。