C# 为什么从服务调用GetWindowThreadProcessId时返回0?
在控制台应用程序中使用以下类并运行至少一个记事本实例时,C# 为什么从服务调用GetWindowThreadProcessId时返回0?,c#,winapi,pinvoke,C#,Winapi,Pinvoke,在控制台应用程序中使用以下类并运行至少一个记事本实例时,GetWindowThreadProcessId正确返回非零线程id。但是,如果Windows服务中包含相同的代码,GetWindowThreadProcessId始终返回0,并且不会引发异常。将服务启动的用户更改为与运行控制台应用程序的用户相同不会改变结果。是什么导致GetWindowThreadProcessId返回0,即使它提供了有效的hwnd?为什么它在控制台应用程序和服务中的功能不同?注意:我运行的是32位Windows 7,目标
GetWindowThreadProcessId
正确返回非零线程id。但是,如果Windows服务中包含相同的代码,GetWindowThreadProcessId
始终返回0
,并且不会引发异常。将服务启动的用户更改为与运行控制台应用程序的用户相同不会改变结果。是什么导致GetWindowThreadProcessId
返回0
,即使它提供了有效的hwnd?为什么它在控制台应用程序和服务中的功能不同?注意:我运行的是32位Windows 7,目标是.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()
{
...
}
}
Windows服务没有UI,因此它没有窗口。服务在其自己的会话中运行,即Vista和Win7中臭名昭著的会话0。该会话将服务与用户桌面隔离,并在另一个会话中运行。特别是为了防止通常使用非常特权的帐户(如LocalSystem)运行的服务与用户交互。安全漏洞 因此,服务无法看到另一个会话拥有的窗口句柄
不知道为什么要这样做,但您通常需要一个助手程序,该程序提供用户界面,并通过IPC机制(如命名管道、套接字、.NET远程处理或WCF)与服务通信。如果使用命名管道,请在管道名称前加上
“Global\”
,以便所有会话都能看到它。还可以启用“允许服务与桌面交互”选项,并查看该选项是否有效。否则,我将不得不同意上面的onbugz评论。但我查询的是notepad.exe实例的线程ID,而不是服务本身。感谢您的建议。我在发帖之前就试过了,这似乎并没有影响我的场景。谢谢你的详细回答。进一步回顾,在应用程序中而不是在服务中运行代码可能是更好的设计决策。