【问题标题】:Get all env variables in C\C++ on Windows获取 Windows 上 C\C++ 中的所有环境变量
【发布时间】:2012-03-21 01:31:19
【问题描述】:

C\C++ 中主函数的签名可以包含 3 个参数:

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

第三个是环境变量。

我正在 VS10 下编译一个库,因此我没有 main()。如何获得与char *envp[] 完全相同类型的环境变量?我宁愿不使用 .NET 来减少依赖关系,也许有一天会向可移植性开放。

【问题讨论】:

标签: c++ c environment-variables


【解决方案1】:

GetEnvironmentStrings 返回一个(只读!)指向进程环境块开始的指针。

该块是一个连续的 C 样式字符串,其中包含以 null 结尾的 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.

【讨论】:

  • 我可以在返回值上转换char*[] 吗?如果可能的话,您能否将此语法添加到您的答案中?
  • @Jonathan 不,你不能,LPTCHTCHAR* 的类型定义。它是一个 single 连续字符串,而不是字符串数组。由于您的问题已被标记,因此处理这种混乱的最简单方法是解析它并将其放入向量中。等等……
  • 我认为应该是单数 "GetEnvironmentVariable": msdn.microsoft.com/en-us/library/windows/desktop/… 但是这需要事先知道变量的名称。
  • 请注意,根据msdn.microsoft.com/en-us/library/windows/desktop/…,应该通过调用 FreeEnvironmentStrings() 来释放 env 块
【解决方案2】:

我不知道 windows,但是在 Linux 上这个变量:

extern char **environ;

正是您要找的。​​p>

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

extern char **environ;

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

  assert(envp == environ);

}

【讨论】:

  • #include &lt;unistd.h&gt; 这些天应该声明environ。曾经有一段时间,environ 是唯一没有标头声明的变量,但他们最终解决了这个问题。
  • 鉴于this question的答案,我猜char **environchar *envp[]属于同一类型
【解决方案3】:

以下内容基于@Konrad's excellent answer,有两个主要区别:

  • 使用wchar_t 而不是TCHAR。任何人都不应该在 Windows 中使用非宽字符。
  • 按照this answer 中的建议,使用std::wstring str(buffer, buflen) 构造keyvalue。我认为性能应该比逐个字符连接更好,尽管我没有测量它。

代码:

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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-17
    • 2012-06-18
    • 2012-04-16
    • 2016-09-29
    • 1970-01-01
    相关资源
    最近更新 更多