Bentornati!
Questo è un problema vecchio, risalente all’epoca di Windows XP, ma ancora attuale presso chi sta tuttora usando XP e non si è ancora deciso a migrare a Windows Vista o Windows 7.
Per motivi legati al risparmio energetico e alle specifiche del Green PC, il Power Manager di XP, spegne la macchina dopo due minuti dall’accensione, se non c’è nessun “contatto” di un utente alla tastiera/mouse o se nessun servizio provvede ad effettuare operazioni che contemplino anche la chiamata SetThreadExecutionState. Qesta è l’API prevista specificatamente per questo compito: mantenere sveglio XP..
Ad esempio, una sessione remota non genera nessuna chiamata alla SetThreadExecutionState, per cui anche nel caso in cui ci si colleghi da remoto con una sessione RDP, la macchina trascorsi i due minuti tornerà nella condizione precedente: se era spenta si spegnerà, se era in hybernation si reibernerà, se era in stand-by ci ritornerà.
Questo problema affligge soprattutto le grandi aziende. Un utente normale, probabilmente non si è mai accorto di questa “funzionalità”.
Per le grandi aziende però, dove ci sono centinaia di PC da amministrare e tenere aggiornati, è normale, pianificare operazioni notturne. Quindi, risvegliare i PC tramite il Wake On Lan, ed eseguire operazioni schedulate, tipo l’installazione di patch o backup, mentre gli utenti non sono presenti.
La soluzione è creare un servizio, che implementi la SetThreadExecutionState, e che parta in automatico. Questo farà in modo che la macchina rimanga sveglia per il tempo necessario ad eseguire l’opearazione pianificata. Al termine, basterà semplicemente interrompere il servizio e il power manager riporterà la macchina al suo stato precedente come se nulla fosse accaduto.
Nell’esempio, avevo anche aggiunto la gestione di una chiave di registry, che se presente impostava un timeout dopo il quale il servizio si terminava in automatico.
Per fare ciò, sono partito dall’esempio Simple Service dell’SDK, disponibile nel folder “C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\WinBase\Service” dopo l’installazione del Platform SDK, disponibile qui: http://www.microsoft.com/downloads/details.aspx?familyid=C17BA869-9671-4330-A63E-1FD44E0E2505&displaylang=en
Se ricompilate l’esempio allegato a questo post, potete modificare la linea di codice dove è definito il percorso della chiave di registry che conterrà il valore che si dovrà chiamare “Timeout”, che porterà al termine del servizio dopo quel tempo, espresso in secondi.
static LPTSTR gsSubKey = _T("Software\\YourCompany\\NoSleep");
while(TRUE) { hr = SetThreadExecutionState(ES_SYSTEM_REQUIRED|ES_CONTINUOUS); dwWait = WaitForMultipleObjects( 1, hEvents, FALSE, 1000 ); if ( dwWait != WAIT_TIMEOUT ) // not overlapped i/o event - error occurred, break; // or server stop signaled if (dwCount==dwTimeout) break; else ++dwCount; }
// name of the executable#define SZAPPNAME "NoSleep"// internal name of the service#define SZSERVICENAME "No_Sleep"// displayed name of the service#define SZSERVICEDISPLAYNAME "NoSleep Service"
schService = CreateService( schSCManager, // SCManager database TEXT(SZSERVICENAME), // name of service TEXT(SZSERVICEDISPLAYNAME), // name to display SERVICE_QUERY_STATUS, // desired access SERVICE_WIN32_OWN_PROCESS, // service type SERVICE_AUTO_START, // start type SERVICE_ERROR_NORMAL, // error control type szPath, // service's binary NULL, // no load ordering group NULL, // no tag identifier TEXT(SZDEPENDENCIES), // dependencies NULL, // LocalSystem account NULL); // no password
NoSleep –install to install the service NoSleep –remove to remove the service NoSleep -debug <params> to run as a console app for debugging
Il sorgente è allegato al post, ma non è compilato.
Per la compilazione, dovete aprire la “Cmd Shell” dell’SDK e usare Setenv.bat per compilare per la piattaforma (x86/x64), la versione debug/release e il sistema operativo target che volete.
Windows XP quando viene risvegliato con il “Wake On Lan” si riporta nello stato precedente dopo pochi minuti se il Power Manager non detecta la presenza di un utente. Per evitare questo e poter effettuare operazioni pianificate come l’installazione di patch o backup, è necessario mantenere la macchina sveglia attraverso la chiamata all’API SetThreadExecutionState.
Questo Servizio di esempio permette esattamente questo.
Alla prossima!
Mario Raccagni Senior Support Engineer Platform Development Support Team