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

标签 c# winapi pinvoke

在控制台应用程序中使用以下类并至少运行一个记事本实例时,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()
    {
        ...
    }
}

最佳答案

服务在它自己的 session 中运行,在 Vista 和 Win7 中臭名昭著的 session 0。该 session 将服务与用户桌面隔离开来,它在另一个 session 中运行。专门用于防止通常使用非常特权帐户(如 LocalSystem)运行的服务与用户交互。一个安全漏洞。

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

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

关于c# - 为什么从服务调用时 GetWindowThreadProcessId 返回 0?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2461171/

相关文章:

windows - 读取随身碟时 CreateFile() 失败,错误代码为 32

c++ - BMP 的完整屏幕截图。 bliting 和保存的问题

c# - 使用 PInvoke char** (C -> C#) 更正返回值

c# - Pinvoke C# : delegated function cause crash

windows - Win32 ListBox 控件是否有 SetText 消息?

c# - CopyFileEx 包装器参数

c# - 在program.cs中使用选项模式

c# - 无法添加对 ´ 的引用。程序集必须具有 dll 或 exe 扩展名才能被引用

javascript - WPF 内自托管 WCF - Javascript 请求中的 Access-Control-Allow-Origin 405 错误

c# - Base 64 图像未在电子邮件中呈现