Thursday, 20 March 2025

Automating Email Alerts for Non-Compliant Devices in Intune via PowerShell and Graph API

Managing devices through Microsoft Intune requires efficient tracking of device compliance, and one key task for administrators is to keep users informed about the status of their devices. In some cases, users may have devices that are not compliant with your organization’s policies. To automate the process of notifying these users, you can use the Microsoft Graph API in combination with PowerShell to send an email to users whose devices are non-compliant.

In this blog post, we'll walk through a PowerShell script that pulls non-compliant device data from Intune via the Microsoft Graph API and sends a notification email to the user informing them about the non-compliant status.

Prerequisites:

Before running the script, ensure the following prerequisites are met:

  1. Microsoft Graph PowerShell SDK is installed. You can install it with the following command:

                                Install-Module Microsoft.Graph -Scope CurrentUser

  1. Permissions: Make sure your account has the necessary Microsoft Graph API permissions to read device data and send emails. The required permissions are:
    • DeviceManagementManagedDevices.ReadWrite.All to manage devices.
    • User.Read to read user information.
  2. SMTP Server Setup: You need access to an SMTP server (in this case, Office 365) to send emails.
  3. PowerShell Version: Ensure you are using PowerShell 7.x or a version that supports the required modules.

PowerShell Script to Send Emails to Non-Compliant Users

Here is a simple PowerShell script to get the non-compliant devices and send an email to the respective users:

# Connect to Microsoft Graph

# Connect to Microsoft Graph

Connect-MgGraph -Scopes "DeviceManagementManagedDevices.ReadWrite.All", "User.Read"

 

# Get the list of non-compliant devices

$nonCompliantDevices = Get-MgDeviceManagementManagedDevice -Filter "complianceState eq 'noncompliant'"

 

# Check if we found any non-compliant devices

if ($nonCompliantDevices -eq $null -or $nonCompliantDevices.Count -eq 0) {

    Write-Host "No non-compliant devices found."

    exit

}

 

# Loop through each non-compliant device and send an email

foreach ($device in $nonCompliantDevices) {

    # Display device details in console (for debugging)

    Write-Host "User: $($device.userPrincipalName)"

    Write-Host "Device Name: $($device.deviceName)"

    Write-Host "Compliance State: $($device.complianceState)"

    Write-Host "----------------------------------------------------------"

 

    # Prepare email subject and body

    $subject = "Non-Compliant Device"

    $body = "Device $($device.deviceName) assigned to $($device.userPrincipalName) is not currently compliant."

   

    # Email settings

    $smtpServer = "smtp.office365.com"

    $from = "IntuneAdmin@domain.com"

    $to = $device.userPrincipalName

    $port = 587

 

    # Ensure email address is valid

    if ($to -match "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$") {

        try {

            # Send email using SMTP

            Send-MailMessage -To $to -Subject $subject -Body $body -SmtpServer $smtpServer -From $from -UseSsl -Port $port

            Write-Host "Email sent to: $to"

        } catch {

            Write-Error "Failed to send email to $to. Error: $_"

        }

    } else {

        Write-Host "Invalid email address for user: $($device.userPrincipalName)"

    }

}

 

# Optional: Disconnect from the Graph API after the operation

Disconnect-MgGraph

Useful References:

  1. Microsoft Graph PowerShell SDK documentation: https://learn.microsoft.com/en-us/powershell/microsoftgraph/intune/introduction

Conclusion:

By using the Microsoft Graph API and PowerShell, you can easily automate the process of identifying non-compliant devices in Microsoft Intune and sending out notifications to users. This script helps improve compliance management and ensures that users are promptly informed of any issues with their devices.

 

Wednesday, 19 March 2025

SCCM Audit: 3 Methods to Identify Audit Status

 When managing an SCCM (System Center Configuration Manager) environment, it’s crucial to regularly audit your deployments, installations, and overall system health. Fortunately, SCCM provides various options to identify audit statuses and troubleshoot potential issues. In this blog post, we'll explore three methods you can use to identify the audit status in SCCM: Status Filter Rule, Default Report, and SQL Query. We'll also provide a sample SQL query to help you get the audit status based on Message ID and strings.

1. Using Status Filter

The first method to track audit status is by using the Status Filter in the SCCM console. This option allows you to filter messages based on criteria such as message type, severity, and date.

To use the Status Filter:

  • Navigate to Monitoring in the SCCM Console.
  • Under System Status, select Status Messages.
  • Use the filtering options to narrow down to the specific status you're looking for.

This is a quick and easy way to check the status of various tasks within SCCM, including package deployments and client health.

2. Using Default Report

SCCM also provides a set of default built-in reports, which are useful for auditing purposes. These reports provide visibility into package deployments, software updates, client activity, and more.

To access default reports:

  • Go to the Monitoring workspace in the SCCM Console.
  • Under Reporting, select Reports.
  • Browse the list of available reports and select the one relevant to your audit.

These reports are pre-configured to give you insights into various aspects of your environment, such as package distribution, client status, and software update compliance.

3. Using SQL Query

If you want more flexibility and advanced querying capabilities, SQL queries are a powerful tool. You can directly query the SCCM database to retrieve audit information based on specific message IDs and strings.

Below is an example SQL query to help you get audit status based on the Message ID and Message String:

SELECT *

FROM vStatusMessagesWithStrings

WHERE MessageID = '30000'

AND InsStrValue3 LIKE '%packagename%'

In this query:

  • vStatusMessagesWithStrings is the SCCM view that contains status messages along with their associated strings.
  • MessageID = '30000' filters the messages for a specific ID, in this case, 30000 (this ID represents a specific status event such as successful package deployment).
  • InsStrValue3 LIKE '%packagename%' further narrows the results to only show messages containing the package name.

Microsoft Technet Blog on Status Message IDs

For further information on the different Message IDs in SCCM, you can refer to the Microsoft Technet Blog. The blog provides an extensive list of SCCM Status Message IDs and their titles. This will help you understand what each message ID represents and how you can use them for better auditing.

Here is the link to the Microsoft Technet Blog that contains detailed information on status message IDs.

Conclusion

By using Status Filter, Default Reports, or SQL Queries, you can effectively track and monitor the audit status of your SCCM environment. SQL queries, in particular, offer advanced flexibility for detailed audits. The sample query provided above is just one example, and you can modify it according to your specific needs. For further reference, the Microsoft Technet Blog provides a complete list of status message IDs and their explanations, which will be extremely helpful for identifying and troubleshooting issues within your SCCM environment.

Stay on top of your SCCM environment's health, and leverage these methods for effective auditing and troubleshooting

Tuesday, 11 March 2025

Windows Update Management from SCCM to Intune

Moving Windows Update Workload from SCCM to Intune and Cleanup GPO Registry Keys for Smooth Intune Update Deployment

As organizations increasingly adopt Intune for modern device management, it becomes necessary to transition certain workloads, such as Windows Update management, from SCCM (System Center Configuration Manager) to Intune. This shift enables you to leverage cloud-based management, offering benefits like simplified administration and greater flexibility.

 

In this blog post, we'll explore how to move the Windows Update workload from SCCM to Intune and use PowerShell scripts to clean up old Group Policy Objects (GPO) registry keys that may interfere with Intune-based update management. Additionally, we will discuss how to use detection and remediation scripts to ensure the devices are ready for Intune update deployment.

 

Steps to Move Windows Update Workload from SCCM to Intune

Before you can move your Windows Update management from SCCM to Intune, you need to follow a few steps to properly set up your environment for Intune-based Windows Update management:

 

1. Disable SCCM Software Update Point (SUP)

The Software Update Point (SUP) role in SCCM manages Windows updates. To transition this responsibility to Intune, the first step is to disable the update management in SCCM.

 

In SCCM, go to Administration > Site Configuration > Sites.

Right-click on the site where the SUP role is installed, and select Remove Roles.

Uncheck the Software Update Point and confirm the removal.

2. Enable Windows Update for Business (WUfB) in Intune

Next, configure Windows Update for Business (WUfB) policies in Intune to manage updates:

 

In the Microsoft Endpoint Manager Admin Center, navigate to Devices > Windows > Update Rings for Windows 10 and later.

Create a new update ring that defines when and how updates are deployed to your devices.

Configure update settings like deferral periods, active hours, and automatic update behavior.

3. Assign Update Rings to Devices

Once the update rings are configured, assign them to relevant groups or devices in your environment. This ensures that Intune will control how and when updates are deployed to these devices.

 

Using PowerShell Scripts for GPO Registry Cleanup

When transitioning to Intune-managed updates, you may need to clean up old Group Policy registry keys set by SCCM, WSUS, or previous GPO configurations. These old registry settings can interfere with Intune’s update management.

 

We will use a PowerShell script for detection and remediation of Windows Update-related registry keys.

 

Detection Script: Check for Existing GPO Registry Settings

This script checks if any Windows Update-related registry keys are still present, indicating that Windows Update is being managed by an old GPO. If found, it will return a non-compliant status.

 

# WU Registry Key Detection Script

$regPath = "HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate"

$keys = Get-ItemProperty -Path $regPath -ErrorAction SilentlyContinue

 

if ($keys) {

    Write-Output "Windows Update GPO settings found"

    exit 1  # Non-compliant status

} else {

    Write-Output "No Windows Update GPO settings found"

    exit 0  # Compliant status

}

Remediation Script: Clean Up Registry Keys

If the detection script finds Windows Update GPO settings, the remediation script will delete the associated registry keys, ensuring that Intune can take over Windows Update management.

 

# Remediation Script to clean up GPO registry keys for Intune update deployment

 

# Define the registry paths to be deleted

$registryPaths = @(

    "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate",

    "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"

)

 

# Function to delete registry keys

function Remove-RegistryKey {

    param (

        [string]$path

    )

    if (Test-Path $path) {

        Remove-Item -Path $path -Recurse -Force

        Write-Host "Deleted registry key: $path"

    } else {

        Write-Host "Registry key not found: $path"

    }

}

 

# Delete the registry keys

foreach ($path in $registryPaths) {

    Remove-RegistryKey -path $path

}

 

# Restart Windows Update service to apply changes

Restart-Service -Name wuauserv

 

Write-Host "Registry cleanup complete. The device is now ready for Intune update deployment."

Additional Detection Script: Verify Windows Update Service (WUfB)

This script checks whether the Windows Update service is being managed by Intune (via Windows Update for Business). If it is, the device is ready for Intune updates.

# Detection Script to verify if Windows Update is managed by Intune (WUfB)

$WUServiceManager = New-Object -ComObject "Microsoft.Update.ServiceManager"

$WUService = $WUServiceManager.Services | Where-Object { $_.IsDefaultAUService -eq $true }

$WUServiceNameDetails = $WUService.Name

 

if ($WUService.Name -eq "Microsoft Update") {

    Write-Output "Intune (WUfB) - $WUServiceNameDetails."

    Exit 0  # Compliant

} else {

    Write-Output "Not Intune (WUfB) - $WUServiceNameDetails."

    Exit 1  # Non-compliant

}

This detection script will help confirm that the Microsoft Update service is controlled by Intune’s Windows Update for Business (WUfB) settings.

 

Conclusion

Transitioning the Windows Update workload from SCCM to Intune allows for a modern, cloud-based approach to update management. By cleaning up old GPO registry keys and verifying that devices are configured for Intune-managed updates, you ensure a smooth and seamless update process for your organization's devices.

By using PowerShell scripts for detection and remediation, you automate the process of preparing devices for Windows Update for Business (WUfB) in Intune, making the transition efficient and secure.

Monday, 10 March 2025

Troubleshooting of SCCM Windows Update Deployment with PowerShell Scripts

 

Introduction

Managing and deploying Windows Updates in an enterprise environment can sometimes become a challenging task. Often, updates fail to install or are stuck in a pending state. When troubleshooting such issues in an SCCM (System Center Configuration Manager) environment, PowerShell scripts can be a powerful tool to monitor, remediate, and resolve common issues. This blog post will guide you through using PowerShell scripts within SCCM Configuration Items (CI) for monitoring and remediating Windows Update deployment issues.

We'll walk through:

  1. Monitoring Windows Update Folder Activity with a PowerShell script.
  2. Remediation of Common Windows Update Issues using PowerShell, such as stopping update services, clearing cache, and resetting configurations.

1. Monitoring Script: Checking Windows Update Folder Activity

The first step in troubleshooting Windows Update issues is to ensure the update files are being handled correctly. The SoftwareDistribution folder stores update-related files, and if it's not being updated regularly, it could indicate a problem with the update process.

Monitor Script:

# Define the folder path you want to check

$folderPath = "C:\Windows\SoftwareDistribution"

# Get the current date

$currentDate = Get-Date

# Get the folder's LastWriteTime property

$folderLastModified = (Get-Item $folderPath).LastWriteTime

# Calculate the time span between the current date and the folder's last modification date

$timeSpan = $currentDate - $folderLastModified

# Check if the folder was last modified within the last 15 days

if ($timeSpan.TotalDays -le 15) {

    Write-Host "Compliant"

} else {

    Write-Host "Non-Compliant"

}


2. Remediation Script: Resolving Windows Update Issues

When updates aren't working as expected, it's time to run a remediation script. This script will:

  • Stop Windows Update services.
  • Clear out old update cache and logs.
  • Rename the SoftwareDistribution and CatRoot2 folders (which may become corrupted).
  • Reset client settings and force discovery of new updates.

Remediation Script:

$arch = Get-WMIObject -Class Win32_Processor -ComputerName LocalHost | Select-Object AddressWidth

$ErrorActionPreference = 'SilentlyContinue'

Write-Host "1. Stopping Windows Update Services..."

Stop-Service -Name BITS -Force

Stop-Service -Name wuauserv -Force

Stop-Service -Name appidsvc -Force

Stop-Service -Name cryptsvc -Force

Write-Host "2. Remove QMGR Data file..."

Remove-Item "$env:allusersprofile\Application Data\Microsoft\Network\Downloader\qmgr*.dat" -ErrorAction SilentlyContinue

Stop-Service -Name BITS -Force

Stop-Service -Name wuauserv -Force

Stop-Service -Name appidsvc -Force

Stop-Service -Name cryptsvc -Force

Write-Host "3. Renaming the Software Distribution and CatRoot Folder..."

Remove-Item $env:systemroot\SoftwareDistribution.bak -Force -Recurse

Rename-Item $env:systemroot\SoftwareDistribution SoftwareDistribution.bak -ErrorAction SilentlyContinue

Rename-Item $env:systemroot\System32\Catroot2 catroot2.bak -ErrorAction SilentlyContinue

Write-Host "4. Removing old Windows Update log..."

Remove-Item $env:systemroot\WindowsUpdate.log -ErrorAction SilentlyContinue

Stop-Service -Name BITS -Force

Stop-Service -Name wuauserv -Force

Stop-Service -Name appidsvc -Force

Stop-Service -Name cryptsvc -Force

Write-Host "5. Resetting the Windows Update Services to default settings..."

"sc.exe sdset bits D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)"

"sc.exe sdset wuauserv D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)"

Set-Location $env:systemroot\system32

Write-Host "6) Removing WSUS client settings..."

REG DELETE "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate" /v AccountDomainSid /f

REG DELETE "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate" /v PingID /f

REG DELETE "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate" /v SusClientId /f

Write-Host "7) Delete all BITS jobs..."

Get-BitsTransfer | Remove-BitsTransfer

Write-Host "8) Starting Windows Update Services..."

Start-Service -Name BITS -Force

Start-Service -Name wuauserv -Force

Start-Service -Name appidsvc -Force

Start-Service -Name cryptsvc -Force

Start-Sleep -Seconds 10

Invoke-WmiMethod -Namespace "root\ccm" -Class "SMS_Client" -Name "ResetPolicy" -ArgumentList 1

Start-Sleep -Seconds 10

Invoke-WmiMethod -Namespace root\ccm -Class sms_client -Name TriggerSchedule "{00000000-0000-0000-0000-000000000021}"

Start-Sleep -Seconds 10

Invoke-WmiMethod -Namespace root\ccm -Class sms_client -Name TriggerSchedule "{00000000-0000-0000-0000-000000000113}"

Start-Sleep -Seconds 10

Invoke-WmiMethod -Namespace root\ccm -Class sms_client -Name TriggerSchedule "{00000000-0000-0000-0000-000000000114}"

Start-Sleep -Seconds 10

Invoke-WmiMethod -Namespace root\ccm -Class sms_client -Name TriggerSchedule "{00000000-0000-0000-0000-000000000026}"

Write-Host "9) Forcing discovery..."

wuauclt /resetauthorization /detectnow

 

Write-Host "Process complete. Please reboot your computer."


Conclusion

By using SCCM Configuration Items (CI) and PowerShell scripts, you can efficiently monitor and remediate Windows Update issues in your environment. The monitoring script helps identify whether updates are happening, while the remediation script tackles common update failures and clears the way for a successful update process.

SCCM Collection Relationships Using SQL Queries

  In System Center Configuration Manager (SCCM), collections are used to group systems or devices based on specific criteria for easier mana...