In an application I wrote a few years back I use function SystemParametersInfo with SPI_GETPOWEROFFTIMEOUT to get the timeout for monitor off. On Vista this doesn’t work anymore.
So I decided to make this work on Vista, but after a few hours I feel like I’m no closer to a solution.
Most of the functions I am going to mention are described on http://msdn.microsoft.com/en-us/library/aa373163(VS.85).aspx
To my understanding I should: 1. use function PowerGetActiveScheme, to get current scheme 2. use PowerEnumerate with GUID_VIDEO_SUBGROUP 3. use PowerReadACValue (or DC value) to get the value.
Is this right? Seems like a lot of work to get to one setting. If this is the correct way, there is one thing I don’t understand. On my system PowerEnumerate returns 3 keys. How do I know which one is for Monitor timeout?
Here is my code so far. I’m having trouble with PowerReadACValue, I probably didn’t define or use it properly.
class Program { [DllImport('powrprof.dll')] static extern UInt32 PowerGetActiveScheme(IntPtr UserRootPowerKey, ref IntPtr ActivePolicyGuid); [DllImport('powrprof.dll')] static extern uint PowerEnumerate( IntPtr RootPowerKey, IntPtr SchemeGuid, Guid SubGroupOfPowerSettingGuid, UInt32 AcessFlags, UInt32 Index, ref Guid Buffer, ref UInt32 BufferSize); [DllImport('powrprof.dll')] static extern uint PowerReadACValue( IntPtr RootPowerKey, IntPtr SchemeGuid, IntPtr SubGroupOfPowerSettingGuid, Guid PowerSettingGuid, ref IntPtr Type, ref IntPtr Buffer, ref UInt32 BufferSize); static void Main(string[] args) { IntPtr activeGuidPtr = IntPtr.Zero; uint res = PowerGetActiveScheme(IntPtr.Zero, ref activeGuidPtr); if (res == 0) { Guid VideoSettingGuid = new Guid(); UInt32 index = 0; UInt32 BufferSize = (UInt32)Marshal.SizeOf(typeof(Guid)); while (0 == PowerEnumerate( IntPtr.Zero, activeGuidPtr, new Guid('7516b95f-f776-4464-8c53-06167f40cc99'), 18, index, ref VideoSettingGuid, ref BufferSize)) { Console.Write(VideoSettingGuid.ToString() + ': '); UInt32 size = 1024; IntPtr temp = Marshal.AllocHGlobal(1024); IntPtr type = IntPtr.Zero; PowerReadACValue(IntPtr.Zero, activeGuidPtr, IntPtr.Zero, VideoSettingGuid, ref type, ref temp, ref size); Console.Write(Marshal.PtrToStringUni(temp)); Marshal.FreeHGlobal(temp); index++; } } } }
I also tried using GetActivePwrScheme and then ReadPwrScheme, but it doesn’t seem to work either. GetActivePwrScheme always returns 0, even if I switch power schemes. I also tried running ReadPwrScheme with incremental values (1,2,3). I got to 5 or 6 but it never returned the correct number for the value I set for monitor timeout in control panel.
I hope I have this totally wrong and there is a much easier way of doing this.
I finally did have some luck and found a function which works on both XP and Vista – GetCurrentPowerPolicies. It is very simple to call and returns a lot of the current settings including the setting I wanted VideoTimeoutAc and VideoTimeoutDc.