【问题标题】:Environment variables not visible to java环境变量对 java 不可见
【发布时间】:2012-05-10 07:59:55
【问题描述】:

项目

该项目是一个用于测试自动化的大型 C# 项目。为此,我必须使用 java-tool,该工具将所有结果保存到可以加载到测试环境中的文件中。

界面

我从测试环境供应商那里得到了一个用 C++ 构建的 DLL,这个 dll 加载 java 环境并加载 jar 文件。

现状

java环境加载成功,用C#中的环境变量配置了这个方法:

String java = GetJavaInstallationPath();
Environment.SetEnvironmentVariable("PATH", String.Format("{0};{1}", Environment.GetEnvironmentVariable("PATH"), Path.Combine(java, @"bin\client")), EnvironmentVariableTarget.Process);

在此之后,我使用以下代码设置 java 类的路径:

Environment.SetEnvironmentVariable("ITEPCLASSPATH",
                String.Format("{0};{1}",
                Path.Combine(iTepPath, "itep.jar"),
                Path.Combine(iTepPath, "libs\\itorx.jar")), EnvironmentVariableTarget.Process);

这实际上应该起作用,它在使用 Environment.GetEnvironmentVariable("ITEPCLASSPATH") 时显示正确的值,但 C++-DLL 告诉我它不起作用。

使用外部 bat 文件设置类路径时,它可以工作。更多事实:

  • 应用由bat文件启动
  • 路径是从我生成的 dll 路径复制而来的
  • 我什么都不注释掉,所以路径还是C#设置的

似乎 java 没有访问我在 C# 中设置的 env.-variable,但识别出我在 bat 文件中设置了它。

我确实需要通过 C# 设置变量,我该如何存档?

【问题讨论】:

  • 一种解决方法是从 c# 使用 System.IO.Process.Start 启动 bat 文件。你真的需要使用DLL吗?否则,请尝试找出环境是如何通过 dll 传递的。我不明白为什么它不起作用。我认为应该。
  • @DarenThomas 这是一种解决方法,但会为我做更多的工作。 :-/ 当然,我必须使用 DLL,并且无法访问这些 DLL 的代码。
  • 有问题的DLL什么时候初始化?也许它会读取环境。变量并记住值,然后再在代码中设置值。
  • @Matej 在设置所有变量后,我使用 Kernel32.dll 方法 LoadLibrary 初始化 DLL。
  • 如果 Environment.GetEnvironmentVariables() 是由批处理文件启动/不是由批处理文件启动,您是否会在 C# 应用程序中获得相同的输出?

标签: c# java environment-variables


【解决方案1】:

它没有明确写在Microsoft System.Environment documentation 中,但目标值Process 似乎仅将范围限制为当前进程。默认情况下,the CreateProcess method 继承子进程的当前进程环境。也许那里使用的参数会破坏这种默认行为。

所以我建议你先在SetEnvironmentVariable 中使用EnvironmentVariableTarget.User 进行测试,看看它是否效果更好。

顺便说一句,我认为您将不得不进一步诊断环境变量并使用Process Monitor 之类的工具创建流程操作。

【讨论】:

  • 这个过程是一样的,但是在设置了环境之后。具有不同目标的变量它可以工作。但这仍然不能回答为什么它使用 bat 文件而不是 Environment.SetEnvironmentVariable 的问题,因为 bat 仅限于当前进程(AFAIK)。
  • 进程不一样——C#创建了一个子进程来运行JVM,对吧? “bat”文件将以“正确的方式”调用 CreateProcess,我的意思是使用默认选项,因此您可以获得预期的行为:环境变量是为子进程继承的。 C# 代码可以使用替代选项,结果是创建的 JVM 进程作为其他环境变量。所以我的想法是使用 Process Monitor 进行诊断。
  • 不,只有一个进程,JVM与C#进程在同一个进程中运行。我检查了这个。
  • 所以可能 JVM 在 C# 代码更改之前已将环境变量加载到某种缓存中。在正常使用中,它们不应在过程寿命期间发生变化。您是否尝试过没有目标的 Environment.SetEnvironmentVariable ?您是否使用 Process Monitor 跟踪环境变量的操作?
  • 设置变量后初始化JVM。不,我没有,也许我会尝试一下,但我认为它针对的是 Process。
【解决方案2】:

确保环境变量适用于每个目标:进程、用户和机器。请参阅此MSDN 文章。

// Set the environment variable for the default target (the current process).
Console.WriteLine(fmt2x, "(default)", myVarA, existsA);
Environment.SetEnvironmentVariable(myVarA, existsA);

// Set the environment variable for the the current process.
Console.WriteLine(fmt2x, "Process", myVarB, existsB);
Environment.SetEnvironmentVariable(myVarB, existsB, 
    EnvironmentVariableTarget.Process);

// Set the environment variable for the the current user.
Console.WriteLine(fmt2x, "User", myVarC, existsC);
Environment.SetEnvironmentVariable(myVarC, existsC, 
    EnvironmentVariableTarget.User);

// Set the environment variable for the the local machine.
Console.WriteLine(fmt2x, "Machine", myVarD, existsD);
Environment.SetEnvironmentVariable(myVarD, existsD, 
    EnvironmentVariableTarget.Machine);

【讨论】:

    【解决方案3】:

    Java 允许您使用以下方式将环境变量作为参数传递:

    java -DMYPROP=MYVALUE myclass.class
    

    参数语法。查看 -D 标志。

    然后,这些系统属性将应用于该 JVM 进程实例。那岂不是比尝试修改操作系统环境更简单?

    【讨论】:

    • 如果java工具是第三方的,不管好坏都得使用实现者提供的方法。
    • 顺便说一句,选项 -D 在 Java 中设置了一个系统属性,该属性可以通过与环境变量相同的 API 访问...
    猜你喜欢
    • 1970-01-01
    • 2021-06-29
    • 1970-01-01
    • 2021-07-11
    • 2021-05-03
    • 2021-06-15
    • 2016-01-28
    • 2016-08-11
    • 1970-01-01
    相关资源
    最近更新 更多