从Windows服务获取桌面大小?

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

在WinForms中 – 标准的C#方法:

SystemInformation.VirtualScreen.Width SystemInformation.VirtualScreen.Height 

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

检查服务与桌面交互的选项无效。

有什么想法吗?

编辑:

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

有趣的是,似乎报告的值变化并且与实际桌面大小无关(有些机器报告800x600即使该机器上的单个显示器具有更高的分辨率。)

那么 – 还有什么想法吗? 删除到注册表和/或命令行是可以的。 唯一的限制是我无法启动winforms应用程序来解决它。

您无法在服务中执行此操作。 服务在会话0中运行,其中没有GDIfunction。 创建进程后,您无法更改会话,也无法在不同的会话中使用UI。

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

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

虽然我自己没有遇到过这个问题,但我怀疑使用多个监视器可能需要你深入研究Win32API级别(很多边缘情况都可以)。

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

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

您可以添加所有屏幕的大小以确定桌面总大小,如本文中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); 

以下代码适用于我在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);