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 Resource ToolKit を使用してスクリプトをサービス (instsrv.exe および srvany.exe) としてインストールする場合も、サービスの環境変数を設定するオプションがありますが、ほとんどの場合、これらの環境変数は間違っています。 srvany.exe 用です。

代わりに、キーを使用します...

HKLM\SYSTEM\CurrentControlSet\Services\YourService\Parameters

AppEnvironment という REG_MULTI_SZ を作成します。

同様にエントリを設定します。

これで、スクリプト サービスに独自の環境変数が追加されました。

私は PHP+WinCache でこれらの手法を使用して、各サービスに固有の APP_POOL_ID を設定できるようにしています。これにより、WinCache はすべての「スレッド」の中央キャッシュ (APP_POOL_ID に基づく) を共有できます (WShell を使用してノンブロッキングの子スレッドを起動します)。 " ランチャーと同じ WinCache を共有し、単純化されたプロセス間通信を可能にします)。

ともかく。これが多少役立つことを願っています。

主に、不要な env_vars をグローバル環境に追加していないと思います。複数ある場合は、ターゲットを絞って一意に保つことができます。

よろしく、

リチャード。

于 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

このコード文字列を試してくださいgetsyspath=System.Environment.GetEnvironmentVariable( "TIP_HOME"、EnvironmentVariableTarget.Machine);

于 2009-10-15T10:34:51.340 に答える
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

変数がどのように格納されたかを確認する必要があります。Set/GetEnvironmentVariable のオーバーロード メソッドがあります。

Environment.GetEnvironmentVariable メソッド (文字列、EnvironmentVariableTarget)

問題は、環境変数 ( EnvironmentVariableTarget )の格納には 3 つのタイプがあるということです。

  • マシン (すべてのユーザーが利用可能)
  • ユーザー (現在のユーザーが利用可能)
  • プロセス (現在のプロセスでのみ使用可能 [お勧めしません])

情報を Machine または User として保存する場合は、Run (Win + R): %TIP_HOME% を実行してテストできます。

それが役に立てば幸い :)

于 2013-06-16T06:56:01.440 に答える
1

システムユーザーの環境変数を認識していますか? デフォルトでは、Windows サービスはシステムアカウントで実行されます。

于 2008-11-20T16:36:51.913 に答える
1

通常、サービスは 3 つのサービス アカウントのいずれかで実行され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 からのものです: Machine: 環境変数は、Windows オペレーティング システム レジストリの HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment キーに格納または取得されます。

ユーザー変数は、レジストリの別の場所に保存されます。

ただし、この変更を加えてサービスを実行すると、文字列はまだ空で表示されます。

于 2008-11-20T16:40:50.377 に答える