在控制台应用程序中使用以下类,并且至少有一个记事本实例正在运行时,GetWindowThreadProcessId
正确返回非零线程 ID。但是,如果 Windows 服务中包含相同的代码,GetWindowThreadProcessId
总是返回0
并且不会抛出任何异常。将服务启动的用户更改为与运行控制台应用程序的用户相同并不会改变结果。是什么原因导致GetWindowThreadProcessId
回来0
即使它提供了有效的 hwnd?为什么它在控制台应用程序和服务中的功能不同?注意:我运行的是 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\"
所以所有会话都可以看到它。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)