C++ 如何正确使用 GetModuleFileName?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18783087/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:12:20  来源:igfitidea点击:

How to properly use GetModuleFileName?

c++getmodulefilename

提问by Sunrise

Following code:

以下代码:

#include <iostream>
#include <Windows.h>

using namespace std;

int main ()
{   LPWSTR buffer; //or wchar_t * buffer;
    GetModuleFileName(NULL, buffer, MAX_PATH) ;
    cout<<buffer;
    cin.get();
    cin.get();

}

Should show the full path where the program executes. But in VS 2012 I get the error:

应该显示程序执行的完整路径。但在 VS 2012 中,我收到错误消息:

uninitialized local variable 'buffer' used

使用了未初始化的局部变量“缓冲区”

What's wrong in code?

代码有什么问题?

回答by Mats Petersson

You need to give it a buffer that can hold some characters;

你需要给它一个可以容纳一些字符的缓冲区;

 wchar_t buffer[MAX_PATH]; 

for example.

例如。

回答by kingsb

VS properly points out that you are using an uninitialized buffer - buffervar is a pointer to WSTR, but it was not initialized with the static buffer, neither it was allocated. Also you should remember that MAX_PATH is often not enough, especially on modern systems with long pathnames.

VS 正确地指出您正在使用未初始化的缓冲区 -缓冲区var 是指向 WSTR 的指针,但它没有使用静态缓冲区进行初始化,也没有分配。您还应该记住 MAX_PATH 通常是不够的,尤其是在具有长路径名的现代系统上。

Since you are using C++, it would be a good practice to use it's features. I can suppose the following code:

由于您使用的是 C++,因此最好使用它的功能。我可以假设以下代码:

vector<wchar_t> pathBuf; 
DWORD copied = 0;
do {
    pathBuf.resize(pathBuf.size()+MAX_PATH);
    copied = GetModuleFileName(0, &pathBuf.at(0), pathBuf.size());
} while( copied >= pathBuf.size() );

pathBuf.resize(copied);

wstring path(pathBuf.begin(),pathBuf.end());

cout << path;

Don't use wstring as buffer directly: it is not defined to have a continuous buffer in every implementation (but usually is)

不要直接使用 wstring 作为缓冲区:它没有被定义为在每个实现中都有一个连续的缓冲区(但通常是)

回答by Ivan Kolev

This is a general problem with the Win32 API, functions return strings into a buffer of a limited size and you are never sure if your buffer was large enough to hold the whole string. Even MAX_PATH is not a good enough constant for paths these days, as kingsb mentioned.

这是 Win32 API 的一个普遍问题,函数将字符串返回到大小有限的缓冲区中,并且您永远不确定您的缓冲区是否足够大以容纳整个字符串。正如 kingsb 提到的那样,即使 MAX_PATH 现在对于路径来说也不是一个足够好的常量。

I tend to use a general helper function for this purpose:

为此,我倾向于使用通用辅助函数:

template <typename TChar, typename TStringGetterFunc>
std::basic_string<TChar> GetStringFromWindowsApi( TStringGetterFunc stringGetter, int initialSize = 0 )
{
    if( initialSize <= 0 )
    {
        initialSize = MAX_PATH;
    }

    std::basic_string<TChar> result( initialSize, 0 );
    for(;;)
    {
        auto length = stringGetter( &result[0], result.length() );
        if( length == 0 )
        {
            return std::basic_string<TChar>();
        }

        if( length < result.length() - 1 )
        {
            result.resize( length );
            result.shrink_to_fit();
            return result;
        }

        result.resize( result.length() * 2 );
    }
}

Which for GetModuleFileName can be used like this:

GetModuleFileName 可以像这样使用:

extern HINSTANCE hInstance;

auto moduleName = GetStringFromWindowsApi<TCHAR>( []( TCHAR* buffer, int size )
{
    return GetModuleFileName( hInstance, buffer, size );
} );

Or for LoadString like this:

或者对于像这样的 LoadString:

std::basic_string<TCHAR> LoadResourceString( int id )
{
    return GetStringFromWindowsApi<TCHAR>( [id]( TCHAR* buffer, int size )
    {
        return LoadString( hInstance, id, buffer, size );
    } );
}