【发布时间】:2012-08-28 14:40:06
【问题描述】:
我想获取当前进程的完整路径。
我使用_getcwd 来获取当前工作目录。但它不包括文件名。
我怎样才能得到类似filename.exe的文件名?
【问题讨论】:
-
它通常是命令行应用程序的第 0 个参数。
-
尝试 arg 0 ,它应该在那里
我想获取当前进程的完整路径。
我使用_getcwd 来获取当前工作目录。但它不包括文件名。
我怎样才能得到类似filename.exe的文件名?
【问题讨论】:
argv[0] 的 main 函数是你的文件名。
一个简单的代码sn-p:
#include<stdio.h>
int main(int argc, char** argv)
{
//access argv[0] here
}
如果您无法访问/更改 main() 中的代码,您可以执行以下操作:
std::string executable_name()
{
#if defined(PLATFORM_POSIX) || defined(__linux__) //check defines for your setup
std::string sp;
std::ifstream("/proc/self/comm") >> sp;
return sp;
#elif defined(_WIN32)
char buf[MAX_PATH];
GetModuleFileNameA(nullptr, buf, MAX_PATH);
return buf;
#else
static_assert(false, "unrecognized platform");
#endif
}
【讨论】:
argv[0] 是用户用来调用您的程序的名称。如果用户使用符号链接,argv[0] 是符号链接,而不是二进制文件本身。
你可以在windows上使用:
TCHAR szExeFileName[MAX_PATH];
GetModuleFileName(NULL, szExeFileName, MAX_PATH);
szExeFileName 将包含完整路径 + 可执行文件名
[编辑]
对于更便携的解决方案,请使用argv[0] 或其他一些特定于平台的代码。你可以在这里找到这样的方法:https://github.com/mirror/boost/blob/master/libs/log/src/process_name.cpp。
【讨论】:
在 Linux 上,二进制文件的文件名是符号链接的目标地址 /proc/self/exe。您可以使用readlink 系统调用来查找符号链接的目标。
请注意,这会告诉您二进制文件在磁盘上的实际存储位置,而不仅仅是用户用来启动程序的命令。
【讨论】:
这是一种使用 boost (https://www.boost.org/) 的跨平台方式
#include <iostream>
#include <boost/dll.hpp>
int main( int argc, char **argv ) {
std::cout << "hello world, this is [" << boost::dll::program_location().filename().string() << "]" << std::endl;
std::cout << "or [" << boost::dll::program_location().string() << "] if you're not into the whole brevity thing." << std::endl;
return 0;
}
编译通过
g++ -o hello_world hello_world.cpp -lboost_filesystem -lboost_system -ldl
输出结果
hello world, this is [hello_world]
or [/home/gjvc/tmp/hello_world] if you're not into the whole brevity thing.
【讨论】:
正如其他人所提到的,您的 可执行文件 的名称包含在 argv[0] 中。如果您需要,您可以:
cout << argv[0] << endl;
如果您需要可执行文件的源文件的名称,C++ 有一个预定义的宏可以使用:
cout << __FILE__ << endl;
Go to here 并滚动到“预定义的宏名称”
【讨论】:
您可以使用 errno.h 中的 program_invocation_name
【讨论】:
通常可以从argv[0]获取可执行文件名:
#include <stdio.h>
int main(int argc, char* argv[])
{
printf("Running: %s\n", argv[0]);
return 0;
}
确实,应用程序有多种方法可以execl() 另一个应用程序(或另一个类似函数)并覆盖此参数。系统为这类应用程序更改它仍然是非常规的。
【讨论】:
execl 并将argv[0] 设置为程序名称。这也是一个可破解的约定。在安全环境中,将 argv[0] 设为 null 有点标准。
在 Linux(POSIX?)中,有一个名为 _ 的环境变量包含当前进程。
$ echo $_
echo
在 C++ 中
#include <stdlib.h> /* getenv */
#include<iostream>
int main(){
std::cout << getenv("_") << '\n';
return 0;
}
编译
$ c++ a.cpp -o a.out
$ ./a.out
打印./a.out(或任何已执行的行,包括路径)。
这与其他方法相比具有一定的优势,可以全局读取(不通过argv[0])并且不需要文件处理。
【讨论】:
tmp/a.out 如果我从不同的目录运行它。