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

发布于 2024-08-25 06:30:16 字数 1430 浏览 6 评论 0原文

在控制台应用程序中使用以下类,并且至少有一个记事本实例正在运行时,GetWindowThreadProcessId 正确返回一个非零线程 ID。但是,如果 Windows 服务中包含相同的代码,则 GetWindowThreadProcessId 始终返回 0 并且不会引发异常。将服务启动的用户更改为与运行控制台应用程序的用户相同并不会改变结果。即使提供了有效的 hwnd,是什么导致 GetWindowThreadProcessId 返回 0 ?为什么它在控制台应用程序和服务中的功能不同?注意:我运行的是 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()
    {
        ...
    }
}

When using the following class in a console application, and having at least one instance of Notepad running, GetWindowThreadProcessId correctly returns a non-zero thread id. However, if the same code is included in a Windows Service, GetWindowThreadProcessId always returns 0 and no exceptions are thrown. Changing the user the service launches under to be the same as the one running the console application didn't alter the result. What causes GetWindowThreadProcessId to return 0 even if it is provided with a valid hwnd? And why does it function differently in the console application and the service? Note: I am running Windows 7 32-bit and targeting .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);

            ....
        }
    }
}

Console Code:

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

        testClass.AttachToNotepad();
    }
}

Service Code:

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()
    {
        ...
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

儭儭莪哋寶赑 2024-09-01 06:30:16

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

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

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

A service runs in its own session, the infamous session 0 in Vista and Win7. That session isolates services from the user desktop, it runs in another session. Specifically to prevent a service that usually runs with a very privileged account (like LocalSystem) from interacting with the user. A security hole.

Accordingly, a service cannot see the window handles owned by another session.

Not sure why you are doing this but you typically need a helper program that presents a user interface and communicates with the service through an IPC mechanism like named pipes, sockets, .NET remoting or WCF. If you use a named pipe, prefix the pipe name with "Global\" so all sessions can see it.

我们只是彼此的过ke 2024-09-01 06:30:16

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

You could also enable the option "Allow service to interact with desktop" and see if that works. Otherwise I would have to agree with onbugz comment above.

〆凄凉。 2024-09-01 06:30:16

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

A Windows Service has no UI, so it has no window.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文