2011-03-14 42 views
1

簡而言之,我試圖將一些功能添加到作爲Windows服務運行的自定義更新程序中。我遇到了一些我嘗試更新的應用程序可能正在運行的問題,如果是,我需要執行一些自定義操作。Windows服務中的EnumDesktopWindows

我遇到的問題是EnumDesktopWindows API調用只返回在本地系統上下文中運行的進程。

現在,這對我來說最主要的是爲什麼這樣做了,等等(我想 - 雖然會感激進一步的解釋)。

然而,如何通過服務完成此功能?

這是我使用的代碼的基礎:

 public static IntPtr[] EnumDesktopWindows() 
     { 
      WinAPI._desktopWindowHandles = new List<IntPtr>(); 
      WinAPI.EnumDelegate enumfunc = new WinAPI.EnumDelegate(EnumWindowsCallBack); 
      IntPtr hDesktop = IntPtr.Zero; // current desktop 
      bool success = WinAPI.EnumDesktopWindows(hDesktop, enumfunc, IntPtr.Zero); 

      if (success) 
      { 
       IntPtr[] handles = new IntPtr[_desktopWindowHandles.Count]; 
       _desktopWindowHandles.CopyTo(handles); 
       return handles; 
      } 
      else 
      { 
       int errorCode = Marshal.GetLastWin32Error(); 
       string errorMessage = String.Format("EnumDesktopWindows failed with code {0}.", errorCode); 
       throw new Exception(errorMessage); 
      } 

     } 

難道是因爲我有這一切錯誤的,問題是在該行?:

IntPtr hDesktop = IntPtr.Zero; 

回答

2

我不確定您是否按照正確的方向列舉了桌面。我不知道誰是服務內部EnumDesktopWindows調用後面的操作的發起者。如果用戶觸發了該操作,則可能會冒充他的用戶帳戶,問題將很容易解決。

如果您沒有任何方式接收用戶令牌,我建議您在繼續之前閱讀Impact of Session 0 Isolation on Services and Drivers in Windows文檔。您遇到的主要問題是終端服務正在計算機上運行,​​並且您的Windows服務在SessionId = 0的會話中運行,但所有用戶進程都在另一個會話中運行。如果您的服務在LocalSystem帳戶下運行,或者在具有SE_TCB_NAME權限的任何其他帳戶下運行,則可以使用SetTokenInformation函數和TokenSessionId參數更改爲當前會話(有關更多詳細信息,請參閱here)。關於LsaEnumerateLogonSessions函數,您可以收到的所有可用會話。

最後我可以重複一次,只有在其他更簡單的用戶模擬方法不能使用的情況下,您才應該更改服務的會話。

2
  • 枚舉進程
  • 讓應用程序通告存在(命名內核對象,例如來自CreateEvent)
  • 嘗試單獨打開EXE文件
4

服務在與交互式用戶不同的會話(會話0)中運行。這被稱爲會話0隔離。

您無法從服務訪問登錄用戶的桌面。

你必須通過枚舉進程而不是窗口來攻擊這個問題。

+0

我很肯定你*可以*從服務訪問任何桌面如果你足夠努力,但過程枚舉絕對是一個更簡單的方法。 – 2011-03-14 14:43:58