• ベストアンサー

実行ファイルのパスを取得したい

C言語で自分自身がどのディレクトリに存在しているか 知りたいのです。 簡単に例を挙げて説明します。 UNIX C言語で cmd1 という実行ファイルを作成しました。 環境変数は以下のように定義されていたとします。 PATH=/bin:/usr/bin /binにcmd1を配置してカレントディレクトリ/homeにおいて cmd1を実行、cmd1プログラム内で"/bin/cmd1" を取得したいのです。 続けて、/bin/cmd1を/usr/bin/cmd1移動して、cmd1を実行すれば、 プログラム内で"/usr/bin/cmd1"を取得できるコーディングをしたいのです。 typeコマンドのような事をC言語で行いたいのですが。 お分かりの方いらっしゃいましたら教えてください。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.7

>C:\WINDOWS\COMMAND\CMD1.EXE >と表示されます。 >この違いはなんだろう? C:\windows\commandってフォルダに突っ込んでる時点でOSがぜんぜん違いますよね。 Win9xとNT系じゃ。 9x系はフルパスが、NT系は起動時の実行コマンドargv[0]には格納されています。 UNIXでは実行モジュールのフルパスを取得する一般的な方法は無いみたいです。 Windowsでは#4の方の書かれているとおり、GetModuleFileName()です。

yukooo
質問者

お礼

「UNIXでは実行モジュールのフルパスを取得する一般的な方法は無いみたいです」 そうですか。 こちらに質問を書き込む前に私なりに調べてみました。 もしかして出来ないのかなぁ?と少し思いつつ、 そんなはずはないだろう。。。と思い質問した次第です。 回答ありがとうございました。

その他の回答 (7)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.8

うろ覚えの記憶で申し訳ありませんが、TclのAPIであるTcl_FindExecutable関数がプログラムのフルパスを取得できます。 Tclを使えるのであれば、そのまま使っても構いませんし、Tcl_FindExecutable関数を真似て、自作してもよいかと思います。 大まかに言って、次のような方法で実現されていたはずです。 gccでは、コマンドラインで入力されたプログラム名が、そのままargv[0]に格納されます。argv[0]に絶対パスまたは相対パスが指定されていれば(要するに'/'が含まれている場合)、そのディレクトリを元にフルパスを生成します。ファイル名のみ指定されていれば、環境変数PATHに指定されているディレクトリを順に検索して、該当するプログラムが存在するかどうかを調べます。 プログラム起動後に、ファイルが削除されたり、移動されたり、改名される可能性もあるので、100%確実な方法とは言えないでしょうが、普通は問題ないかと思います。高いセキュリティが要求される場合は、やめた方がよいかも知れませんが...

yukooo
質問者

お礼

やはり行き着く先はPATHのディレクトリ探索になりますか。 おしゃられるように起動後のファイル移動等に注意が必要ですね。 回答ありがとうございました。

  • nitscape
  • ベストアンサー率30% (275/909)
回答No.6

#4です。 この掲示板では討論のような個人的なやりとりは禁止されているので書き込むのは悩むところですが、質問者さんが誤解するといけないので... 繰り返しになりますがargやWindowsAPIのGetCommandLineで取得できるのは実行時の「コマンド」になります。そのため実行ファイルに対するフルパスではありません。 しかしargを調べて見ると実行時にフルパスが取得できていることがあります。それは実行時にフルパスを指定して起動した場合です。また実行するときにフルパスを指定していないにもかかわらずフルパスが返ることもあります。これはWindowsAPIのCreateProcessが勝手にフルパスに変換することがあるためです。 具体的にはWindows9x系ではフルパスが返ることが多いようです。WindowsNT4.0/2000/XPの場合はフルパスにならないことが多いです。 また質問は >C言語で自分自身がどのディレクトリに存在しているか ということです。自分自身がどのディレクトリに存在しているかを知るためには自分自身ファイルへのフルパス(例c:\a.exe)を取得して、そこからファイルの部分を除去してディレクトリ(例c:\)に変換します。 しかしargなどで取得できるのは"実行ファイル"のみです。例えば自分自身がDLLファイルなどで実行されていた場合にはDLLをロードしているExeのフルパスが返るだけであり、自分自身へのフルパスを取得することができません。 そのためWindowsでは自分自身のフルパスを取得するにはGetModuleFileNameのようなAPIを利用します。 EXEであれば #include "windows.h" TCHAR pszPath[MAX_PATH]; GetModuleFileName(NULL,pszPath,MAX_PATH); のように利用します。DLLの場合は第一引数をモジュールへのハンドルにします。 UNIXでは。。。すみません。知識がなく分かりません。 argを見てフルパスならそれを利用、そうでなければカレントフォルダを参照する、のような方法が考えられますが、「./aaa/bbb/cmd.exe」のような相対的なパスを示すargが返ってくることも考えられるので気をつける必要があると思います。

yukooo
質問者

お礼

回答ありがとうございます。 「Windows9x系ではフルパスが返ることが多いようです。WindowsNT4.0/2000/XPの場合はフルパスにならないことが多いです」 そうなんだ。と驚いています。 GetModuleFileNameについても丁寧に書いていただきありがとうございます。

  • ty_cobb
  • ベストアンサー率16% (1/6)
回答No.5

>#4殿 話をドリフトさせるのはやめてください。 >Windowsで自分自身のファイルを取得したい場合はGetModuleFileNameを使います。 そんな要求はしていません。 >コマンドプロンプトなどで実行した場合はフルパスになりません。 試したんですか? こちらは書いたとおりのことを試してみて、書き込んでるんですよ。c:\windows\commandに実際にcmd1.exeをコピーし、コマンドプロンプトからc:\へ移動してcmd1とタイプしてごらんなさい。 C:\WINDOWS\COMMAND\CMD1.EXE と表示されますよ。

yukooo
質問者

お礼

回答ありがとうございます。 確かにGetModuleFileNameは期待している回答では ありません。 ですが、UNIXでという質問の意図とは異なりはしますが、 WindowsでもOS違いでargv[0]の値は異なるみたい。 というのは驚きと面白い発見でした。

  • nitscape
  • ベストアンサー率30% (275/909)
回答No.4

argやGetCommandLineは実行時に渡された「コマンド」が返ります。VC++などでは実行時にフルパスで実行するためargでフルパスが返りますが、コマンドプロンプトなどで実行した場合はフルパスになりません。プラットフォームが何なのかにもよりますが、Windowsで自分自身のファイルを取得したい場合はGetModuleFileNameを使います。

yukooo
質問者

お礼

回答ありがとうございます。 VC++で実行した場合とコマンドプロンプトから 実行、さらにプラットフォームの違いによっても argv[0]の値が異なる可能性があるということですね。 勉強になります。

  • ty_cobb
  • ベストアンサー率16% (1/6)
回答No.3

こちらも実際に試してみました。 VC++6.0で、console applicationを作って、cmd1.exeを作成し、c:\windows\commandに入れました。 c:\上から、cmd1とタイプすると、 C:\WINDOWS\COMMAND\CMD1.EXE と表示されます。 この違いはなんだろう? ていうか、argv[0]にフルパスが含まれるのは大分昔からの仕様だと思ってたんだけど・・・。

yukooo
質問者

お礼

WindowsのOS違いで動作が異なるということなんですね。 いろいろ試して頂きありがとうございます。

  • ty_cobb
  • ベストアンサー率16% (1/6)
回答No.2

今unixの環境が手元に無いんだけど、MS-DOSで実行すると argv[0]はフルパスを返します。 "c:\windows\デスクトップ\cmd1.exe"のように。 unixでは"/usr/bin/cmd1"を返さないのでしょうか? "cmd1"のみ?

yukooo
質問者

補足

回答ありがとうございます。 MS-DOSはあまり経験がないのですが今やってみました。 Windows2000です。 cmd1.exeを作成して、PATHの通った場所にコピーしました。 具体的にはC:\WINNT\system32に入れました。 そしてカレントをC:\に移動して実行しました。 C:\>cmd1.exe cmd1.exe cmd1.exeとしか表示されませんでした。 私の説明がまだ不足しているような気がします。 C:\WINNT\system32\cmd1.exe というパスを何らかの方法で簡単に取得できないかと 苦慮しています。 よろしくお願いします。

  • ty_cobb
  • ベストアンサー率16% (1/6)
回答No.1

#include <stdio.h> int main(int argc,char **argv) { printf("%s\n",argv[0]); return 0; }

yukooo
質問者

補足

申訳ありません。説明が不足していたようです。 カレントディレクトリでは、cmd1 としか入力しません。 よろしくお願いします。

関連するQ&A