Ответ 1
Вам нужно указать буфер, который может содержать несколько символов;
wchar_t buffer[MAX_PATH];
например.
Следующий код:
#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'
Что не так в коде?
Вам нужно указать буфер, который может содержать несколько символов;
wchar_t buffer[MAX_PATH];
например.
VS правильно указывает, что вы используете неинициализированный буфер - buffer var - это указатель на WSTR, но он не был инициализирован статическим буфером, и он не был выделен. Также вы должны помнить, что MAX_PATH часто недостаточно, особенно в современных системах с длинными именами путей.
Поскольку вы используете С++, было бы неплохо использовать его функции. Я могу предположить следующий код:
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 как буфер: он не определен для непрерывного буфера в каждой реализации (но обычно это)
Это общая проблема с 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 LoadStringA( hInstance, id, buffer, size );
} );
}