2

在 Windows 上,我有一个 COM 可见的 C# 程序集。它引用其他程序集来控制机器中的应用程序。它工作正常。

但是,在 Apache Web Server 和使用 CGI 下,它不起作用。在做了一些调试之后,我发现问题在于,在 Apache 的 CGI 下运行时,引用的程序集显然需要的环境变量 SYSTEMROOT 和 SYSTEMDRIVE 没有加载。

我也可以将 Apache 配置为传递那些 environemtn 变量,但在这样做之前,我真的很想知道是否有一些命令可以放在我的 C# COM 可见程序集上,使其像加载环境变量一样加载环境变量,比方说, SYSTEM 用户或类似的用户,因此它不必中继启动应用程序传递的环境。

当当前进程中没有设置它(或者它被启动进程删除了)时,如何在 C# 中强制加载现有的系统环境变量?

在此先感谢您的任何建议!

编辑 1 - 添加信息:只是为了让它更清楚(正如我在当前答案中看到的那样,它不是很清楚):Apache 有意为 CGI 进程删除了很多环境变量。不是 Apache 看不到它们,它可以,但它不会将它们传递给 CGI 进程。

4

5 回答 5

2

这应该可以解决问题:

Environment.GetEnvironmentVariable("variable", EnvironmentVariableTarget.Machine);

我做了一个小测试,它正在工作:

        //has the value
        string a = Environment.GetEnvironmentVariable("TMP");

        Environment.SetEnvironmentVariable("TMP", null);

        //does not have has the value
        a = Environment.GetEnvironmentVariable("TMP");

        //has the value
        a = Environment.GetEnvironmentVariable("TMP", EnvironmentVariableTarget.Machine);
于 2013-03-29T04:17:54.513 回答
2

解决方案: Marco 的回答很好,从技术上回答了我的问题 - 除了我发现环境变量 SYSTEMROOT 和 SYSTEMDRIVE 并没有真正在设置了所有环境变量的注册表中设置,因此,选择的答案适用于除这两个变量之外的所有变量,我在 OP 中指定。

SYSTEMROOT 在 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot 的注册表中定义,显然(经过更多研究),SYSTEMDRIVE 是作为 SYSTEMDRIVE 的子字符串生成的。

因此,要从注册表中获取 SYSTEMDRIVE 和 SYSTEMROOT 并将它们加载到环境中:

using Microsoft.Win32;

namespace MySpace
{
    public class Setup
    {
        public Setup()
        {
            SetUpEnvironment();
        }
        private void SetUpEnvironment()
        {
            string test_a = Environment.GetEnvironmentVariable("SYSTEMDRIVE", EnvironmentVariableTarget.Process);
            string test_b = Environment.GetEnvironmentVariable("SYSTEMROOT", EnvironmentVariableTarget.Process);
            if (test_a == null || test_a.Length == 0 || test_b == null || test_b.Length == 0)
            {
                string RegistryPath = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
                string SYSTEMROOT = (string) Registry.GetValue(RegistryPath, "SystemRoot", null);
                if (SYSTEMROOT == null)
                {
                    throw new System.ApplicationException("Cannot access registry key " + RegistryPath);
                }
                string SYSTEMDRIVE = SYSTEMROOT.Substring(0, SYSTEMROOT.IndexOf(':') + 1);
                Environment.SetEnvironmentVariable("SYSTEMROOT", SYSTEMROOT, EnvironmentVariableTarget.Process);
                Environment.SetEnvironmentVariable("SYSTEMDRIVE", SYSTEMDRIVE, EnvironmentVariableTarget.Process);
            }
        }
    }
}

然后你可以Setup setup = new Setup();从其他班级打电话。就是这样。:-)

于 2013-03-29T06:18:22.000 回答
1
Environment.GetEnvironmentVariable

请参阅此处的参考资料。

例如

Environment.CurrentDirectory = Environment.GetEnvironmentVariable("windir");        
DirectoryInfo info = new DirectoryInfo(".");
lock(info)
{      
    Console.WriteLine("Directory Info:   "+info.FullName);
}
于 2013-03-29T03:30:59.160 回答
0

变量是否设置为系统范围?

如果不是,那就是您需要做的,否则为运行 COM 的用户创建用户变量。

于 2013-03-29T03:27:31.140 回答
0

谢谢你。我不能肯定地说这已经一劳永逸地刺穿了吸血鬼的心脏,但令人惊讶的是,错误已经消失了(现在)。奇怪的是访问语句

Environment.GetEnvironmentVariable("variable", EnvironmentVariableTarget.Machine);

是调试器中的一个真正奇怪的地方。它没有出现在 Intellisense 中,甚至没有出现触发,这让我怀疑,你们都知道,这是某种神奇的运行时对象Environment,在调试器中没有实例化,但也可以良性跳转超过。那好吧。

哦,我应该提一下,在您看到该错误后,您会注意到 Windows 操作系统中的异常情况,这令人担忧。特别是,您将看到,如果您尝试使用控制面板/系统/高级属性(无论如何)它无法再加载环境变量的对话框,这表明%windir% 已被严重破坏(妥协)所有应用程序。坏坏坏....

于 2013-11-12T01:13:36.403 回答