Having the misfortune of a sudden battery failure on my laptop the other day, it got me thinking about how we monitor laptop health across our environment. Wouldn’t it be cool if I could monitor battery health for all laptops in my organisation and get them to raise support tickets if they found their battery health was failing.
So once again going back to one of the most under utilised and powerful features of configuration manager (CI & CB), I set up a configuration item and baseline to perform the following actions
- Query the machine WMI for the manufactures max charge spec
- Query the WMI for the current max charge
- Compare the two values
- Should the battery health be below a set value (in my example below I used a very high value at 99%, obviously this is just for testing however I would recommend ~40% for real world monitoring) generate a full battery status report and email it to our IT Helpdesk using a template containing the Make, Model and Serial number of the laptop with the issue:

Email Notification

Attachment – Battery Health Report
Microsoft Script Library Link – https://gallery.technet.microsoft.com/Laptop-Battery-Health-98d1dc60
Note: This script requires Windows 8 upwards if you require the battery report attachment.
UPDATE – 24/2/2017
Following feedback from the community I have updated the script to allow environments with no internal SMTP relay or port 25 access to external SMTP servers to save the reports to a network share.
When the script runs and you use the -NetworkReport $true in the function call it will generate a CSV with the required values to generate an email and the battery report, the goal here is to get your reports saved to a server with access to the network share and SMTP ACL access. In this instance a new secondary script (which I have included in the updated link on the MS script link) can be scheduled to run on this server in order to generate the notifications to your helpdesk.
Things To Note:
You might want to consider including a date filter on line 51 in the LaptopBatteryNotifier.ps1 script so the helpdesk don’t receive mulitple emails for the same machine over time. For instance you could schedule the script to run every 7 days and only include machine reports within that period by changing the line to;
$Computers = Get-ChildItem -Path $NetworkShare | where-object {$_.LastWriteTime -gt (Get-Date).AddDays(-7)
If you are using this method make sure that the share has permissions for at least the Domain Computers and the account you are running the LaptopBatteryNotifier script to have full permissions to the share / folder. I would recommend that this folder is a hidden share in this instance.
Create A Configuration Item
Open the SCCM Management console and under Assets and Compliance\Compliance Settings select Configuration Item. Now create a new Configuration Item

Select Operating Systems
Pick the Operating Systems that you which to apply the CI to:

Add Settings
Click on New on this screen and select “Script” under Settings Type:
Discovery Script
Now enter your Discovery script (LaptopBatteryCheck.ps1 from the ZIP file). No remediation script is required unless you want to separate the email function.

Create A New Rule
Here we will select the settings previously created and set a target value for the new rule


Now the Configuration Item is in place, we can go onto setting up the Baseline to deploy to your chosen Collection.
Create A New Configuration Baseline
Create your new Configuration Baseline, Select the Configuration Item you set up in the previous steps and click OK.


The Final Step is to deploy your newly created Configuration Baseline to a chosen collection.
As always folks, please keep your PowerShell version installations up to date for compatibility.
Does anyone know where I can download the script now? I can’t find a link on this page.
Hi Greg,
The link is on the post – https://gallery.technet.microsoft.com/Laptop-Battery-Health-98d1dc60
Thank you for this, I implemented in on our pilot group and while about half the computers reported Compliant, the other half reported as Error, Description “Incorrect function”. I also tested on a VM and that was reported as Unknown, “Client check failed/Active”, which is probably expected.
Brilliant!
Can you do a similar one for hard drive failures?
Mick Pletcher has a configuration baseline that monitors error 51 events for predicted hard disk failure – https://mickitblog.blogspot.ie/2017/02/event-51-drive-failure-reporting-tool.html.
top work Maurice, just implemented this in to test . We use mostly use Lenovo so it doesn’t populate the the make/model in the email though in the report is the full information
This is great! A question I have is if you (or anyone) has had luck using this with HP laptops, specifically the ProBook line? In testing I was getting the exact same value for the design capacity and the full charge capacity. I’ll look at modifying it so if the model is, say, a HP ProBook 650 G1 model I will hard-code the design capacity.
–Neal
Hi Neal, the company I work for uses Dell hardware so I haven’t any HP devices to test. I’ll ask around a few of my contacts to see if they share your experience.
Hi Maurice, is there an change to get this runing on Windows 7?
The battery report is only available from Windows 8 and up unfortunately. I’m in an all Windows 10 environment so I have focused on that, however I’l have a look at Windows 7 and as long as the WMI objects are available then the email notice could be generated minus the attachment with only a small mod to the script.
+1 – Would love to get this working on windows 7 as well!
I’ve made this change and now it works also for Windows 7
$BatteryDesignSpec = (Get-WmiObject -Class “BatteryStaticData” -Namespace “ROOT\WMI” | Where-Object {$_.InstanceName -eq $($Battery.InstanceName)}).DesignedCapacity
$BatteryFullCharge = (Get-WmiObject -Class “BatteryFullChargedCapacity” -Namespace “ROOT\WMI” | Where-Object {$_.InstanceName -eq $($Battery.InstanceName)}).FullChargedCapacity
Seriously I love this! I did have one question. I modified the script for my environment including mail system, etc. when copying the script info into the CI item. I am not getting emails from my SCCM server even though it is whitelisted to send email. I went into the SCCM email settings and the test email works but the script properties I pasted into the CI isn’t generating the alert if it is non-compliant. I was able to get my laptop machine whitelisted to send email as a test and the script works fine if I run it via PowerShell. Any ideas? Loved the output and how you got this working.
Hi Chris. The script is executed on the clients so they will need port 25 access to your SMTP server directly. If this can’t be achieved for security reasons I could provide a script that would provide a work around by saving the client reports to a share, then a second script would poll the folders for health reports and generate SMTP traffic direct from the server.
That would be awesome. I don’t think I could get this opened for the security implications. The other option would be awesome if you could swing it.
Is it possible to add more than one recipient? I have tried the following listed below.
$Recipient = “[email protected]”,”[email protected]” – No error but email never goes through
$Recipient = (’[email protected],[email protected]’) – Invalid character was found in mail header
Try $Recipient = @(“[email protected]”,”[email protected]”)
Same result. No error but no email.
So technically a different result ;-). Have you confirmed that you have port 25 access to your SMTP server? Run the contents of the function and you’ll get a better idea of what the issue is.
Awesome work, it’s been really insightful with our staff fleet! Is there any reason you recommend 40% as the limit in production and not a higher value like 60% or 70% ?
Cheers
Hi Adrian
It’s really what value you and your hardware provider are happy with. On setting this up I found that 40% was the normal point for laptops to start reporting the issue on post, as many users would ignore it I thought this would help IT Helpdesks be informed of the issue.
Epic stuff! I’ve modified your script into just a standalone function I can have in my bag-o-tools! Thanks for the hard work!
The only thing I changed aside from parameterizing the variables used in the script, was to flip your $SendEmailNotice from a bool to a Switch. It prevents me from having to type $true to get it to kick.
That one small change and adding an ICM -Computername and a few -Computer flags on GWMI, and this is an excellent tool for on-demand diagnostics.