2009-01-06 198 views
7

我正在C#中編寫一個應用程序,該應用程序需要作爲服務運行,但也有用戶交互。我知道服務沒有UI等,所以我將我的程序分成了一個windows窗體應用程序和一個可以相互通信的服務。C#從服務(和Vista中)運行Windows窗體應用程序

我遇到的問題是我需要該服務來確保窗體窗體應用程序始終運行並重新啓動它,如果它不是。我能檢測是否正在運行,並與在Windows 2000/XP下面的代碼重新啓動:

System.Diagnostics.Process.Start("ExePath"); 

,但在Vista上運行新的過程作爲一個本地/系統的過程,是不可見的用戶。有人解決這個問題嗎?有什麼方法可以檢測當前登錄哪個用戶並以該用戶身份運行新進程?此時我不需要考慮快速用戶切換。東西 - 任何東西 - 基本就足夠了。

如果您有任何關於此主題的幫助或建議,我將不勝感激。

我需要說明的是,我在安裝服務時設置了「允許服務與桌面交互」選項。這就是它允許它在2000/XP上工作的原因。但是,Vista仍然有上述問題。

+0

我錯過了什麼嗎?如果你有一個始終在運行的服務......爲什麼你的Windows窗體應用程序正在運行會影響它? – bobwienholt 2009-01-06 21:02:26

+0

因爲我需要一種服務直接與用戶溝通的方式。這有很多原因,但最基本的例子是升級通知。 – 2009-01-06 21:07:22

+1

我與其他人在這裏...我懷疑你正在採取錯誤的方法解決你想解決的任何問題。如果你必須擁有一個UI,那麼你可能不應該使用服務模型。也許是系統托盤中的東西......? – 2009-01-06 21:08:23

回答

13

這種事情的總體思路是,如果用戶需要與服務交互,他們應該啓動一個單獨的應用程序。如果你想幫助他們,你可以通過在啓動菜單中放置一個快捷方式來配置單獨的應用程序以啓動窗口。您還可以將崩潰恢復構建到應用程序中,以便它可以自動重新啓動。

你不應該真的依靠監視窗體應用程序,如果沒有人登錄會怎麼樣?如果多人登錄會怎麼樣?這樣做會讓事情變得凌亂。

讓服務只坐在那裏並向聽衆廣播是一條路。當表單應用程序啓動時,它可以通知它想要監聽事件的服務。

+0

正如我在上面的評論中提到的,我需要該服務能夠直接通知用戶某些事件。如果有辦法解決我所描述的問題,或者有更好的方法來實現這個目標,我會很開心的。 – 2009-01-06 21:12:37

+1

你應該讓你的表單應用程序自動啓動。然後它會通知它正在偵聽更新的服務。 – Bob 2009-01-06 21:16:11

+0

我想我必須接受這一點。我真的希望有一種方法可以重新啓動服務。 – 2009-01-06 21:21:58

2

在這種情況下,您必須有第三個監視進程,它檢測程序是否失敗並在此情況下重新啓動它。

但是,最終會出現無法解決的問題,因爲必須監視監視進程以確保它不會關閉,等等,等等。

您可能想重新考慮這種方法。

0

在Windows 2000和XP中,服務屬性窗口的「登錄」選項卡上有一個選項(複選框),以允許服務與桌面進行交互。我相信這是你正在尋找的。我剛剛在VB.NET中用Process.Start(「calc.exe」)編寫了一個快速服務,並且Windows計算器打開得很好。

我不是100%確定這在Vista中的工作方式是相同的。

0

聽起來像你可能不需要它作爲服務運行的一半(除非需要更高的權限),因爲當沒有交互式用戶登錄時服務需要應對。

1

這是一個艱難的情況。正如在幾個地方提到的,如果你的必須有有一個用戶界面,那麼在技術上你不應該使用一個服務。畢竟,即使登錄,用戶也無需用戶即可運行。如果沒有人登錄,則不能擁有用戶界面。

通常,當我需要一個服務需要與外界溝通時,我選擇了兩件事。我可以將條目放入事件日誌中,也可以將消息放入隊列中。

在你的情況下,我會使用一個隊列。當用戶登錄時,您可以爲監控隊列的用戶自動啓動應用程序。如果應用程序正在運行,收到消息時,它們也會以這種方式發出警報。但是,如果用戶關閉應用程序,則會發生同樣的事情......他們不知道。

1

首先,快速回答:'允許服務與桌面交互'選項(服務 - >屬性 - >登錄)還是指定一個帳戶允許你想要什麼?如果是這樣,這些都可以在您的服務安裝程序類上進行配置。

像其他人一樣,我懷疑有更好的方法來解決這個問題,並且以下兩種情況都是正確的: - 服務中的代碼可以包含在winforms應用程序中(可能運行在後臺線程中),添加到Windows啓動。兩者都將運行 -winforms應用程序可以在服務開啓時收聽服務,並且不需要從服務啓動。或者類似地,該應用程序可以添加到啓動。

1

爲了讓您的服務運行應用程序的用戶(這似乎是你正在嘗試做的),你需要做到以下幾點:

System.Security.SecureString ss = new System.Security.SecureString(); 

foreach (char c in password) 
    ss.AppendChar(c); 

System.Diagnostics.Process proc = Process.Start(path, arguments, username, ss, domain); 

其中:

  • 路徑=完整路徑(包括文件名)的可執行文件。
  • 參數=的參數字符串,如果您使用的是網絡帳戶 - 如果空白(使用空字符串是沒有的)
  • 用戶名=您的服務器/計算機
  • 域上的用戶帳戶的名稱=您的網絡域(無)

此外,爲了讓您的服務有權啓動應用程序,它也必須作爲服務運行。要做到這一點,您需要將這些行添加到服務安裝程序類中:

serviceProcessInstaller.Account = ServiceAccount.User; 

serviceProcessInstaller.Username = "yourdomain\\yourAccountName"; //Or just "AccountName" for local accounts..    

serviceProcessInstaller.Password = "yourPassword"; 
相關問題