从Windows服务访问环境变量

时间:2008-11-20 16:17:46

标签: c# windows-services permissions

我正在尝试用C#编写Windows服务。我需要找到某个文件的路径,该文件存储在环境变量中。在常规的C#控制台应用程序中,我可以使用以下行来实现:

string t = System.Environment.GetEnvironmentVariable("TIP_HOME");

如果我把它写到控制台,我发现它是成功的。

现在,如果我在Windows服务中尝试相同的代码,则字符串t为空。

知道为什么吗?

10 个答案:

答案 0 :(得分:29)

我不知道这是否有用,但我发现对于每项服务,都可以选择将环境变量直接添加到服务中。

通过注册表完成。

说服务的关键是......

HKLM \系统\ CurrentControlSet \服务\ YourService

创建一个名为Environment的REG_MULTI_SZ。

现在您可以添加像......

这样的条目
Var1=Value1
Var2=Value2

这些将可用于服务代码。

如果您使用Windows Resource ToolKit将脚本作为服务安装(instsrv.exe和srvany.exe),那么,您可以选择为服务设置环境变量,但很可能是错误的一个,因为这将是srvany.exe。

相反,你使用密钥......

HKLM \系统\ CurrentControlSet \服务\ YourService \参数

并创建一个名为AppEnvironment的REG_MULTI_SZ

以相同的方式设置条目。

现在你的脚本服务有它自己的环境变量。

我在PHP + WinCache中使用这些技术,允许我为每个服务设置唯一的APP_POOL_ID,允许WinCache为所有“线程”共享中央缓存(基于APP_POOL_ID)(使用WShell启动非阻塞子“线程”仍然与启动器共享相同的WinCache,允许简单的进程间通信。

反正。我希望这有点帮助。

我认为,总的来说,你没有在全球环境中添加不必要的env_vars。当你有超过1时,你可以保持目标和唯一。

此致

理查德。

答案 1 :(得分:18)

你的问题似乎与我们经历过的一样,并且可能非常难以弄清楚发生了什么。

当添加/删除/更改环境变量时,服务环境在“重新启动”之前无法识别此情况。这是因为这些环境变量存储在注册表中,并且此注册表由服务环境只读一次 ...在系统启动

这意味着为了使服务能够获取环境变量的变化,需要重新启动系统。

查看Microsoft KB

答案 2 :(得分:6)

该服务可能在不同的帐户下运行,并且没有获得相同的环境变量。

答案 3 :(得分:1)

好的,我不太明白这一点,但这是我发现的......

在同一个服务中,我首先尝试我之前描述的内容,字符串返回空。

然后,如果我枚举每个系统级环境变量,它会找到我正在寻找的变量。

以下是一段代码片段,稍微修改了MSDN上的一些示例代码:

foreach(DictionaryEntry de in Environment.GetEnvironmentVariables(tgt))
{
    key   = (string)de.Key;
    value = (string)de.Value;

    if(key.Equals("TIP_HOME") && value != null)
        log.WriteEntry("TIP_HOME="+value, EventLogEntryType.Information);
}

答案 4 :(得分:1)

您是否在本地系统帐户下运行该服务?

添加TIP_HOME变量后,您是否重新启动了计算机?

在本地系统下运行的服务从services.exe服务启动,该服务仅在启动时读取其环境:http://support.microsoft.com/kb/821761

答案 5 :(得分:1)

试试这段代码  string getsyspath = System.Environment.GetEnvironmentVariable(“TIP_HOME”,EnvironmentVariableTarget.Machine);

答案 6 :(得分:1)

您需要检查变量的存储方式。 有Set / GetEnvironmentVariable的重载方法:

Environment.GetEnvironmentVariable Method (String, EnvironmentVariableTarget)

问题是,存储环境变量有三种类型(EnvironmentVariableTarget):

  • 机器(适用于所有用户)
  • 用户(适用于当前用户)
  • 流程(仅适用于当前流程[不推荐顺便说一句])

如果您将信息存储为计算机或用户,则可以将其测试为正在运行的运行(Win + R):%TIP_HOME%

希望有所帮助:)

答案 7 :(得分:0)

您是否了解系统用户环境变量?默认情况下,Windows服务在系统帐户下运行。

答案 8 :(得分:0)

我修改了这行代码:

string t = System.Environment.GetEnvironmentVariable(“TIP_HOME”,EnvironmentVariableTarget.Machine);

我可以查看我的注册表,看看TIP_HOME已设置。

这是来自MSDN: 计算机:从Windows操作系统注册表中的HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session Manager \ Environment键存储或检索环境变量。

用户变量存储在注册表的其他位置..

但是,当我使用此更改运行服务时,字符串仍然显示为空。

答案 9 :(得分:0)

服务通常在三个服务帐户之一Local Service Local SystemNetwork Service下运行。对于所有这些,您的典型环境变量将 null


调查


我通过让服务编写事件日志条目进行测试,并打印它存储在HOMEPATH变量中的内容。它为服务帐户返回空。在C#中:

protected override void OnStart(string[] args)
{
    EventLog.WriteEntry("The HomePath for this service is '" + Environment.GetEnvironmentVariable("HOMEPATH") + "'", EventLogEntryType.Information);
}

可能的解决方案


您可以在服务属性窗口或服务安装配置中设置服务使用的帐户(例如您的用户帐户)。当我使用我的用户帐户测试时,事件日志条目显示为The HomePath for this service is '\Users\Admin-PC'。如果它使用您的用户帐户,则可以访问您通常可以访问的所有环境变量  enter image description here。  enter image description here