Существует ли безопасный для локализации способ получения каталога AppData учетной записи SYSTEM? - PullRequest
0 голосов
/ 16 апреля 2019

Я знаю, что могу использовать GetSystemDirectory(), чтобы получить каталог C:\Windows\System32, но мне интересно, есть ли способ получить этот путь к каталогу ниже, независимо от того, как локализована ОС или я работаю как обычный пользователь или учетная запись SYSTEM:

C:\Windows\System32\config\systemprofile\AppData\Local\TEMP

Или, по крайней мере, до C:\Windows\System32\config\systemprofile\AppData

Я попытался использовать параметр SHGFP_TYPE_DEFAULT вместо SHGFP_TYPE_CURRENT для SHGetFolderPath(), но он вернет каталог текущего работающего пользователя вместо SYSTEM, если он не работает как SYSTEM.

void GetUserLocalTempPath(std::wstring& input_parameter) {
    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(L"\\TEMP");
        CloseHandle(folder_handle);
    }
}

Ответы [ 2 ]

1 голос
/ 17 апреля 2019

Чтобы запросить профиль SYSTEM, вам нужен процесс, работающий под учетной записью SYSTEM.

Создайте отдельную службу, которая запускается как SYSTEM. При необходимости вызовите SHGetFolderPath(CSIDL_LOCAL_APPDATA) или SHGetKnownFolderPath(FOLDERID_LocalAppData), указав NULL для токена пользователя, чтобы он запрашивал профиль вызывающего пользователя (т.е. SYSTEM) (или , просто используйте GetTempPath(), что также будет работать в этом контексте ).

Затем служба может передать этот путь обратно в ваше основное приложение через любой механизм IPC, независимый от сеанса, который вы хотите (каналы, сокеты и т. Д.).

На примечании стороны:

  • вам не нужно набирать temp_path при назначении на input_parameter. temp_path будет неявно распадаться в указатель wchar_t*, который может быть передан как есть в указатель const wchar_t*, который std::wstring::operator=() принимает в качестве входных данных.

  • вместо того, чтобы использовать input_parameter.append(L"\\TEMP") вручную (что вам вообще не нужно, если вы используете GetTempPath()), вам следует рассмотреть возможность использования PathCchCombineEx() (или связанных) или SHGetFolderPathAndSubDir() вместо. Пусть ОС обработает добавление для вас.

  • вы звоните CloseHandle() с HWND в качестве ввода, что неверно, поскольку вместо этого ожидается HANDLE (но это не работает в вашем случае, так как HWND имеет значение NULL, поэтому просто удалите CloseHandle()). Очевидно, вы не компилируете свой проект с включенной проверкой типа STRICT , в противном случае компилятор предотвратил бы передачу HWND параметру HANDLE.

0 голосов
/ 18 апреля 2019

Ответ Реми Лебо - правильный способ сделать это программно.Однако, это может быть больше, чем требуется для you ;Возможно, вы не захотите прыгать через все эти обручи, если ваша причина для этого не требует поддержки ОС нескольких поколений.Так что, если вы находитесь в Windows 10-land, то сейчас кажется безопасным для этого.Тем не менее, я не рекомендую это для его фундаментальных недостатков.Это простой неаккуратный обходной путь, поэтому используйте на свой страх и риск .

У меня нет подтверждающей документации на долговечность этого потенциального решения, только отдельные отзывы и личное тестирование.

Я слышал от пары людей, что важные системные каталоги ОС не локализованы.Я установил японский образ Windows 10 Pro на хост Hyper-V в качестве виртуальной машины.Вставка и ввод строки, C:\Windows\System32\config\systemprofile\AppData в адресную строку Japanese Explorer, работали очень хорошо, как показано ниже,
japanese_win10_vm_sysprof_appdata
Суть здесь в том, что после того, как вы получите значение системного каталога (мы не можем предположить C:\WINODWS\system32), вы сможете жестко закодировать остальное простым английским языком.Вот пример приложения, которое может сделать это для вас:

#define STRICT
#include <Windows.h>
#include <wchar.h>
#include <memory>

int wmain()
{
    static constexpr const wchar_t * SystemProfileAppData_RemainingPath
        = L"\\config\\systemprofile\\AppData";

    wchar_t system_path_buffer[MAX_PATH];
    const std::size_t winapi_worked = GetSystemDirectory(system_path_buffer, MAX_PATH);

    if (winapi_worked) {
        const std::size_t system32_offset = wcsnlen_s(system_path_buffer, MAX_PATH);
        const std::size_t appdata_offset  = wcsnlen_s(SystemProfileAppData_RemainingPath, MAX_PATH);
        const std::size_t path_bytes_size = (appdata_offset + system32_offset) * sizeof(wchar_t);

        memcpy_s(
            &system_path_buffer[system32_offset],
            path_bytes_size,
            SystemProfileAppData_RemainingPath,
            path_bytes_size
        );

        wprintf_s(L"SYSTEM's AppData is here: %s\r\n", system_path_buffer);

        return 0;
    }
    return 1;
}

SYSTEM's AppData is here: C:\WINDOWS\system32\config\systemprofile\AppData

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...