Our Story

Who we are and how we solve complex IT challenges.

Our Certifications

Microsoft certifications and partnerships validating our technical expertise.

Leadership

Meet the Experienced Leadership Team Driving WME’s Success

Advisory Updates

Expert guidance on Microsoft, security, and compliance developments.

Case Studies

Real-world outcomes from complex Microsoft-focused IT engagements.

Financial Industry

Secure technology solutions for regulated banks and financial institutions.

Healthcare

Secure Microsoft solutions for compliant, connected, and modern healthcare organizations.

Manufacturing

Cloud and security solutions supporting modern manufacturing operations.

Non-Profit

Cost-efficient Microsoft solutions for mission-driven organizations.

Public Sector

Microsoft-based IT services for secure public sector modernization.

High Tech

Scalable cloud, security, and staffing for fast-growing technology companies.

SMBs

Scalable cloud, security, and staffing for fast-growing technology companies.

Cloud Migration Services

Transition your workloads to the cloud securely for greater scalability and performance.

Data Migration Services

Securely transfer your business data with minimal downtime and maximum integrity.

Application Migration Services

Move your applications seamlessly to modern platforms with minimal business disruption.

Identity & Security Migration Services

Strengthen identity management and security while transitioning to modern Microsoft solutions.

IT Staffing

Connect with skilled IT professionals to strengthen your team and accelerate project delivery.

Accounting & Finance

Connect with experienced accounting and finance professionals to support your business goals.

Licensing Support

Discover the benefits of both CSP and On-premises licensing options and find the best fit for your unique business needs. From cost savings to flexibility, we’ve got you covered.

Power Platform

Unlock the full potential of the Microsoft Power Platform Suite to streamline operations, automate repetitive tasks, and gain real-time insights that drive business growth.

Sharepoint Solutions

Supercharge your business productivity and enhance visibility through our proven SharePoint expertise.

Security Solutions

Protect your business with proactive cybersecurity, compliance, and risk management solutions.

Endpoint Management

Secure, manage, and monitor every device with modern endpoint management solutions.

Creating an Endpoint Protection Alert using PowerShell

July 6, 2020

MEMCM does not provide a built-in method for alerting administrators when a remediation action fails for Endpoint Protection. When remediation fails, the device is still considered infected, and may require manual intervention to complete remediation. This blog post details a method by which you can send an email whenever a computer enters this state.

This blog post replaces the post found here: Creating an Endpoint Protection Alert using System Center Orchestrator – (windowsmanagementexperts.com). Instead of using System Center Orchestrator, this method will use only a PowerShell script.

I completed this blog post using MEMCM 2002 on a server running Windows Server 2016.

Background

The Monitoring workspace of the MEMCM contains some valuable information about Endpoint Protection. If you open this workspace and expand Security, then Endpoint Protection Status, then Microsoft Defender Status, you should see a chart that looks like this:

This chart shows you what is happening in almost real time. As you can see, I have four devices where remediation failed (i.e. the device is still infected) and one device where the malware modified the client settings. These are the machines we are focusing on.

By default, this chart updates every 20 minutes when Endpoint Protection summarization runs. You can set that value lower or higher by using the MEMCM PowerShell cmdlets.

  1. Click the drop-down in the upper-left corner of the MEMCM console.
  1. Select Connect via Windows PowerShell.
  2. Run this command, changing the interval and unit type to fit your needs.
Set-CMEndpointProtectionSummarizationSchedule -Interval <value> -UnitType <minutes, hours, or days>

Prerequisites

To complete this blog post, you need two things.

First, you will need a service account. This service account will execute the script as a scheduled task. The account also needs to be assigned the “Read-Only Analyst” role in MEMCM console so that it can execute WMI queries against MEMCM.

Second, you will need a storage location to store files. The service account from prerequisite #1 needs full control of this storage location. The script creates a file in this location after sending the alert email. When the script executes again, it checks this directory for those files, and does not send another email if a file with the infected computer name exists. This is to prevent you from getting multiple emails for a single computer. The script will delete these files on a time interval defined in the script.

Script

The entire script is available at the bottom of this post. I’m going to walk through a couple of areas of the script, just to show you what is going on. There are two parts that require configuration from you; I’ve marked them as such. You will want to copy the entire script from the bottom of the page.

[Required Configuration] In lines 10-14, you define the variables that are important for the script function. The first two (lines 11-12) are self-explanatory. These are the site server name and site code for your environment. The next two (lines 13-14) define the trigger markers. For $marker_date_threshold, specify the number of days before the marker is deleted. You will not receive additional alerts for the computer within this date range. For $marker_file_dir, define the directory where the marker files are stored. This can be local to the computer running the script, or a network share.

# REQUIRED VARIABLES
$site_server = "sccm01.contoso.com"
$site_code = "S01"
$marker_date_threshold = 5
$marker_file_dir = "E:\EP-Alerts"

Line 33 of the script exits the script if no new alerts need to be created. This cuts down on the script execution time, as the script will not proceed any further if nothing new needs to happen.

if ($new_fail_comp_names -eq $null) {exit 0}

Line 36 of the script will grab the entire SMS_R_System class from WMI. If you have a large environment, be careful of this line and consider scoping it. This can be scoped by limiting it to collections, or by limiting the scope assigned to the service account. This is out of scope of this post, but examples can be found online.

$r_system = Get-WmiObject -ComputerName $site_server -namespace "root\sms\site_$site_code" -class SMS_R_System

Lines 39-99 process each new alert. Of particular importance are Lines 63-79, which configure the body of the email that is sent, so if you want to make changes, come here. It’s using HTML, so any HTML code here will work.

$body = @"
Computer Name: $comp_name
<br>
ConfigMgr Primary User: $user_name
<br>
Computer IP Address(es): $ip_a
<br>
Infection Name: $infection_name
<br>
EP Signature Version: $sig_ver
<br>
EP Antispyware Signature Last Update Date/Time: $vir_def_update
<br>
EP Last Full Scan Date/Time: $full_scan
<br>
EP Last Infection Time: $last_inf
"@

[Required Configuration] The email message is configured in Line 82. You must change the smtpserver, from, and to attributes to match your environment. This line also assumes that the smtp server is unauthenticated. You can also change the subject, if you like.

That’s it. You should be able to set this up as a scheduled task and let it run on whatever frequency you like. Just remember to run the scheduled task as the service account defined in the prerequisites.

Here is the entire script:

###########################################################################
###																		###
###		Endpoint Protection - Remediation Failed Alert					###
###		Version: 1.0													###
###		Modified: July 6, 2020											###
###		Downloaded from: https://windowsmanagementexperts.com/		###
###																		###
###########################################################################
# REQUIRED VARIABLES
$site_server = "sccm01.contoso.com" # ConfigMgr Site Server FQDN
$site_code = "S01" # ConfigMgr Site Code
$marker_date_threshold = 5 # Number of Days Before Alert re-Triggers
$marker_file_dir = "E:\EP-Alerts" # Location to Store Alert Marker Files. Can be local storage or network file share.

###########################################################################

# cleanup old markers
$f_marker_date_threshold = "-" + $marker_date_threshold
$date = (get-date).adddays($f_marker_date_threshold)
get-childitem -path $marker_file_dir | where-object -filterscript {$_.LastWriteTime -lt $date} | remove-item

# get all failed EP remediatations
$ep_failed = Get-WmiObject -ComputerName $site_server -namespace "root\sms\site_$site_code" -class SMS_CombinedDeviceResources | where-object -FilterScript {$_.EPInfectionStatus -eq "4"}

# exclude current alert triggers from being alerted again. Uses the alert marker files.
$new_fail_comp_names = $null
$cur_markers = (get-childitem $marker_file_dir).name
if ($cur_markers -eq $null) { $new_fail_comp_names = $ep_failed.Name }
else { $new_fail_comp_names = (compare-object -ReferenceObject $ep_failed.name -DifferenceObject $cur_markers).inputobject }

# exits script if no new alerts need to be generated
if ($new_fail_comp_names -eq $null) {exit 0}

# captures data about all systems to be used later to obtain IP addresss of computer.
$r_system = Get-WmiObject -ComputerName $site_server -namespace "root\sms\site_$site_code" -class SMS_R_System

# PROCESSES EACH FAILED REMEDIATION AND SENDS EMAIL
foreach ($comp_name in $new_fail_comp_names) {
# sets up IP address array
$ip_a = @()

# gets EP status entry for computer
$comp = $ep_failed | where-object -filterscript {$_.Name -eq $comp_name}

# gets primary user of computer
$user_name = $comp.UserName

# process data about EP state
$infection_name = $comp.EPLastThreatName
$sig_ver = $comp.EPAntivirusSignatureLastVersion
If (($comp.EPAntispywareSignatureLastUpdateDateTime) -gt "1") {$vir_def_update = $comp.ConvertToDateTime($comp.EPAntispywareSignatureLastUpdateDateTime)}
If (($comp.EPLastFullScanDateTimeEnd) -gt "1") {$full_scan = $comp.ConvertToDateTime($comp.EPLastFullScanDateTimeEnd)}
If (($comp.EPLastInfectionTime) -gt "1") {$last_inf = $comp.ConvertToDateTime($comp.EPLastInfectionTime)}

# gets IP address of computer
$ips = ($r_system | where-object -filterscript {$_.Name -eq $comp_name}).IPAddresses
ForEach ($ip in $ips) {
if ($ip -like "10.*" -or $ip -like "152.13.*") { $ip_a += $ip }
}

# creates HTML email body
$body = @"
Computer Name: $comp_name

ConfigMgr Primary User: $user_name

Computer IP Address(es): $ip_a

Infection Name: $infection_name

EP Signature Version: $sig_ver

EP Antispyware Signature Last Update Date/Time: $vir_def_update

EP Last Full Scan Date/Time: $full_scan

EP Last Infection Time: $last_inf
"@

# sends email
Send-MailMessage -smtpserver "smtp.contoso.com" -from "ConfigMgr Alerts <configmr@contoso.com>" -to "<sccm-admin@contoso.com>" -subject "[EP ALERT] Remediation Failed" -body $body -BodyAsHtml

# creates marker
new-item -itemtype file "$marker_file_dir\$comp_name" | out-null

# nulls all variables used in loop
$ip_a = $null
$comp = $null
$user_name = $null
$infection_name = $null
$sig_ver = $null
$vir_def_update = $null
$full_scan = $null
$last_inf = $null
$ips = $null
$body = $null

}

Disclaimer

All content provided on this blog is for information purposes only. Windows Management Experts, Inc makes no representation as to accuracy or completeness of any information on this site. Windows Management Experts, Inc will not be liable for any errors or omission in this information nor for the availability of this information. It is highly recommended that you consult one of our technical consultants, should you need any further assistance.

Share:

Facebook
Twitter
LinkedIn

Get Microsoft Updates Before They Cost You Downtime

Retirement dates, licensing changes, and security updates from a Microsoft-exclusive team, sent when they matter, not on a filler schedule.

More Posts

Copilot Cowork: Credit-Based Billing

Until now, Copilot Cowork has been included with M365 Copilot Premium licenses. Now that Cowork has moved out of public preview, Cowork is introducing a ...
Read Full Article
SharePoint OTP Retirement Is Coming in July 2026

SharePoint OTP Retirement Is Coming in July 2026 — What IT Admins Need to Do Before Access Breaks

Starting July 2026, external users who access OneDrive and SharePoint files through legacy SPO OTP links will start receiving access denied — silently, with no ...
Read Full Article
Power Virtual Agents Is Gone. Here's What Replaced It and Why It Matters.

Power Virtual Agents Is Gone. Here’s What Replaced It and Why It Matters.

If someone on your team still calls it “Power Virtual Agents,” they’re working from an outdated map. Microsoft retired the product on November 15, 2023 ...
Read Full Article

Get Microsoft Updates Before They Cost You Downtime

Retirement dates, licensing changes, and security updates from a Microsoft-exclusive team, sent when they matter, not on a filler schedule.
Subscription Form email