为什么GetWindowThreadProcessId从服务调用时返回0?

在控制台应用程序中使用以下类,并且至少有一个Notepad实例正在运行时, GetWindowThreadProcessId正确返回非零线程ID。 但是,如果Windows服务中包含相同的代码,则GetWindowThreadProcessId始终返回0并且不会引发任何exception。 将服务启动的用户更改为与运行控制台应用程序的用户相同并未改变结果。 是什么原因导致GetWindowThreadProcessId返回0即使它提供有效的hwnd? 为什么它在控制台应用程序和服务中的function不同? 注意:我运行的是Windows 7 32位并以.NET 3.5为目标。

 public class TestClass { [DllImport("user32.dll")] static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId); public void AttachToNotepad() { var processesToAttachTo = Process.GetProcessesByName("Notepad") foreach (var process in processesToAttachTo) { var threadID = GetWindowThreadProcessId(process.MainWindowHandle, IntPtr.Zero); .... } } } 

控制台代码:

 class Program { static void Main(string[] args) { var testClass = new TestClass(); testClass.AttachToNotepad(); } } 

服务代码:

 public class TestService : ServiceBase { private TestClass testClass = new TestClass(); static void Main() { ServiceBase.Run(new TestService()); } protected override void OnStart(string[] args) { testClass.AttachToNotepad(); base.OnStart(args); } protected override void OnStop() { ... } } 

服务在自己的会话中运行,在Vista和Win7中臭名昭着的会话0。 该会话将服务与用户桌面隔离,它在另一个会话中运行。 特别是为了防止通常使用特权帐户(如LocalSystem)运行的服务与用户进行交互。 一个安全漏洞。

因此,服务无法看到另一个会话所拥有的窗口句柄。

不确定为什么要这样做但你通常需要一个帮助程序,它提供一个用户界面并通过IPC机制(如命名管道,套接字,.NET远程处理或WCF)与服务进行通信。 如果使用命名管道,请在管道名称前加上"Global\"前缀,以便所有会话都能看到它。

您还可以启用“允许服务与桌面交互”选项,看看是否有效。 否则我将不得不同意上面的onbugz评论。

Windows服务没有UI,因此没有窗口。