Получить все переменные env в C \ C ++ в Windows - PullRequest
6 голосов
/ 02 марта 2012

Подпись для главной функции в C \ C ++ может содержать 3 аргумента:

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

Третье - переменные окружения.

Я компилирую библиотеку под VS10, и поэтому у меня нет main(). Как я могу получить переменные окружения точно такого же типа, как в char *envp[]? Я скорее не использую .NET, чтобы уменьшить зависимости и, возможно, однажды буду открыт для переносимости.

Ответы [ 3 ]

6 голосов
/ 02 марта 2012

GetEnvironmentStrings возвращает (только для чтения!) Указатель на начало блока среды для процесса.

Блок представляет собой непрерывную строку в стиле C, которая содержит нольопределено key=value пар.Блок завершается дополнительным нулевым завершением.

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

typedef std::basic_string<TCHAR> tstring; // Generally convenient
typedef std::map<tstring, tstring> environment_t;

environment_t get_env() {
    environment_t env;

    auto free = [](LPTCH p) { FreeEnvironmentStrings(p); };
    auto env_block = std::unique_ptr<TCHAR, decltype(free)>{
            GetEnvironmentStrings(), free};

    for (LPTCH i = env_block.get(); *i != T('\0'); ++i) {
        tstring key;
        tstring value;

        for (; *i != T('='); ++i)
            key += *i;
        ++i;
        for (; *i != T('\0'); ++i)
            value += *i;

        env[key] = value;
    }

    return env;
}

Конечно, правильная реализация будет инкапсулировать это в классеи, вероятно, используйте std::stringstream вместо ручной итерации по символам, объединяя строки в char одновременно.Но я ленивый.

Использование такое:

environment_t env = get_env();

// Now you can write env[T("Var1")] to access a variable.
4 голосов
/ 02 марта 2012

Я не знаю о Windows, но в Linux эта переменная:

extern char **environ;

- это именно то, что вы ищете.

#include <stdio.h>
#include <assert.h>

extern char **environ;

int main (int ac, char **av, char **envp) {

  assert(envp == environ);

}
1 голос
/ 09 ноября 2015

Нижеследующее основано на @ превосходном ответе Конрада с двумя основными отличиями:

  • Использование wchar_t вместо TCHAR. Никто не должен использовать неширокие символы в Windows.
  • Построение key и value с использованием std::wstring str(buffer, buflen), как предлагается в этого ответа . Я считаю, что производительность должна быть лучше, чем констатация char-by-char, хотя я ее не измерял.

код:

typedef std::map<std::wstring, std::wstring> environment_t;
environment_t get_env() {
    environment_t env;

    auto free = [](wchar_t* p) { FreeEnvironmentStrings(p); };
    auto env_block = std::unique_ptr<wchar_t, decltype(free)>{
        GetEnvironmentStringsW(), free};

    for (const wchar_t* name = env_block.get(); *name != L'\0'; )
    {
        const wchar_t* equal = wcschr(name, L'=');
        std::wstring key(name, equal - name);

        const wchar_t* pValue = equal + 1;
        std::wstring value(pValue);

        env[key] = value;

        name = pValue + value.length() + 1;
    }

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