gpt4 book ai didi

c++ - 如何尽可能干净地使用 VS C++ GetEnvironmentVariable?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:03:09 25 4
gpt4 key购买 nike

(与其说这是一个学究气的练习,不如说是个问题,所以就这样吧。)

我制作了一个很好的小程序,它是我的 linux 操作系统的 native 程序,但我认为它也足够有用,可以存在于我的 Windows 机器上。因此,我想访问 Windows 的环境变量,MSDN 引用了这样一个例子:

const DWORD buff_size = 50;
LPTSTR buff = new TCHAR[buff_size];

const DWORD var_size = GetEnvironmentVariable("HOME",buff,buff_size);

if (var_size==0) { /* fine, some failure or no HOME */ }
else if (var_size>buff_size) {

// OK, so 50 isn't big enough.
if (buff) delete [] buff;
buff = new TCHAR[var_size];

const DWORD new_size = GetEnvironmentVariable("HOME",buff,var_size);

if (new_size==0 || new_size>var_size) { /* *Sigh* */ }
else { /* great, we're done */ }
}
else { /* in one go! */ }

这(对我而言)不如使用 getenv 和仅检查空指针那么好。我也不想动态分配内存,因为我只是想让程序在 Windows 和我的 linux 操作系统上运行,这意味着这个 MS 代码必须与 nix 代码很好地配合。更具体地说:

template <class T> // let the compiler sort out between char* and TCHAR*
inline bool get_home(T& val) { // return true if OK, false otherwise
#if defined (__linux) || (__unix)
val = getenv("HOME");
if (val) return true;
else return false;
#elif defined (WINDOWS) || defined (_WIN32) || defined (WIN32)
// something like the MS Code above
#else
// probably I'll just return false here.
#endif
}

因此,我必须在堆上进行全局分配或在调用函数中执行 #ifdef 以释放内存。不是很漂亮。

当然,我可以首先在堆栈上分配“buff”,但如果“buff_size”不够大,我就必须创建一个新的 TCHAR[]在我第一次调用 GetEnvironmentVariable 时。更好,但是如果我是一个 Nerd 并且不想到处创建多余的数组怎么办?关于更美观的东西有什么想法吗?

我不是那么有见识,所以有人会嫉妒我故意强制 GetEnvironmentVariable 失败以获得字符串大小吗?有没有人看到以下问题:

const DWORD buff_size = GetEnvironmentVariable("HOME",0,0);
TCHAR buff[buff_size];
const DWORD ret = GetEnvironmentVariable("HOME",buff,buff_size);
// ...

还有其他想法或建议吗? (或更正明显的错误?)

更新:下面有很多有用的信息。我认为我正在尝试做的最好的选择是使用 static char[] ,例如:

inline const char* get_home(void) { // inline not required, but what the hell.
#if defined (__linux) || (__unix)
return getenv("HOME");
#elif defined (WINDOWS) || defined (WIN32) || defined (_WIN32)
static char buff[MAX_PATH];
const DWORD ret = GetEnvironmentVariableA("USERPROFILE",buff,MAX_PATH);
if (ret==0 || ret>MAX_PATH)
return 0;
else
return buff;
#else
return 0;
#endif
}

也许这不是最优雅的方式,但它可能是在 *nix 和 Windows 之间同步我想做的事情的最简单方式。 (稍后我还会担心 Unicode 支持。)

感谢所有帮助过的人。

最佳答案

DWORD bufferSize = 65535; //Limit according to http://msdn.microsoft.com/en-us/library/ms683188.aspx
std::wstring buff;
buff.resize(bufferSize);
bufferSize = GetEnvironmentVariableW(L"Name", &buff[0], bufferSize);
if (!bufferSize)
//error
buff.resize(bufferSize);

当然,如果您想要 ASCII,请将 wstring 替换为 string 并将 GetEnvironmentVariableW 替换为 GetEnvironmentVariableA

编辑:您也可以自己创建 getenv。这是有效的,因为

The same memory location may be used in subsequent calls to getenv, overwriting the previous content.

const char * WinGetEnv(const char * name)
{
const DWORD buffSize = 65535;
static char buffer[buffSize];
if (GetEnvironmentVariableA(name, buffer, buffSize))
{
return buffer;
}
else
{
return 0;
}
}

当然,如果您想保持 unicode 支持,使用所有这些的宽字符版本可能是个好主意。

关于c++ - 如何尽可能干净地使用 VS C++ GetEnvironmentVariable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4130180/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com