31

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

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

如果我将其写入控制台,我会看到它是成功的。

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

知道为什么吗?

4

10 回答 10

48

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

它是通过注册表完成的。

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

HKLM\SYSTEM\CurrentControlSet\Services\YourService

创建一个名为 Environment 的 REG_MULTI_SZ。

现在您可以添加条目,例如...

Var1=Value1
Var2=Value2

这些将可用于服务代码。

如果您使用 Windows 资源工具包将脚本安装为服务(instsrv.exe 和 srvany.exe),那么您可以再次选择为服务设置环境变量,但很可能是错误的,因为这些将用于 srvany.exe。

相反,您使用密钥...

HKLM\SYSTEM\CurrentControlSet\Services\YourService\Parameters

并创建一个名为 AppEnvironment 的 REG_MULTI_SZ

以相同的方式设置条目。

现在您的脚本服务拥有自己的环境变量。

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

反正。我希望这会有所帮助。

我认为,主要是,您不会向全局环境添加不必要的 env_vars。当您拥有超过 1 个时,您可以使它们具有针对性和独特性。

问候,

理查德。

于 2010-04-28T10:22:05.427 回答
25

您的问题似乎与我们经历过的类似,并且很难弄清楚发生了什么。

发生的情况是,当环境变量被添加/删除/更改时,服务环境在“重新启动”之前不会识别这一点。这是因为这些环境变量存储在注册表中,并且该注册表仅被服务环境读取一次......在系统启动时。

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

查看有关此的Microsoft KB

于 2008-11-20T17:03:49.503 回答
6

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

于 2008-11-20T16:19:58.907 回答
3

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

添加 TIP_HOME 变量后是否重新启动了机器?

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

于 2008-11-20T17:21:49.170 回答
1

您知道系统用户环境变量吗?默认情况下,Windows 服务在系统帐户下运行。

于 2008-11-20T16:36:51.913 回答
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);
}
于 2008-11-20T17:13:42.947 回答
1

试试这个代码字符串 getsyspath = System.Environment.GetEnvironmentVariable("TIP_HOME",EnvironmentVariableTarget.Machine);

于 2009-10-15T10:34:51.340 回答
1

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

Environment.GetEnvironmentVariable 方法(字符串,EnvironmentVariableTarget)

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

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

如果您将信息存储为机器或用户,那么您可以在运行时对其进行测试 Run (Win + R): %TIP_HOME%

希望能帮助到你 :)

于 2013-06-16T06:56:01.440 回答
1

服务通常在三个服务帐户之一下运行,Local Service Local System并且Network 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'。如果它使用您的用户帐户,它将可以访问您通常可以访问的所有环境变量。
在此处输入图像描述. 在此处输入图像描述

于 2015-03-21T00:19:44.030 回答
0

我将那行代码修改为:

字符串 t = System.Environment.GetEnvironmentVariable("TIP_HOME", EnvironmentVariableTarget.Machine);

我可以查看我的注册表并查看 TIP_HOME 是否已设置。

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

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

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

于 2008-11-20T16:40:50.377 回答