views:

2340

answers:

5

i want to be a good developer citizen, pay my taxes, and disable things if we're running over Remote Desktop, or running on battery.

If we're running over remote desktop (or equivalently in a Terminal server session), we must disable animations and double-buffering. You can check this with:

/// <summary>
/// Indicates if we're running in a remote desktop session.
/// If we are, then you MUST disable animations and double buffering i.e. Pay your taxes!
/// 
/// </summary>
/// <returns></returns>
public static Boolean IsRemoteSession
{
    //This is just a friendly wrapper around the built-in way
    get
    {
     return System.Windows.Forms.SystemInformation.TerminalServerSession;
    }
}

Now i need to find out if the user is running on battery power. If they are, i don't want to blow through their battery. i want to do things such as

  • disable animations
  • disable background spell-checking
  • disable background printing
  • turn off gradients
  • use graphics.SmoothingMode = SmoothingMode.HighSpeed;
  • use graphics.InterpolationMode = InterpolationMode.Low;
  • use graphics.CompositingQuality = CompositingQuality.HighSpeed;
  • minimize hard drive access - to avoid spin up
  • minimize network access - to save WiFi power

Is there a managed way to see if the machine is currently running on battery?

References

How do you convince developers to pay their "taxes"?

Taxes: Remote Desktop Connection and painting

GetSystemMetrics(SM_REMOTESESSION)


Update: The short answer is:

Boolean isRunningOnBattery = 
    (System.Windows.Forms.SystemInformation.PowerStatus.PowerLineStatus ==
     PowerLineStatus.Offline);
A: 

You could use WMI (Windows Management Instrumentation) to query the operating system about the battery status.

You could find more information here:

Hope that helps.

hmemcpy
+1  A: 

You could use the GetSystemPowerStatus function using P/Invoke. See: http://msdn.microsoft.com/en-gb/library/aa372693.aspx

Here's an example:

using System;
using System.Runtime.InteropServices;
namespace PowerStateExample
{
    [StructLayout(LayoutKind.Sequential)]
    public class PowerState
    {
        public ACLineStatus ACLineStatus;
        public BatteryFlag BatteryFlag;
        public Byte BatteryLifePercent;
        public Byte Reserved1;
        public Int32 BatteryLifeTime;
        public Int32 BatteryFullLifeTime;

        // direct instantation not intended, use GetPowerState.
        private PowerState() {}

        public static PowerState GetPowerState()
        {
            PowerState state = new PowerState();
            if (GetSystemPowerStatusRef(state))
                return state;

            throw new ApplicationException("Unable to get power state");
        }

        [DllImport("Kernel32", EntryPoint = "GetSystemPowerStatus")]
        private static extern bool GetSystemPowerStatusRef(PowerState sps);
    }

    // Note: Underlying type of byte to match Win32 header
    public enum ACLineStatus : byte
    {
        Offline = 0, Online = 1, Unknown = 255
    }

    public enum BatteryFlag : byte
    {
        High = 1, Low = 2, Critical = 4, Charging = 8,
        NoSystemBattery = 128, Unknown = 255
    }

    // Program class with main entry point to display an example.
    class Program
    {        
        static void Main(string[] args)
        {
            PowerState state = PowerState.GetPowerState();
            Console.WriteLine("AC Line: {0}", state.ACLineStatus);
            Console.WriteLine("Battery: {0}", state.BatteryFlag);
            Console.WriteLine("Battery life %: {0}", state.BatteryLifePercent);
        }
    }
}
driis
+15  A: 

I believe you can check SystemInformation.PowerStatus to see if it's on battery or not.

Boolean isRunningOnBattery =
      (System.Windows.Forms.SystemInformation.PowerStatus.PowerLineStatus == 
       PowerLineStatus.Offline);

Edit: In addition to the above, there's also a System.Windows.Forms.PowerStatus class. One of its methods is PowerLineStatus, which will equal PowerLineStatus.Online if it's on AC Power.

R. Bemrose
A: 

I don't believe it's exposed in managed code, but you can use the Win32 GetSystemPowerStatus via pinvoke to get this info.

As an aside, you may want to consider using the GetCurrentPowerPolicies or similar to determine the users preferences relating to performance/power management.

Andrew Grant
A quick look at the API (http://msdn.microsoft.com/en-us/library/aa372689(VS.85).aspx) didn't show anything related to any user preferences. It returns things like how slow the CPU will go, and if the monitor will be dimmed, and the fans will be turned off, etc.
Ian Boyd
Yes - the CPU speed is a user preference that can be controlled via the Power Settings control panel.Just a suggestion.
Andrew Grant
i was expecting things like "Disable animations", "Disable Glass transparency effects", "Disable alert sounds", etc
Ian Boyd
+5  A: 

R. Bemrose found the managed call. Here's some sample code:

/// <summary>
/// Indicates if we're running on battery power.
/// If we are, then disable CPU wasting things like animations, background operations, network, I/O, etc
/// </summary>
public static Boolean IsRunningOnBattery
{
   get
   {
      PowerLineStatus pls = System.Windows.Forms.SystemInformation.PowerStatus.PowerLineStatus;
      if (pls == PowerLineStatus.Offline)
      {
         //Offline means running on battery
         return true;
      }
      else
      {
         return false;
      }
   }
}
Ian Boyd
please just return pls == PowerLineStatus.Offline; This hurts my eyes.
Pim Jager
i prefer a helper function, so that people don't have to keep re-learning how to check for power line status. And nobody says that there is only one enumeration value for "on battery". Especially since there is a 3rd value in the enumeration. i want a single implementation for "are we on battery", and a central implementation that can be fixed when it turns out to be wrong.
Ian Boyd