如何正确使用GetModuleFileName?

时间:2013-09-13 09:41:50

标签: c++ getmodulefilename

以下代码:

#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();

}

应显示程序执行的完整路径。但是在VS 2012中我得到了错误:

  

使用未初始化的局部变量'buffer'

代码有什么问题?

3 个答案:

答案 0 :(得分:26)

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

 wchar_t buffer[MAX_PATH]; 
例如,

答案 1 :(得分:7)

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

由于您使用的是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;

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

答案 2 :(得分:0)

这是Win32 API的一个普遍问题,函数会将字符串返回到有限大小的缓冲区中,并且您不确定缓冲区是否足够大以容纳整个字符串。正如kingsb所提到的,即使是MAX_PATH,对于如今的路径而言,也不够好。

为此,我倾向于使用一般的辅助功能:

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 );
    }
}

GetModuleFileName可以这样使用:

extern HINSTANCE hInstance;

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

对于这样的LoadString:

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