Ответ 1
Есть ли причина, по которой вы не можете использовать API Win32 GetTempPath?
Этот API доступен начиная с W2K и, следовательно, будет доступен для всех перечисленных вами целей.
Как я могу получить путь к папке пользователя temp в С++? Моя программа должна работать в Windows Vista и XP, и у них разные темпы. Как я могу получить его без потери совместимости?
Есть ли причина, по которой вы не можете использовать API Win32 GetTempPath?
Этот API доступен начиная с W2K и, следовательно, будет доступен для всех перечисленных вами целей.
Функция GetTempPath возвращает путь к каталогу, предназначенному для временных файлов. Эта функция заменяет функцию GetTempDrive.
DWORD GetTempPath(
DWORD nBufferLength, // size, in characters, of the buffer
LPTSTR lpBuffer // address of buffer for temp. path
);
Параметры
nBufferLength
Определяет размер в символах буфера строк, идентифицированного lpBuffer.
lpBuffer
Указывает на строковый буфер, который получает строку с нулевым завершением, указывающую путь к временному файлу.
Возвращаемые значения
Если функция завершается успешно, возвращаемым значением является длина в символах строки, скопированной в lpBuffer, не включая завершающий нулевой символ. Если возвращаемое значение больше, чем nBufferLength, возвращаемое значение является размером буфера, необходимого для удержания пути. Если функция не работает, возвращаемое значение равно нулю. Чтобы получить расширенную информацию об ошибке, вызовите GetLastError.
Примечания
Функция GetTempPath получает временный путь к файлу следующим образом:
Начиная с C++ 17 вы можете использовать кроссплатформенную функцию:
std::filesystem::temp_directory_path()
https://en.cppreference.com/w/cpp/filesystem/temp_directory_path
#include <iostream>
#include <string>
int main(int argc, char* argv[]){
std::cout << getenv("TEMP") << std::endl;
return 0;
}
Используйте GetTempPath(), чтобы получить путь к каталогу, предназначенному для временных файлов.
wstring TempPath;
wchar_t wcharPath[MAX_PATH];
if (GetTempPathW(MAX_PATH, wcharPath))
TempPath = wcharPath;
GetTempPath не будет работать на Vista, если у пользователей нет административного доступа. Сейчас я сталкиваюсь с этой проблемой с одним из моих приложений.
Функция GetTempPath вернет путь с коротким именем, например: C:\Users\WDKREM~1\AppData\Local\Temp\
.
Чтобы получить полное имя временного пути, впоследствии используйте GetLongPathName.
Как отметил VictorV, GetTempPath
возвращает свернутый путь. Вам потребуется использовать оба макроса GetTempPath
и GetLongPathName
, чтобы получить полностью расширенный путь.
std::vector<TCHAR> collapsed_path;
TCHAR copied = MAX_PATH;
while ( true )
{
collapsed_path.resize( copied );
copied = GetTempPath( collapsed_path.size( ), collapsed_path.data( ) );
if ( copied == 0 )
throw std::exception( "An error occurred while creating temporary path" );
else if ( copied < collapsed_path.size( ) ) break;
}
std::vector<TCHAR> full_path;
copied = MAX_PATH;
while ( true )
{
full_path.resize( copied );
copied = GetLongPathName( collapsed_path.data( ), full_path.data( ), full_path.size( ) );
if ( copied == 0 )
throw std::exception( "An error occurred while creating temporary path" );
else if ( copied < full_path.size( ) ) break;
}
std::string path( std::begin( full_path ), std::end( full_path ) );
В Windows 10 это может быть непросто, поскольку значение временного пути зависит не только от того, какой он установлен по умолчанию, но и от того, какое приложение вы используете. Так что это зависит от того, что конкретно вам нужно.
#include <Windows.h>
#include <Shlobj.h>
#include <Shlobj_core.h>
#include <string_view>
// ...
static void GetUserLocalTempPath(std::wstring& input_parameter) {
static constexpr std::wstring_view temp_label = L"\\Temp\\";
HWND folder_handle = { 0 };
WCHAR temp_path[MAX_PATH];
auto get_folder = SHGetFolderPath(
folder_handle, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_DEFAULT, temp_path
);
if (get_folder == S_OK) {
input_parameter = static_cast<const wchar_t*>(temp_path);
input_parameter.append(temp_label);
CloseHandle(folder_handle);
}
}
GetUserLocalTempPath
, скорее всего, вернет полное имя вместо короткого.
Кроме того, если что-либо работает, оно делает это как SYSTEM вместо зарегистрированного пользователя, вместо того, чтобы возвращать %USERPROFILE%\AppData\Local\Temp
, оно будет возвращать что-то более похожее, C:\Windows\System32\config\systemprofile\AppData\Local\Temp
#include <Windows.h>
// ...
static void GetEnvTempPath(std::wstring& input_parameter) {
wchar_t * env_var_buffer = nullptr;
std::size_t size = 0;
if ( _wdupenv_s(&env_var_buffer, &size, L"TEMP") == 0 &&
env_var_buffer != nullptr) {
input_parameter = static_cast<const wchar_t*>(env_var_buffer);
}
}
#include <filesystem>
// ...
auto temp_path = std::filesystem::temp_directory_path().wstring();
temp_directory_path
скорее всего вернет короткое имя вместо полного имени.
Вы, вероятно, получите максимальную отдачу от первой и последней функций в зависимости от ваших потребностей. Если вы имеете дело с приложениями AppContainer, выберите последнее, предоставленное <filesystem>
. Это должно вернуть что-то вроде
C:\Users\user name\AppData\Local\Packages\{APP GUID}\AC\Temp