从Windows服务获取桌面大小

本文关键字:桌面 获取 Windows 服务 | 更新日期: 2023-09-27 18:26:17

我正试图从我编写的服务中获取Windows桌面的大小(整个东西,而不仅仅是一个屏幕)。

在WinForms中——的标准C#方法

SystemInformation.VirtualScreen.Width   
SystemInformation.VirtualScreen.Height

似乎有效(如果您导入Winforms DLL,我想避免),但它返回了错误的值。桌面大小为2048x768(2个屏幕),但服务报告1024x768(可能它只在其中一个屏幕上启动。)

检查服务与桌面交互的选项没有任何效果。

有什么想法吗?

编辑:

C#上发布的解决方案:获得完整的桌面大小?不要在服务内部工作。他们都报错了值。

有趣的是,报告的值似乎各不相同,与实际桌面大小无关(有些机器报告800x600,尽管该机器上的单个显示器的分辨率要高得多。)

还有什么想法吗?放入注册表和/或命令行是可以的。唯一的限制是我不能启动winforms应用程序来解决这个问题。

从Windows服务获取桌面大小

您不能在服务内部执行此操作。服务在会话0中运行,其中没有任何GDI函数工作。一旦创建了流程,就不能更改会话,也不能在不同的会话中使用UI。

其中一个可能的解决方案是在用户会话中启动一个新流程。你可以开始看这个SO问题。此方法的其他先决条件是,您的服务必须以本地系统的身份运行,以便您可以启用SE_TCB_NAME权限(通过调用AdjustTokenPrivileges)。既然你说你已经连接到用户登录通知,你应该能够提取你感兴趣的会话的会话ID

一旦在用户会话中启动了流程,就必须将新流程的结果传递回服务流程。为此,可以使用任何类型的IPC机制。

您可以添加所有屏幕的大小来确定桌面的总大小,正如p Daddy在本文中所描述的那样。

Rectangle rect = new Rectangle(int.MaxValue, 
                               int.MaxValue,
                               int.MinValue,
                               int.MinValue); 
foreach (Screen screen in Screen.AllScreens) 
{
    rect = Rectangle.Union(rect, screen.Bounds); 
}
Console.WriteLine("(w, h) = ({0}, {1})", rect.Width, rect.Height); 

虽然我自己还没有遇到这个确切的问题,但我怀疑使用多个监视器可能需要深入到Win32API级别(很多边缘情况都是这样)。

看看user32中的EnumDisplayMonitors函数,特别是C#中的一个例子。

或者,你可以使用Screen.AllScreens(作为你不想导入的Winforms DLL的一部分)作为快速检查,看看你想做的事情是否可以作为Windows服务。我几乎可以肯定,这个WinForms方法在内部依赖于EnumDisplayMonitors

以下代码适用于我在sharpAvi中找到的服务:https://sharpavi.codeplex.com/

        System.Windows.Media.Matrix toDevice;
        using (var source = new HwndSource(new HwndSourceParameters()))
        {
            toDevice = source.CompositionTarget.TransformToDevice;
        }
        screenWidth = (int)Math.Round(SystemParameters.PrimaryScreenWidth * toDevice.M11);
        screenHeight = (int)Math.Round(SystemParameters.PrimaryScreenHeight * toDevice.M22);