Как сделать правильный вызов GetModuleFileName с UnicodeStrings
GetModuleFileName не возвращает имя файла программы службы Windows.
Я уже определил переменные как AnsiString и UnicodeString, но, похоже, что-то связано с обработчиком событий, который я использую для получения этого значения.
AnsiString exefile = "", sIniFile = "", AppFile = "";
DWORD tamanho = MAX_PATH;
LPTSTR lpBuffer = exefile.c_str();
this->LogMessage("Iniciando serviço",EVENTLOG_INFORMATION_TYPE,0,0);
tamanho = GetModuleFileName( NULL, lpBuffer, tamanho );
if( tamanho > 0 ){ // retornou nome !
exefile = String(lpBuffer);
}
else
{
this->LogMessage("Impossível determinar pasta do executável",EVENTLOG_ERROR_TYPE,0,0);
Started = false;
return;
}
sIniFile = ChangeFileExt( exefile, L".ini");
if( !FileExists(sIniFile) )
{
this->LogMessage("Arquivo de inicialização não encontrado",EVENTLOG_ERROR_TYPE,0,0);
Started = false;
return;
}
else
this->LogMessage(sIniFile,EVENTLOG_INFORMATION_TYPE,0,0);
/*
// Debug
Started = true;
return;
*/
Там нет никаких сообщений об ошибках. Приложение успешно компилируется, оно не находит файл инициализации, который фактически существует в пути приложения.
Я использовал тот же код в другом сервисном приложении, и он отлично работает.
Что я делаю не так, пожалуйста?
Есть ли учебник, показывающий примеры работы с UnicodeStrings?
1 ответ
Вы злоупотребляете GetModuleFileName()
,
Вы не передаете выделенный буфер GetModuleFileName()
так что ему негде хранить свою продукцию. Строка c_str()
Метод никогда не возвращает нулевой указатель, поэтому, если строка пуста, c_str()
возвращает указатель на нулевой символ, который хранится в статической памяти. Вы говорите GetModuleFileName()
что вы выделили память для буфера, который вы ей даете, но на самом деле нет, поэтому когда GetModuleFileName()
пытается записать в ваш нераспределенный буфер, он либо удалит память, либо откроется просто сбой.
Вместо этого используйте что-то вроде этого:
this->LogMessage(_D("Iniciando serviço"), EVENTLOG_INFORMATION_TYPE, 0, 0);
WCHAR szBuffer[MAX_PATH];
DWORD tamanho = GetModuleFileNameW(NULL, szBuffer, MAX_PATH);
if( tamanho == 0 ){ // retornou nome !
{
this->LogMessage(_D("Impossível determinar pasta do executável"), EVENTLOG_ERROR_TYPE, 0, 0);
Started = false;
return;
}
String exefile(szBuffer, tamanho);
String sIniFile = ChangeFileExt(exefile, _D(".ini"));
if (!FileExists(sIniFile))
{
this->LogMessage(_D("Arquivo de inicialização não encontrado"), EVENTLOG_ERROR_TYPE, 0, 0);
Started = false;
return;
}
this->LogMessage(sIniFile, EVENTLOG_INFORMATION_TYPE, 0, 0);
/*
// Debug
Started = true;
return;
*/
Или вы можете сделать это:
this->LogMessage(_D("Iniciando serviço"), EVENTLOG_INFORMATION_TYPE, 0, 0);
UnicodeString exefile;
exefile.SetLength(MAX_PATH);
DWORD tamanho = GetModuleFileNameW(NULL, &exefile[1], MAX_PATH);
if( tamanho == 0 ){ // retornou nome !
{
this->LogMessage(_D("Impossível determinar pasta do executável"), EVENTLOG_ERROR_TYPE, 0, 0);
Started = false;
return;
}
exefile.SetLength(tamanho);
String sIniFile = ChangeFileExt(exefile, _D(".ini"));
if (!FileExists(sIniFile))
{
this->LogMessage(_D("Arquivo de inicialização não encontrado"), EVENTLOG_ERROR_TYPE, 0, 0);
Started = false;
return;
}
this->LogMessage(sIniFile, EVENTLOG_INFORMATION_TYPE, 0, 0);
/*
// Debug
Started = true;
return;
*/
При этом вам не нужно звонить GetModuleFileName()
прямо на всех. Вы можете использовать RTL ParamStr()
1 функция вместо. Когда это Index
параметр равен 0, он возвращает путь и имя файла вызывающего процесса (т.е. он вызывает GetModuleFileName()
внутренне для вас), например:
this->LogMessage(_D("Iniciando serviço"), EVENTLOG_INFORMATION_TYPE, 0, 0);
String exefile = ParamStr(0);
String sIniFile = ChangeFileExt(exefile, _D(".ini"));
if (!FileExists(sIniFile))
{
this->LogMessage(_D("Arquivo de inicialização não encontrado"), EVENTLOG_ERROR_TYPE, 0, 0);
Started = false;
return;
}
this->LogMessage(sIniFile, EVENTLOG_INFORMATION_TYPE, 0, 0);
/*
// Debug
Started = true;
return;
*/
1: В приложении VCL Forms Application->ExeName
свойство просто возвращает ParamStr(0)
,