2012-03-02 74 views
6

在C \ C++的主要功能簽名用C \ C++都ENV變量可以包括3個參數:獲得在Windows

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

第三是環境變量。

我正在編譯VS10下的庫,因此我沒有main()。我怎樣才能得到與char *envp[]完全一樣的環境變量?我寧願不使用.NET來減少依賴關係,也許有一天會對可移植性開放。

+0

的getenv()和SETENV()不能使用,因爲你要知道整個列表...但如果你正在使用Visual Studio,那麼你爲Windows開發應用,那麼http://msdn.microsoft.com/en-us/library/ms683187%28v=vs.85%29.aspx? – Benoit 2012-03-02 14:45:25

+0

相關:http://stackoverflow.com/questions/2692855/extern-c-char-environ-windows-c-cli(可能甚至是一個笨蛋) – Flexo 2012-03-02 14:46:35

+0

我建議你不要試圖編寫多語言源文件。 – pmg 2012-03-02 14:47:23

回答

6

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. 
+0

我可以在返回值上強制轉換char * []'嗎?你可以添加這個語法,如果可能的話,你的答案? – Jonathan 2012-03-02 14:49:40

+0

@Jonathan不,你不能,'LPTCH'是'TCHAR *'的typedef。它是一個* single *連續的字符串,而不是一個字符串數組。由於你的問題被標記了,處理這個混亂的最簡單的方法是解析它並把它放入一個向量中。等等... – 2012-03-02 14:53:04

+0

我認爲這應該是單數「GetEnvironmentVariable」:http://msdn.microsoft.com/en-us/library/windows/desktop/ms683188%28v=vs.85%29.aspx 但是,這需要知道預先變量的名稱。 – 2012-03-02 15:02:37

4

我不知道有關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); 

} 
+3

'#include '現在應該聲明'environ'。有一段時間'environ'是唯一沒有頭部聲明的變量,但他們終於修正了這個問題。 – 2012-03-02 15:11:12

+0

鑑於[這個問題]的答案(http://stackoverflow.com/questions/1370399/c-function-arg-char-is-not-the-same-as-char),我猜'char ** environ'和'char * envp []'屬於同一類型 – Jonathan 2012-03-02 16:45:09

1

基於的@Konrad's excellent answer,用2個主要區別如下:

  • 使用wchar_t而非TCHAR。沒有人應該在Windows中使用非寬字符。
  • 構建keyvalue使用std::wstring str(buffer, buflen),如在this answer中所建議的那樣。我相信性能應該比逐字符串更好,儘管我沒有測量它。

代碼:

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