2012-02-29 23 views
5

Sto cercando di ottenere la dimensione del desktop di Windows (il tutto, non solo una singola schermata) all'interno di un servizio che ho scritto.Ottieni le dimensioni del desktop dal servizio di Windows?

in WinForms - il metodo standard C# di:

SystemInformation.VirtualScreen.Width 
SystemInformation.VirtualScreen.Height 

sembra funzionare (se si importa il Winforms DLL, che voglio evitare) - ma restituisce il valore errato. Le dimensioni del desktop sono 2048x768 (2 schermate), ma il servizio segnala 1024x768 (presumibilmente si solleva solo su una delle schermate)

Controllare l'opzione per il servizio di interagire con il desktop non ha alcun effetto.

Qualche idea?

Edit:

Le soluzioni pubblicato su C#: Get complete desktop size? non funzionano all'interno di un servizio. Tutti riportano il valore sbagliato.

È interessante notare, sembra che il valore che viene segnalato varia ed è di alcuna relazione con la dimensione desktop reale (alcune macchine riportano 800x600 anche se un singolo display su quella macchina è una risoluzione molto più elevata.)

Così - Altre idee? Il passaggio al registro e/o alla riga di comando è OK. L'unica limitazione è che non posso lanciare un'app winforms per capirlo.

+1

Hai preso in considerazione il fatto che il servizio potrebbe essere in esecuzione su un sistema senza testa? O semplicemente non ci sono utenti registrati? – Dmitry

+0

Spero che questo http://stackoverflow.com/questions/1317235/c-get-complete-desktop-size ti aiuterà. –

+0

Dovrei chiarire. I sistemi senza testa non sono un problema in questa configurazione. In secondo luogo, mi collego all'evento di accesso, quindi so quando tentare di capire la dimensione del desktop (solo dopo che qualcuno effettua l'accesso.) – debracey

risposta

3

Non è possibile farlo all'interno del servizio. I servizi vengono eseguiti nella sessione 0, in cui nessuna funzione GDI funziona. Una volta creato il processo, non è possibile modificare le sessioni e non è possibile utilizzare l'interfaccia utente in sessioni diverse.

Una delle possibili soluzioni per voi è di avviare un nuovo processo nella sessione utente. È possibile iniziare a guardare questo SO question. Gli altri prerequisiti per questo metodo sono che il servizio deve essere in esecuzione come Sistema locale, in modo da poter abilitare il privilegio SE_TCB_NAME (chiamando AdjustTokenPrivilegies). Poiché stai dicendo che sei già collegato alla notifica di accesso dell'utente, dovresti essere in grado di estrarre l'ID di sessione della sessione che ti interessa.

Una volta che un processo è stato eseguito nella sessione utente, devi passare risultato dal nuovo processo per il processo di servizio. Per questo potrebbe essere usato qualsiasi tipo di meccanismo IPC.

+0

Grazie. Ho trovato un post interessante sull'interrogazione di WMI per capire la dimensione del desktop (qualcosa come "SELECT * FROM Win32_DesktopMonitor" 'then' queryObj ["ScreenWidth"] '). Sai se funzionerà all'interno di un servizio? Purtroppo non sono al lavoro in questo momento, quindi non posso provarlo --- Proverò questo e il tuo suggerimento domani e riferirò. – debracey

+0

Sembra che Win32_DesktopMonitor fornisca i parametri dell'hardware fisico, ossia effettivamente collegato alla scheda video con cavo. Non riporta le dimensioni dello schermo per le sessioni RDP. Dipende dalle tue esigenze: hai bisogno di specifiche hardware fisiche o di qualsiasi altra schermata effettivamente utilizzata dall'utente. –

+0

Questo è un buon punto, immagino che la mia domanda iniziale non fosse chiara. Mi interessa di più della massima risoluzione che l'hardware può visualizzare. Ciò che l'utente effettivamente vede potrebbe anche essere qualcosa di utile da segnalare - ma penso che si preoccupino di più di "qual è la ris più alta che potrei mostrare" – debracey

1

Anche se non ho riscontrato questo problema esatto, sospetto che lavorare con più monitor possa richiedere di eseguire il downward a livello di Win32API (un sacco di casi limite).

Dai un'occhiata alla funzione EnumDisplayMonitors da user32 e in particolare a example in C#.

In alternativa è possibile utilizzare Screen.AllScreens (come parte della DLL di Winforms che non si desidera importare) come controllo rapido per vedere se ciò che si vuole fare sarà possibile come servizio di Windows. Sono quasi certo che questo metodo WinForms si basa su EnumDisplayMonitors internamente.

+0

Stessa offerta della chiamata gestita, viene riportato il valore errato ... – debracey

1

È possibile aggiungere la dimensione di tutti gli schermi per determinare le dimensioni totali del desktop, come descritto da P Daddy in 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ì ... l'ho visto, non funziona in un servizio Windows. Il risultato è lo stesso: 1024x768 quando dovrebbe essere 2048x768. – debracey

0

Il seguente codice funziona in un servizio che ho trovato in 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); 
Problemi correlati