【问题标题】:How to Get the Filename of the Currently Running Executable in C++ [duplicate]如何在 C++ 中获取当前运行的可执行文件的文件名 [重复]
【发布时间】:2012-08-28 14:40:06
【问题描述】:

我想获取当前进程的完整路径。

我使用_getcwd 来获取当前工作目录。但它不包括文件名。

我怎样才能得到类似filename.exe的文件名?

【问题讨论】:

标签: c++ filenames


【解决方案1】:

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] 是符号链接,而不是二进制文件本身。
  • 您可以使用以下方式从 argv[0] 中提取文件名:cplusplus.com/forum/beginner/1962/#msg7180
  • 我使用 int WINAPI WinMain() 显示我如何通过这种方式做到这一点
  • 我怎样才能对 dll 文件做同样的事情?
【解决方案2】:

你可以在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

【讨论】:

  • 这不是便携式的
  • @sancelot 没有可移植的代码可以做到这一点,他/她的一个 cmets 中的 OP 要求 win32 平台,所以这个答案。同样在 Windows 下,您无法在所有应用程序类型中访问 argv[0]。顺便提一句。我添加了一些提示,以便以便携的方式制作它。
【解决方案3】:

在 Linux 上,二进制文件的文件名是符号链接的目标地址 /proc/self/exe。您可以使用readlink 系统调用来查找符号链接的目标。

请注意,这会告诉您二进制文件在磁盘上的实际存储位置,而不仅仅是用户用来启动程序的命令。

【讨论】:

【解决方案4】:

这是一种使用 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.

【讨论】:

    【解决方案5】:

    正如其他人所提到的,您的 可执行文件 的名称包含在 argv[0] 中。如果您需要,您可以:

    cout << argv[0] << endl;
    

    如果您需要可执行文件的源文件的名称,C++ 有一个预定义的宏可以使用:

    cout << __FILE__ << endl;
    

    Go to here 并滚动到“预定义的宏名称”

    【讨论】:

      【解决方案6】:

      您可以使用 errno.h 中的 program_invocation_name

      https://linux.die.net/man/3/program_invocation_short_name

      【讨论】:

        【解决方案7】:

        通常可以从argv[0]获取可执行文件名:

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

        确实,应用程序有多种方法可以execl() 另一个应用程序(或另一个类似函数)并覆盖此参数。系统为这类应用程序更改它仍然是非常规的。

        【讨论】:

        • argc和argv顺序错误,我已经给出答案了:)
        • Re 您总是可以从 argv[0] 获取可执行文件名:并非总是如此。约定调用execl 并将argv[0] 设置为程序名称。这也是一个可破解的约定。在安全环境中,将 argv[0] 设为 null 有点标准。
        • 感谢两位。我在回答中修正了一些问题,但现在不用担心太多。
        【解决方案8】:

        在 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])并且不需要文件处理。

        【讨论】:

        • 这在我的 linux 机器上对我不起作用。它打印 shell 的 pid 和路径。不是当前进程的名称。但是,如果我随后通过系统调用另一个程序,则该子进程将具有正确的名称。对于不同的 unix 变体,这似乎也略有不同。
        • @TomTanner,它也可能取决于外壳。例如,我知道该变量可以包含执行行的相对路径。例如 tmp/a.out 如果我从不同的目录运行它。
        猜你喜欢
        • 1970-01-01
        • 2017-04-20
        • 2017-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-02
        相关资源
        最近更新 更多