2012-02-29 22 views
5

Estoy tratando de obtener el tamaño del escritorio de Windows (todo, no solo una pantalla) desde el interior de un servicio que he escrito.¿Obtener tamaño de escritorio desde el servicio de Windows?

En WinForms - el método estándar de C#:

SystemInformation.VirtualScreen.Width 
SystemInformation.VirtualScreen.Height 

parece funcionar (si importa el Winforms DLL, que quiero evitar) - pero devuelve el valor incorrecto. El tamaño del escritorio es 2048x768 (2 pantallas), pero el servicio informa 1024x768 (presumiblemente solo aparece en una de las pantallas)

La verificación de la opción para que el servicio interactúe con el escritorio no tiene ningún efecto.

¿Alguna idea?

Editar:

con las soluciones publicadas en C#: Get complete desktop size? no funcionan en el interior de un servicio. Todos ellos informan el valor incorrecto.

Curiosamente, parece que el valor que se informó varía y no tiene relación con el tamaño real de escritorio (algunas máquinas informan 800x600 a pesar de que una sola pantalla en esa máquina es una resolución mucho más alta.)

Así - ¿más ideas? Dejar caer en el registro y/o en la línea de comandos está bien. La única restricción es que no puedo iniciar una aplicación de winforms para resolverlo.

+1

¿Tomó en cuenta el hecho de que el servicio se esté ejecutando en un sistema sin cabeza? ¿O simplemente no hay usuarios conectados? – Dmitry

+0

Espero que este http://stackoverflow.com/questions/1317235/c-get-complete-desktop-size te ayude. –

+0

Debo aclarar. Los sistemas sin cabeza no son una preocupación en esta configuración. En segundo lugar, me estoy adjuntando al evento de inicio de sesión, por lo que sé cuándo intentar averiguar el tamaño del escritorio (solo después de que alguien inicie sesión). – debracey

Respuesta

3

No puede hacer esto dentro del servicio. Los servicios se ejecutan en la sesión 0, donde no funcionan las funciones GDI. Una vez que se crea el proceso, no puede cambiar las sesiones y no puede usar la IU en diferentes sesiones.

Una de las soluciones posibles para usted es iniciar un nuevo proceso en la sesión del usuario. Puede comenzar a buscar en este SO question. Los otros requisitos previos para este método es que su servicio se debe ejecutar como Sistema local, para que pueda habilitar el privilegio SE_TCB_NAME (llamando a AdjustTokenPrivilegies). Puesto que está diciendo que ya está conectado a la notificación de inicio de sesión del usuario, debería poder extraer la ID de sesión de la sesión que le interese.

Una vez que haya iniciado un proceso en la sesión del usuario, debe pasar el resultado del nuevo proceso de vuelta a su proceso de servicio. Para eso, se podría usar cualquier tipo de mecanismo de IPC.

+0

Gracias. Encontré una publicación interesante sobre cómo consultar WMI para averiguar el tamaño del escritorio (algo así como '" SELECT * FROM Win32_DesktopMonitor "' then 'queryObj [" ScreenWidth "]'). ¿Sabes si eso funcionará dentro de un servicio? Lamentablemente, no estoy trabajando en este momento, así que no puedo probarlo; intentaré eso y tu sugerencia mañana e informaré. – debracey

+0

Parece que Win32_DesktopMonitor le proporciona los parámetros del hardware físico, es decir, adjuntado a una tarjeta de video con cable. No informa los tamaños de pantalla para las sesiones RDP. Depende de sus requisitos: ¿necesita especificaciones físicas de hardware o la pantalla que usa realmente el usuario? –

+0

Ese es un buen punto, creo que mi pregunta original no estaba clara. Me preocupa más la resolución máxima que puede mostrar el hardware. Lo que el usuario realmente ve también puede ser algo útil para informar, pero creo que les importa más "cuál es la resolución más alta que puedo mostrar" – debracey

1

Si bien no he encontrado este problema yo mismo, sospecho que trabajar con varios monitores puede requerir que profundice en el nivel de Win32API (una gran cantidad de casos extremos).

Eche un vistazo a la función EnumDisplayMonitors de user32, y específicamente a example in C#.

Como alternativa, puede usar Screen.AllScreens (como parte de la DLL de Winforms que no desea importar) como una comprobación rápida para ver si lo que desea hacer será posible como un Servicio de Windows. Estoy casi seguro de que este método de WinForms se basa internamente en EnumDisplayMonitors.

+0

El mismo trato que la llamada administrada, se informa el valor incorrecto ... – debracey

1

Puede agregar el tamaño de todas las pantallas para determinar el tamaño total del escritorio, según lo descrito por P Daddy en this post.

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); 
+0

Sí ... Vi eso, no funciona en un servicio de Windows. El resultado es el mismo: 1024x768 cuando debería ser 2048x768. – debracey

0

El código siguiente funciona en un servicio que he encontrado en 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); 
Cuestiones relacionadas