C++编程实现获取当前可执行文件名称
作者:fpcc
一、介绍
在C++开发中,有时需要获取当前可执行文件的名称用来处理一些事务。那么,在主流的平台上,获取当前可执行文件名称的方法有哪些呢?一般来说,无论哪个平台下都分为以下几类:
- 使用接口
- 使用配置文件或相关属性(注册表等)
- 使用第三方库
下面将分别在Windows和Linux两大主流平台上进行分析说明。
二、Windows平台
按照上面的三类划分,在Windows平台上获取可执行文件名称的方法有:
1.系统接口
1)使用GetModuleFileName函数,这是在Windows平台上推荐的用法:
#include <windows.h>
#include <iostream>
#include <string>
int main() {
char exePath[MAX_PATH];
DWORD len = GetModuleFileNameA(NULL, exePath, MAX_PATH);
if (len == 0) {
std::cerr << "err code: " << GetLastError() << std::endl;
return 1;
}
std::string fullPath(exePath);
std::cout << "cur full path: " << fullPath << std::endl;
return 0;
}
2)使用C提供的_get_pgmptr函数来获取_pgmptr
#include <cstdlib>
#include <iostream>
int main() {
char* pgmptr = nullptr;
errno_t err = _get_pgmptr(&pgmptr);
if (pgmptr != nullptr) {
std::cout << "full path: " << pgmptr << std::endl;
}
return 0;
}2.配置文件及相关
- 直接读取main函数中的argv[0],它一般只包括名字而不包括完整路径。这个简单就不举例了。
- 读取环境变量或配置文件(这需要程序中做一些特殊的输出或配置,普通的可执行文件可能无法应用)
3.第三方库
在Windows平台上有很多的第三方框架或库都提供了类似的机制,如boost::dll::program_location()等。例程看后面。
三、Linux平台
Linux平台亦是如此,但是它的实现方式更加丰富:
1.系统接口
使用dladdr
#include <iostream>
#include <dlfcn.h>
int main() {
Dl_info dl;
if (dladdr((void*)main, &dl) && dl.dli_fname) {
std::cout << "path: " << dl.dli_fname << std::endl;
}
return 0;
}
其它平台一些变种:如Solaris中的getexecname()接口等
2.配置文件及相关
读取/proc/self/exe链接,获取当前可执行文件名称
#include <iostream>
#include <unistd.h>
#include <limits.h>
int main() {
char exePath[PATH_MAX];
ssize_t len = readlink("/proc/self/exe", exePath, sizeof(exePath) - 1);
if (len != -1) {
exePath[len] = '\0';
std::cout << "full path: " << exePath << std::endl;
}
return 0;
}
读取/proc/self/cmdline
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::ifstream cmdline("/proc/self/cmdline");
if (cmdline.is_open()) {
std::string exePath;
std::getline(cmdline, exePath, '\0');
std::cout << "full path: " << exePath << std::endl;
}
return 0;
}
使用main函数中的argv[0],不赘述
gunlib中的program_name
这个需要主动初始化,有点类似Windows平台的特殊配置
3.第三库
1)典型的就是使用Boost库中的boost::dll::program_location(),看例子:
#include <iostream>
#include <boost/dll/runtime_symbol_info.hpp>
int main() {
boost::dll::fs::path fullPath = boost::dll::program_location();
std::cout << "full path: " << fullPath.string() << std::endl;
return 0;
}
2)其它一些特定系统上的库如libbsd等
四、分析说明
除了上面的分析的方法外,另外还可以使用一些特殊的技巧来获取执行文件的名称,比如使用调试的接口(backstarce函数)等等。
通过上面的分析说明,基本上可以看到它们的优缺点。
对使用接口操作来说,优点是安全稳定及准确,但可能无法跨平台。而且可能有的平台上需要安装一些特定的库;
一般来说,使用配置及相关的方法,相对来说都比较准确,通常包括完整的全路径。但缺点是依赖于特定的平台或系统,而且有可能还需要权限。这点就限制了不少的应用,特别是在某些裁剪的系统上的应用;
使用第三方库的优点是应用上简单,灵活多变。缺点是需要安装第三方库而且在编译时需要增加对相关的库的链接。对于一些小的工程就不太实用了。
这里必须单独把使用argv[0]拿出来,它作为一种很传统的获取可执行文件名称的方法,在正式场景下不建议使用。因为影响它的因素比较多,有可能名称根本就不对。所以还是要引起注意。
五、总结
其实在真正的应用中,这种小功能的需求层出不穷。真正和用户打过交道的开发者就会明白,用户有时候想得非常“野”,让开发者有一种应接不暇的感觉。其实换位思考,谁都想让软件的应用更方便快捷。一个小功能往往就会让用户感到软件的人性化。
以上就是C++编程实现获取当前可执行文件名称的详细内容,更多关于C++获取当前可执行文件名称的资料请关注脚本之家其它相关文章!
