为什么从服务调用时GetWindowThreadProcessId返回0? [英] Why does GetWindowThreadProcessId return 0 when called from a service?

查看:1340
本文介绍了为什么从服务调用时GetWindowThreadProcessId返回0?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当使用一个控制台应用程序下面的类,并具有记事本运行至少一个实例, GetWindowThreadProcessId 正确返回非零线程ID。但是,如果相同的代码包含在Windows服务, GetWindowThreadProcessId 总是返回 0 并没有异常抛出。改变根据服务启动用户是相同的运行控制台应用程序没有改变的结果之一。是什么原因导致 GetWindowThreadProcessId 返回 0 即使设有有效的HWND?为什么它的功能是不同的控制台应用程序和服务?注:我运行Windows 7 32位和定位.NET 3.5



 公共类识别TestClass 
{
函数[DllImport(user32.dll中)]
静态外部UINT GetWindowThreadProcessId(IntPtr的的HWND,IntPtr的进程ID);

公共无效AttachToNotepad()
{
VAR processesToAttachTo = Process.GetProcessesByName(记事本)

的foreach(VAR在processesToAttachTo过程)
{
VAR主题ID = GetWindowThreadProcessId(process.MainWindowHandle,
IntPtr.Zero);

....
}
}
}

控制台代码:

 类节目
{
静态无效的主要(字符串[ ]参数)
{
变种的TestClass =新识别TestClass();

testClass.AttachToNotepad();
}
}



服务代码:

 公共类TestService的:ServiceBase 
{
私人TestClass中的TestClass =新识别TestClass();

静态无效的主要()
{
ServiceBase.Run(新TestService的());
}

保护覆盖无效的OnStart(字串[] args)
{
testClass.AttachToNotepad();

base.OnStart(参数);
}

保护覆盖无效调用OnStop()
{

}
}


解决方案

一个服务于自己的会话,在Vista和Win7的臭名昭著的会话0中运行。那届从用户桌面隔离服务,它在另一个会话中运行。具体地,以防止通常具有非常优越的帐户(如本地系统)运行的服务,从与用户交互。一个安全漏洞。



因此​​,服务不能看到窗口句柄由另一个会话拥有。



不知道你为什么这样做,但通​​常需要呈现的用户界面,并通过IPC机制喜欢命名管道,插座,.NET远程或WCF服务进行通信的辅助程序。如果使用命名管道,以Global\因此,所有的会话可以看到它的前缀管道名称。


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

解决方案

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.

这篇关于为什么从服务调用时GetWindowThreadProcessId返回0?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆