2010-07-07 82 views
4

我從Windows服務中使用如何獲取當前記錄的用戶會話ID?

ProcessStartInfo processStartInfo = new .... 
Process.Start(processStartInfo); 

的問題是運行過程中,如果我在本地系統帳戶下運行的服務,它運行正常的,但它並不顯示程序窗口。 我試圖把用戶憑據放在服務屬性中,但'允許服務與桌面交互'複選框變爲禁用狀態。

我真的需要運行應用程序從服務調用它,我真的需要看到應用程序的窗口。

請幫助我。

UPD。那麼,你使用過載的版本的Process.Start需要用戶名,密碼和域 - 它會將程序拖到桌面上。但現在它啓動應用程序在一個憑據下,但顯示在不同的用戶的桌面上。怎麼來的?

UPD2:我有個主意!我可以使用Sysinternals Suite中的psexec.exe。但問題是我需要以「管理員」的身份默默地開始這件事。我不知道如何。 我的意思是,即使你已經擁有管理員權限,有時你也必須手動說出「以管理員身份運行」,確認UAC並且只有在你準備好後才能進行。我不知道如何靜靜地運行一些東西,但不帶UAC的東西......

UPD3:親愛的主。我有這個東西!最後。

好的。在開始時,問題確實在會話0隔離的事情。所以我需要構建一個可以從服務啓動的中間應用程序,然後,該應用程序又將通過RPC啓動我的應用程序並將其引入桌面。與其構建中間層應用程序,我決定使用psexec工具(無論如何,它的工作方式與我需要的完全相同 - 通過RPC)。 當我嘗試在LOCAL SYSTEM帳戶下使用該工具時,由於某種原因它不起作用。然後我意識到 - 原因是MS放在每一個pstool中的該死的EULA彈出對話框,並且不可能在本地系統帳戶下點擊按鈕確認對話框。 所以解決的辦法是在註冊表HKU.DEFAULT \ Software \ Sysinternals \ PsExec中用DWORD值創建一個密鑰EulaAccepted = 1

Hooray,現在工作! 但是!現在我需要將程序帶到當前記錄的用戶屏幕。要做到這一點,我需要會話ID!

所以問題是:如何獲取當前登錄的用戶的會話ID?如果沒有人登錄,會發生什麼?會是什麼會話ID?

UPD4:就是這樣!我有那個! (DllImport(「Kernel32.dll」,EntryPoint =「WTSGetActiveConsoleSessionId」)] public static extern int WTSGetActiveConsoleSessionId();

謝謝你們!

+1

我重新閱讀我的答案,並意識到我只給了你一半的解決方案......你應該拼湊你的最終解決方案,並將其添加爲答案而不是問題。在這裏發表回答你自己的問題是可以的:)讓未來有人閱讀這篇文章更清楚(有人會 - 這是一個比較常見的問題)。 – 2011-10-02 19:22:11

回答

3

一種解決方案是讓第三個進程充當中介,並通過RPC /命名管道啓動應用程序。

過程:

  • Windows服務
  • 中介申請
  • 要運行

墊片的應用程序創建一個通信端點(命名管道,WCF端點)和偵聽它。當它收到一條消息時,它會啓動你想運行的應用程序。

然後,當Windows服務想要啓動應用程序時,它會查找並打開端點(命名管道,WCF端點),併發送消息以啓動應用程序。然後,中介應用程序負責流程啓動業務,並且不具有Windows服務具有的任何限制。

使這個中間過程開始登錄,你很好去。

這與Microsoft測試代理/控制器在需要運行與桌面交互的測試時的工作方式類似。

+0

Ahhhh ...有沒有更簡單的解決方案? 我試圖從SysInternals套件中啓動一個psexec.exe應用程序。您可以將會話ID提供給它,它會將該應用程序帶到使用該會話的該用戶的桌面。 但問題是,它需要以管理員身份啓動。 例如,如果你甚至試圖運行這樣的東西: PsExec.exe -u mydomain \ user -p pass123 -i -s 1「c:\ windows \ system32 \ calc.exe」 即使用戶具有管理員權限,該腳本將工作,除非你手動說「以管理員身份運行」。我如何以管理員的身份悄悄地運行某些東西而不帶UAC的東西? – Agzam 2010-07-08 13:17:56

1

如果您嘗試使用比WindowsXP更新的任何東西,這將無法正常工作。這是因爲在Vista/Windows 7中引入了一個稱爲會話0隔離的新功能。 http://msdn.microsoft.com/en-us/library/bb756986.aspx您將無法獲得由服務啓動的應用程序以顯示在用戶桌面上。

2

這可以在沒有中間過程的情況下完成,但它需要500多行代碼才能完成。基本上,您想要以當前登錄用戶的身份啓動第二個進程。對於Vista/7,此用戶將擁有自己的winlogon進程,而對於XP,他們將擁有一個瀏覽器進程。您需要獲取該運行過程的主令牌,環境塊,安全屬性和線程安全屬性,然後使用所有信息調用Windows API函數CreateProcessAsUser,並確保選擇了正確的窗口工作站(通常爲「WinSta0 \ Default 「)。這一切都是可行的,但是對於第二個過程和IPC的其他建議,您可能會有更好的時間。

+0

我試過了,還是不帶窗口。該死的0隔離東西... – Agzam 2010-07-08 17:29:57

3

您可以使用WTSGetActiveConsoleSessionId(來自終端服務API)獲取活動控制檯會話標識。你只能在WinXP/Win2K3或更高版本上使用它,但這應該沒問題,因爲你可以在Win2K或更早版本上爲會話ID硬編碼0。下面是它的PInvoke簽名:

[DllImport("Kernel32.dll", SetLastError = true)] 
[return:MarshalAs(UnmanagedType.U4)] 
public static extern int WTSGetActiveConsoleSessionId (); 

至於在用戶的會話啓動一個過程,你可以參考我給here答案。它基本上涉及調用四個API; WTSGEtConsoleSessionId,WTSQueryUserToken,DuplicateTokenEx,然後是CreateProcessAsUser,它可以在任何運行WinXP/Win2K3或更高版本的機器上運行。

+0

-1:這個答案已經在問題中。 – 2010-09-04 07:04:08

+0

對不起,我意識到我誤解了實際問題並更新了我的帖子以提供更好的答案。 – Javert93 2010-09-04 07:18:44