C++ Concat LPCTSTR

Я реализую настраиваемое действие для CAB-файла WindowsCE, и мне нужно объединить LPCTSTR, чтобы получить правильный путь к исполняемому файлу.

Мое настраиваемое действие получает LPCTSTR в качестве аргумента.

Итак (псевдокод):

extern "C" codeINSTALL_EXIT MYCUSTOMACTION_API Install_Exit(
    HWND    hwndParent,
    LPCTSTR pszInstallDir,
    WORD    cFailedDirs,
    WORD    cFailedFiles,
    WORD    cFailedRegKeys,
    WORD    cFailedRegVals,
    WORD    cFailedShortcuts
)
{
    if (FALSE == LaunchApp(pszInstallDir + "\\MyApp.exe"))
       ::MessageBox(hwndParent, L"Could not launch app!", L"Setup", MB_ICONINFORMATION );
    return codeINSTALL_EXIT_DONE;
}

Это использует мнимый оператор "+", который я использовал бы на моем стандартном языке C#.

У меня сравнительно небольшой опыт в C++. Как правильно добавить LPCTSTR для моих целей? Метод LaunchApp использует этот тип в качестве аргумента.

Также, если я хочу отобразить результирующий путь (для целей отладки) в MessageBox, есть ли быстрый способ конвертировать в LPCWSTR?

2 ответа

Решение

Для объединения используйте StringCchCat

TCHAR pszDest[260] = _T("");
StringCchCat(pszDest, 260, pszInstallDir); 
StringCchCat(pszDest, 260, _T("\\MyApp.exe"));
LaunchApp(pszDest);

Вам нужно выделить новый буфер для сборки объединенной строки, а затем скопировать в нее обе части. Вы можете выбрать фиксированный, большой размер буфера

TCHAR fullPath[MAX_PATH + 11]; // 11 = length of "\MyApp.exe" + nul in characters
_sntprintf_s(fullPath, MAX_PATH + 11, _T("%s\\MyApp.exe"), pszInstallDir);

или распределить его динамически, чтобы соответствовать:

size_t installDirLen = tcslen(pszInstallDir);
size_t bufferLen = installDirLen + 11; // again 11 = len of your string
LPWSTR fullPath = new TCHAR[bufferLen];
// if you're paranoid, check allocation succeeded: fullPath != null
tcsncpy_s(fullPath, bufferLen, pszInstallDir);
tcsncat_s(fullPath, bufferLen, _T"\\MyApp.exe");
// use it
delete fullPath;

Если вы находитесь в режиме Unicode, тогда LPCTSTR == LPCWSTR (вместо этого в режиме MBCS == LPCSTR). В любом случае макрос MessageBox должен работать для вас - он будет выбирать между MessageBoxA или MessageBoxW в зависимости от ситуации.


Как указывает ctacke ниже, это в Windows CE, и я не могу предположить, что у вас будут функции _s. Я думаю, что во втором случае можно использовать не _s варианты, так как мы знаем, что буфер достаточно большой, но в первом _sntprintf не гарантирует завершающий ноль в выходной строке (как в версии _s), и поэтому нам нужно сначала инициализируем буфер самостоятельно:

size_t bufferLen = MAX_PATH + 11;
TCHAR fullPath[bufferLen];
// zero the buffer out first
memset(fullPath, 0, sizeof(TCHAR) * bufferLen);
// only write up to bufferLen - 1, i.e. ensure the last character is left zero
_sntprintf(fullPath, bufferLen - 1, _T("%s\\MyApp.exe"), pszInstallDir);

(Это также можно сделать, опуская memset и используя возвращаемое значение _sntprintf, чтобы найти конец объединенной сгенерированной строки и обнулить следующий символ.)

AFAICR Windows CE только для Unicode и поэтому LPCTSTR == LPCWSTR всегда.

Вы можете использовать строку для объединения, а затем преобразовать результат в LPCTSTR с помощью помощников ATL, таких как CA2T:

std::string filePath = "\\\\user\\Home\\";
std::string fileName = "file.ex";
std::string fullPath = filePath + fileName;
CA2T t(fullPath.c_str());
LPCTSTR lpctsrFullPath = t;
Другие вопросы по тегам