跨语言共享环境变量

时间:2019-10-31 10:50:10

标签: c# c++ windows environment-variables

我正在编写一个由以不同语言(即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文件夹

2 个答案:

答案 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://social.msdn.microsoft.com/Forums/en-US/c27a6623-6f57-4c7e-be9b-6dd35d362872/sharing-environment-variables-across-languages?forum=windowsgeneraldevelopmentissues

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