Получение временного пути к папке пользователя в Windows

Как я могу получить путь к папке пользователя temp в С++? Моя программа должна работать в Windows Vista и XP, и у них разные темпы. Как я могу получить его без потери совместимости?

Ответы

Ответ 1

Есть ли причина, по которой вы не можете использовать API Win32 GetTempPath?

Этот API доступен начиная с W2K и, следовательно, будет доступен для всех перечисленных вами целей.

Ответ 2

Функция 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 получает временный путь к файлу следующим образом:

  • Путь, указанный переменной среды TMP.
  • Путь, указанный переменной среды TEMP, если TMP не определен.
  • Текущий каталог, если оба TMP и TEMP не определены.

Ответ 4

#include <iostream>
#include <string>

int main(int argc, char* argv[]){

    std::cout << getenv("TEMP") << std::endl;

    return 0;
}

Ответ 5

Используйте GetTempPath(), чтобы получить путь к каталогу, предназначенному для временных файлов.

wstring TempPath;
wchar_t wcharPath[MAX_PATH];
if (GetTempPathW(MAX_PATH, wcharPath))
   TempPath = wcharPath;

Ответ 6

GetTempPath не будет работать на Vista, если у пользователей нет административного доступа. Сейчас я сталкиваюсь с этой проблемой с одним из моих приложений.

Ответ 7

Функция GetTempPath вернет путь с коротким именем, например: C:\Users\WDKREM~1\AppData\Local\Temp\.

Чтобы получить полное имя временного пути, впоследствии используйте GetLongPathName.

Ответ 8

Как отметил 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 ) );

Ответ 9

В Windows 10 это может быть непросто, поскольку значение временного пути зависит не только от того, какой он установлен по умолчанию, но и от того, какое приложение вы используете. Так что это зависит от того, что конкретно вам нужно.

[Общая область] TEMP в пользовательских данных локального приложения

#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

Temp для любой переменной среды 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);
    }
}

[Надежный] Temp для всего, что доступно вашему приложению (С++ 17)

#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