2008-11-20 174 views
20

我正在嘗試在C#中編寫Windows服務。我需要找到某個文件的路徑,該文件存儲在一個環境變量中。在一個常規的C#控制檯應用程序,我可以做到這一點下面的行:從Windows服務訪問環境變量

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

如果我寫的控制檯我看它是成功的。

現在,如果我在Windows服務中嘗試使用相同的代碼,字符串t爲空。

任何想法爲什麼?

回答

6

該服務可能運行在不同的帳戶下,並且沒有獲得相同的環境變量。

+0

我想我應該澄清這一點,但TIP_HOME是一個系統變量。我認爲系統變量不是用戶特定的? – Brian 2008-11-20 16:22:16

+0

那麼,作爲一個測試,您可以將調試代碼添加到您的服務中,讓它遍歷啓動時看到的所有環境變量並將它們輸出到臨時文件。 – EBGreen 2008-11-20 16:26:38

0

您是否知道系統用戶環境變量?默認情況下,Windows服務在系統帳戶下運行。

+0

是的,我正在尋找的變量是一個系統變量。看到我在下面發佈的答案。 – Brian 2008-11-20 16:41:41

0

我修改該代碼行這樣:

串T = System.Environment.GetEnvironmentVariable( 「TIP_HOME」,EnvironmentVariableTarget.Machine);

我可以查看我的註冊表並查看TIP_HOME已設置。

這是來自MSDN: 機器:環境變量存儲或從Windows操作系統註冊表中的HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session Manager \ Environment鍵中檢索。

用戶變量存儲在註冊表中的其他地方..

該字符串仍然顯示了空當我與這個變化運行服務,雖然。

+0

您是否按照我的建議嘗試列舉env變量? – EBGreen 2008-11-20 16:45:14

+0

我想弄清楚如何..我對C#很新,只需要它爲這個小項目。 – Brian 2008-11-20 16:50:59

18

你的問題似乎是我們經歷過的事情,可能非常難以弄清楚發生了什麼事情。

當環境變量被添加/刪除/更改時,會發生什麼情況,服務環境在「重新啓動」之前不會識別此項。這是因爲這些環境變量存儲在註冊表中,並且此註冊表是只讀一次由服務環境...在系統啓動

這意味着爲了讓服務獲取環境變量的變化,需要重新啓動系統。

看看這個Microsoft KB

+3

但請注意,這僅適用於在本地系統帳戶下運行的服務。對於在指定用戶帳戶下運行的服務,它們將在重新啓動後從註冊表中選取環境更改。 – 2011-06-30 14:58:42

1

好吧,我不很明白這一點,但這裏是我發現..

在相同的服務,我第一次嘗試了我前面描述和字符串返回空。

然後,如果我通過每個系統級環境變量進行枚舉,它會發現我正在尋找的變量。

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); 
} 
1

你是在本地系統帳戶下運行的服務:

這裏是一個代碼段,稍有在MSDN上找到一些示例代碼修改?

添加TIP_HOME變量後,您是否重新啓動機器?

服務本地系統下運行得到從Services.exe的服務,只在啓動時讀取它的環境開始:http://support.microsoft.com/kb/821761

1

試試這個代碼 串getsyspath = System.Environment.GetEnvironmentVariable(「TIP_HOME」 EnvironmentVariableTarget.Machine);

28

我不知道這是否有用,但我發現對於每個服務,都有一個選項可以將環境變量直接添加到服務中。

它通過註冊表完成。

說,關鍵看你的服務是...

HKLM \系統\ CurrentControlSet \服務\ YourService

創建一個名爲REG_MULTI_SZ環境。現在

您可以添加條目一樣......

Var1=Value1 
Var2=Value2 

而這些將提供給服務代碼。

如果您使用Windows資源工具包將腳本安裝爲服務(instsrv.exe和srvany.exe),那麼您可以再次選擇爲服務設置環境變量,但最有可能的是錯誤的一個,因爲這些將是srvany.exe。

相反,你用鑰匙...

HKLM \系統\ CurrentControlSet \服務\ YourService \參數

,並創建一個名爲AppEnvironment

設置以同樣的方式條目REG_MULTI_SZ。

現在你的腳本服務有它自己的環境變量。

我在PHP + WinCache中使用這些技巧,允許我爲每個服務設置唯一的APP_POOL_ID,它允許WinCache爲所有「線程」共享一箇中央緩存(基於APP_POOL_ID)(使用WShell啓動non-阻止孩子「線程」,並仍然與啓動程序共享相同的WinCache,從而允許簡單的進程間通信)。

無論如何。我希望這有些幫助。

我認爲,主要的是,您不會在全球環境中添加不必要的env_vars。你可以讓他們針對性的,獨特的,當你有超過1

問候,

理查德。

1

您需要檢查變量的存儲方式。 有用於Set/GetEnvironmentVariable的重載方法:

Environment.GetEnvironmentVariable Method (String, EnvironmentVariableTarget)

的事情是,有三種類型的存儲環境變量(EnvironmentVariableTarget)的:(適用於所有用戶)

  • 用戶(可用於當前用戶)
  • 過程(僅適用於當前過程[不推薦btw])

如果存儲的信息爲計算機或用戶,那麼你可以測試它的運行運行(WIN + R):%TIP_HOME%

希望它能幫助:)

0

服務通常是下運行三個服務帳戶之一,Local ServiceLocal 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 hereenter image description here