如何获取程序正在运行的目录?
是否有平台无关和文件系统无关的方法来获取使用C / C ++从中运行程序的目录的完整路径?不要与当前工作目录混淆。 (除非是标准库,例如clib或者STL,否则请不要建议它们。)
(如果没有与平台/文件系统无关的方法,那么也欢迎在Windows和Linux中适用于特定文件系统的建议。)
解决方案
对于Win32,GetCurrentDirectory应该可以解决问题。
不,没有标准方法。我相信C / C ++标准甚至不考虑目录(或者其他文件系统组织)的存在。
在Windows上,当hModule参数设置为NULL时,GetModuleFileName()将返回当前进程的可执行文件的完整路径。我帮不上Linux。
另外,我们还应该澄清是要使用当前目录还是要使用程序映像/可执行文件所在的目录。就目前情况而言,问题在这一点上有点模棱两可。
如果要使用没有库的标准方式:否。目录的整个概念未包含在标准中。
如果我们同意对标准库的某种(便携式)依赖关系是可以的:使用Boost的文件系统库,并请求initial_path()。
恕我直言,我们可以通过良好的业力获得最大的收益(Boost是一套完善的高质量库)
在POSIX平台上,可以使用getcwd()。
在Windows上,我们可能会使用_getcwd(),因为已不建议使用getcwd()。
对于标准库,如果Boost对我们而言已经足够标准了,我会建议使用Boost :: filesystem,但是它们似乎已从提案中删除了路径标准化。我们可能要等到TR2可以立即用于完整的标准解决方案。
也许用argv [0]连接当前工作目录?我不确定这是否适用于Windows,但适用于Linux。
例如:
#include <stdio.h> #include <unistd.h> #include <string.h> int main(int argc, char **argv) { char the_path[256]; getcwd(the_path, 255); strcat(the_path, "/"); strcat(the_path, argv[0]); printf("%s\n", the_path); return 0; }
运行时,它输出:
jeremy@jeremy-desktop:~/Desktop$ ./test /home/jeremy/Desktop/./test
我们不能为此目的使用argv [0],通常它确实包含可执行文件的完整路径,但不一定可以在字段中使用任意值创建进程。
另外请注意,当前目录和带有可执行文件的目录是两件不同的事情,因此getcwd()也不会对我们有所帮助。
在Windows上,使用GetModuleFileName(),在Linux上,读取/ dev / proc / procID / ..文件。
Boost Filesystem的" initial_path()"的行为类似于POSIX的" getcwd()",我们自己也不需要做任何事情,但是将argv [0]添加到其中任何一个上都可以。
我们可能会注意到结果并不总是很漂亮-我们可能会得到诸如/ foo / bar /../../ baz / a.out
或者/ foo / bar // baz / a.out
之类的东西,但我相信它总是会产生一个有效的路径来命名可执行文件(请注意,路径中的连续斜杠会折叠成一个)。
之前,我曾使用envp
(main()的第三个参数)编写了一个解决方案,该解决方案在Linux上有效,但在Windows上似乎不可行,因此我实质上建议与其他人使用相同的解决方案,但建议使用即使结果不佳,也要解释为什么它实际上是正确的。
如果我们在程序首次启动时获取当前目录,那么我们实际上就拥有了程序从其启动的目录。将值存储在变量中,然后在程序中引用它。这不同于保存当前可执行程序文件的目录。它不一定是同一目录。如果有人从命令提示符处运行该程序,则即使该程序文件位于其他位置,也正在从命令提示符的当前工作目录中运行该程序。
getcwd是POSIX函数,并且所有POSIX兼容平台均支持开箱即用。我们不必做任何特殊的事情(除了在Unix上抬头unistd.h和在Windows上抬头direct.h之外)。
由于我们正在创建C程序,它将与默认的c运行时库链接,该库由系统中的所有进程链接到该库(避免了特制的异常),并且默认情况下将包含此函数。 CRT从不被视为外部库,因为它为OS提供了基本的标准兼容接口。
在Windows上,不建议使用getcwd函数,而推荐使用_getcwd。我认为我们可以以这种方式使用它。
#include <stdio.h> /* defines FILENAME_MAX */ #ifdef WINDOWS #include <direct.h> #define GetCurrentDir _getcwd #else #include <unistd.h> #define GetCurrentDir getcwd #endif char cCurrentPath[FILENAME_MAX]; if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) { return errno; } cCurrentPath[sizeof(cCurrentPath) - 1] = 'int bytes = GetModuleFileName(NULL, pBuf, len); if(bytes == 0) return -1; else return bytes;'; /* not really required */ printf ("The current working directory is %s", cCurrentPath);
这是获取执行应用程序完整路径的代码:
视窗:
char szTmp[32]; sprintf(szTmp, "/proc/%d/exe", getpid()); int bytes = MIN(readlink(szTmp, pBuf, len), len - 1); if(bytes >= 0) pBuf[bytes] = '##代码##'; return bytes;
Linux:
##代码##只是迟来地堆在这里,...
没有标准的解决方案,因为这些语言与底层文件系统无关,因此,正如其他人所说的那样,基于目录的文件系统的概念不在c / c ++语言的范围之内。
最重要的是,我们不想要当前的工作目录,而是想要程序正在运行的目录,它必须考虑程序如何到达其所在位置,即,它是通过fork生成为新进程等的。如解决方案所示,获取程序正在运行的目录,要求我们从相关操作系统的过程控制结构中获取该信息,这是对此问题的唯一授权。因此,根据定义,它是特定于OS的解决方案。
正如Minok所提到的,在ini C标准或者C ++标准中没有指定这样的功能。这被认为是纯粹的特定于OS的功能,例如,它是在POSIX标准中指定的。
Thorsten79给出了很好的建议,它是Boost.Filesystem库。但是,如果我们不希望程序具有二进制形式的任何链接时相关性,这可能会带来不便。
我推荐的一个很好的选择是收集100%仅标头的STLSoft C ++库Matthew Wilson(有关C ++的必读书籍的作者)。 PlatformSTL具有可移植的外观,可访问系统特定的API:Windows的WinSTL和Unix上的UnixSTL,因此是可移植的解决方案。所有特定于系统的元素都是使用特征和策略来指定的,因此它是可扩展的框架。当然,提供了文件系统库。