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
How to properly use 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 );
} );
}