【问题标题】:Full path of executable file in Windows, c++ [duplicate]Windows中可执行文件的完整路径,c ++ [重复]
【发布时间】:2014-03-17 21:48:09
【问题描述】:

我只想在控制台上获取我的可执行文件的完整路径,但变量路径只存储数字我如何将其转换为字符串(我知道此代码仅输出路径的内存位置)?

#include <iostream>
#include <windows.h>
#include <string>

using namespace std;

int main() {

    WCHAR path[MAX_PATH];

    GetModuleFileName(NULL, path, 500);

    cout << "File path is: " << path << endl;
}

【问题讨论】:

  • 请问实际的错误是什么??
  • 用 wcout 找出一个 WCHAR !!!!
  • @πάνταῥεῖ 我想将 WCHAR(或任何可能写在那里的)转换为字符串
  • 请注意,input 是您在上述代码中从未使用过的变量。
  • @Splendor 我想将 WCHAR(或任何可能写在那里的内容)转换为字符串 ... 这不是 您实际错误的描述 ,编译时间,或运行时!! (顺便说一句,我想要一匹小马!!)

标签: c++ winapi


【解决方案1】:

您的代码有几个问题:

  • 您将错误的大小参数传递给GetModuleFilename - 缓冲区大小应该是 TCHARs 中的大小,在您的情况下是 MAX_PATH,而不是 500。这是等待发生的缓冲区溢出 500 > MAX_PATH
  • 您正在使用窄流进行输出,无法打印宽字符串,因此您看到的是地址。要打印宽字符,您需要改用 std::wcout。

【讨论】:

  • 谢谢!是的,wcout 解决了我可以打印文件路径的问题,但是如果我想将它转换为字符串呢?例如,我想用 imread() 加载图像,它接受文件参数中的字符串。
  • 简单的答案 - 不要构建 unicode 版本,如果您需要窄字符串,则构建使用窄字符串的版本。或者,您可以使用一些内置的 Windows 字符串转换函数将宽字符串转换为窄字符串。
  • @TimoGeusch:您不能使用任何随机函数或代码页。最好的办法是获取 8.3 名称,即纯 ASCII IIRC。
【解决方案2】:

正如 cmets 中已经指出的,您可能希望使用 wcout 来打印 WCHAR 字符串。

您可能需要考虑这样的函数,以方便的 C++ 方式包装 GetModuleFileName() 调用:

#include <stdexcept> // For std::runtime_error
#include <string>    // For std::wstring
#include <Windows.h> // For Win32 API

// Represents an error in a call to a Win32 API.
class win32_error : public std::runtime_error 
{
public:
    win32_error(const char * msg, DWORD error) 
        : std::runtime_error(msg)
        , _error(error)
    { }

    DWORD error() const 
    {
        return _error;
    }

private:
    DWORD _error;
};


// Returns the full path of current EXE
std::wstring GetPathOfExe() 
{
    // Get filename with full path for current process EXE
    wchar_t filename[MAX_PATH];
    DWORD result = ::GetModuleFileName(
        nullptr,    // retrieve path of current process .EXE
        filename,
        _countof(filename)
    );
    if (result == 0) 
    {
        // Error
        const DWORD error = ::GetLastError();
        throw win32_error("Error in getting module filename.", 
                          error);
    }

    return filename;
}

请注意,如果您想要WCHARs 中的原始字符串缓冲区大小,您可能需要使用_countof()

【讨论】:

  • 有没有办法以string 格式存储路径?
  • @Splendor:一种选择是显式使用GetModuleFileNameA(),即ANSI版本和char字符串(而不是wchar_t字符串)。或者使用CW2A(这是WideCharToMultiByte() API 上的一个方便的RAII 包装器)从std::wstring 转换为ANSI。
  • @Mr.C64 什么是Midule? :) #trolly
  • @Mr.C64 因为我想使用 char 字符串,GetModuleFileNameA 是我正在寻找的功能,谢谢
  • @Splendor:如果您发现一些答案对您有帮助,您可能需要点赞,并将最佳回复标记为答案。
【解决方案3】:

wchar 是 16 位,而您使用的是 cout,并且输出流需要 8 位字符,这就是为什么您在输出中得到奇怪数字的原因

当您必须使用 wchar 时,请使用 wcout 并注意您使用的字符串类型!

【讨论】:

    【解决方案4】:
    #include <iostream>
    #include <string>
    #include <windows.h>
    
    std::wstring app_path() {
        std::wstring path;
        path.resize(MAX_PATH, 0);
        auto path_size(GetModuleFileName(nullptr, &path.front(), MAX_PATH));
        path.resize(path_size);
        return path;
    }
    
    int main() {
        auto path(app_path());
        std::wcout << L"File path is: " << path << std::endl;
    }
    

    试试这个!

    【讨论】:

    • 为什么不直接使用_countof() 而不是冗长的sizeof() 东西?
    • @Mr.C64 具有教育意义。 :) 强迫他也查一下并理解它。
    • 通过MAX_PATH 会容易得多。顺便说一句,你有一个一次性的错误。您应该传递缓冲区大小,而不是缓冲区大小 - 1。这将错误地截断长度为 MAX_PATH-1 的有效路径
    • @MSalters Windows XP:字符串被截断为 nSize 个字符,并且不是以 null 结尾的。 - 我的非母语英语说在 XP 上,我应该保留结尾NULL自己。 --- 添加了 1 个额外字符以防万一。
    • @CodeAngry,有没有办法以字符串格式存储路径?我想使用imwrite 保存图像,路径必须是字符串格式才能使用该功能
    猜你喜欢
    • 2011-02-08
    • 2019-05-03
    • 2013-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多