我正在编写一个由以不同语言(即Java,C#,C ++)编写的多个模块组成的应用程序。 我遇到一种奇怪的行为,即我在一个模块(例如C#)中设置的环境变量没有传播到其他模块。 据我了解,问题是由于Windows中的环境变量是通过运行时库中的_environ结构而不是通过进程描述符访问的,因此使用不同运行时的库具有不同的环境变量。
特别是对于C#,仅当我在Release中编译并运行代码时,才会出现此问题,而在Debug中编译代码就可以了。
下面的代码使用两个非常简单的用C#和C ++编写的模块来重现该问题。我用VS2015 Professional编译了代码。 C#代码是使用运行时v4.0和.NET Framework v4.5.2编译的
C#可执行文件
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
[DllImport("cpp_lib.dll", CharSet = CharSet.Unicode)]
public static extern void print_path();
static void Main(string[] args)
{
var path = Environment.GetEnvironmentVariable("PATH");
path += ";D:\\Temp";
Environment.SetEnvironmentVariable("PATH", path);
// Print the path from C#
Console.WriteLine("Path from C#: " + Environment.GetEnvironmentVariable("PATH"));
// Print the path from c++
print_path();
}
}
}
C ++库
#include <iostream>
#include <Windows.h>
extern "C" {
__declspec(dllexport) void print_path() {
std::cout << "PATH seen in C++: " << getenv("PATH") << std::endl;
}
}
如前所述,在Debug中运行代码会从C#和C ++打印相同的路径,但是在Release中运行代码会导致从c ++打印的PATH中缺少D:\ Temp文件夹
答案 0 :(得分:1)
用户环境变量是按进程的,更改不会传播到其他进程。
在示例PATH
中更改系统环境变量。您需要修改注册表项HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment
下的值,然后广播WM_SETTINGCHANGE
消息。希望看到更改的应用程序必须处理广播。
来源:https://docs.microsoft.com/en-us/windows/win32/procthread/environment-variables
答案 1 :(得分:1)
事实证明Windows提供了更多的功能来获取环境变量。 从文档“ getenv和_putenv使用全局变量_environ指向的环境的副本来访问环境。” 而GetEnvironmentVariable “从环境块中检索指定变量的内容。调用过程。” 从这些语句中,GetEnvironmentVariable看起来是最安全的选择,用GetEnvironmentVariable代替getenv确实可以解决问题。
参考文献:
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/getenv-wgetenv?view=vs-2019
https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getenvironmentvariable