简体   繁体   English

如何使用独立于平台的方法在C中获取执行程序的目录?

[英]How do I get the executing program's directory in C using a plataform independent method?

I develop my app in Linux for both unix and win32(cross compile at each build) platforms, so a ready to use function would be nice :). 我在Linux中为unix和win32(在每个构建时交叉编译)平台开发我的应用程序,所以一个随时可用的函数会很好:)。 I'm using glib that has the gchar* g_get_current_dir(void) function and it returns the current directory, but what I really need is the executable's directory. 我正在使用具有gchar* g_get_current_dir(void)函数的glib,它返回当前目录,但我真正需要的是可执行文件的目录。 I'm inexperienced in C programming so any suggestions are welcome. 我对C编程缺乏经验,所以欢迎任何建议。

GetModuleFileName in Windows. Windows中的GetModuleFileName argv[0] in linux linux中的argv [0]

NOTE: If you do cross-platform programming you should use also some cross platform libraries that hide this layer (Qt, wxWidgets, ACE, Boost[Don't know but I think it has something] ... ) 注意:如果你进行跨平台编程,你也应该使用一些隐藏这一层的跨平台库(Qt,wxWidgets,ACE,Boost [不知道,但我认为它有一些东西] ...)

Under Unix like operating systems that have the /proc directory you can readlink /proc/self/exe to get the actual executable files full path even when argv[0] does not have this. 在具有/proc目录的Unix操作系统下,你可以readlink /proc/self/exe以获得实际可执行文件的完整路径,即使argv[0]没有这个。

This may not work, however, if the executable was started with fexecv (not available on many systems) and if that is implemented as a system call on your system. 但是,如果可执行文件是使用fexecv启动的(在许多系统上不可用),并且在系统上实现为系统调用,则这可能不起作用。 fexecv is just like execve except that it is passed an open file descriptor rather than a filename to run. fexecv就像execve一样,除了传递一个打开的文件描述符而不是文件名来运行。 Under Linux it is implemented by calling execve on the string generated by `"/proc/self/%i", fd", so the file would have to live in the file system at the time the program was started. 在Linux下,它通过调用由“/ proc / self /%i”,fd“生成的字符串上的execve来实现,因此文件在程序启动时必须存在于文件系统中。

I think that GNU/Hurd supports fexecve natively. 我认为GNU / Hurd原生支持fexecve

It is possible for an executable file to be renamed or unlinked from the filesystem after it has been executed which makes it become an unnamed file which will go away as soon as it ceases to be open (in this context running a file usually requires it to be open by the kernel). 可执行文件在执行后可以从文件系统重命名或取消链接,这使得它成为一个未命名的文件,一旦它停止打开就会消失(在这种情况下,运行文件通常需要它由内核打开)。

I cannot speak to windows. 我不能和窗户说话。 However in UNIX, a fair percentage of the time it is possible, but it is not guaranteed. 但是在UNIX中,有相当一部分时间是可能的,但不能保证。 The reasons for this involve calls to exec from other programs like shell which in some circumstances can cloud where the executable lives, for example, a relative path like "../../../mybin/exe/myprogram". 这种情况的原因涉及从shell等其他程序调用exec,在某些情况下可以在可执行文件所在的地方云,例如,像“../../../mybin/exe/myprogram”这样的相对路径。 The PATH variable also makes it fun to track down an executable. PATH变量还可以跟踪可执行文件。

Let me ask: what are you trying to do, or, more correctly, why do you need to know? 让我问一下:你想做什么,或者更确切地说,为什么你需要知道? IMO you don't need to know. IMO你不需要知道。 you can check getcwd() and if you are not running in a directory that works, exit. 你可以检查getcwd(),如果你没有在一个有效的目录中运行,退出。 It should not matter where your executable image lives. 可执行映像的存在位置无关紧要。

Here is one code hunk that works most of the time, not always! 这是一个大部分时间都可以工作的代码块,并非总是如此!

requires a call from main, using argv[0], I am using popen() calls to shell to make the code fit in a small are, popen() is not always a great choice, this can fail if there are other executables earlier in the PATH with the same name: 需要从main调用,使用argv [0],我使用popen()调用shell来使代码适合小的,popen()并不总是一个很好的选择,如果之前还有其他可执行文件,这可能会失败在PATH中具有相同的名称:

char *
mypath(const char *src)
{
   FILE *cmd=NULL;
   static char path_2_me[PATH_MAX]={0x0};
   char tmp[PATH_MAX]={0x0};
   const char *basename=strrchr(src, '/');

   if(basename==NULL) 
        basename=src;
   else
        basename++;      

   if(memcmp(src, "./", 2)==0)      
     sprintf(path_2_me,"%s/%s", getcwd(tmp, PATH_MAX), basename);             
   else
   {
      sprintf(tmp, "/usr/bin/which %s", basename);
      cmd=popen(tmp, "r");      
      fgets(path_2_me, sizeof(path_2_me), cmd); /* one read only */
      pclose(cmd);
      /* check for what your version of which says on failure */
      if(memcmp(path_2_me, "no ", 3)==0)
         *path_2_me=0x0;
   }  

   return (*path_2_me) ?path_2_me: NULL;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM