Как сделать правильный вызов 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) ,

Другие вопросы по тегам