Introduction
As organizations move towards the Microsoft 365 ecosystem, managing user accounts in Microsoft Entra ID (formerly Azure Active Directory) becomes a routine task for system administrators and IT support teams.
One of the critical checks often required is verifying the account status—whether a user is enabled, disabled, or simply doesn’t exist in the tenant. This could be part of a regular audit, license cleanup, or onboarding/offboarding workflow.
Manually checking each user’s status through the Microsoft Entra admin portal is inefficient and time-consuming—especially in large environments.
That’s why I have written this PowerShell script: to automate the process of checking user status from a CSV list using the Microsoft Graph API.
Let’s walk through how it works, what you need, and how to use it in your environment.
💡 What the Script Does
This script performs the following steps:
- Connects to Microsoft Graph using delegated permissions.
- Reads a CSV file containing user email addresses (
UserPrincipalName
). - Queries Microsoft Entra ID for each user’s account status.
- Builds a report indicating whether the user is:
- Enabled
- Disabled
- Not Found
- Displays the report in the PowerShell console.
- Exports the report to a timestamped CSV file for record-keeping or further analysis.
📥 Script Download
👉 You can download the full script from my GitHub repo:
🔗 Check-EntraIDUserStatus.ps1 – GitHub
📋 Use Case Scenarios
Here are a few real-world scenarios where this script becomes incredibly useful:
- ✅ Audit and compliance: Validate account status for a list of critical users.
- 🧹 License cleanup: Check if disabled accounts are still consuming licenses.
- 👋 Offboarding verification: Ensure accounts of departed users are disabled.
- 🔍 Troubleshooting: Quickly check if a user experiencing access issues is active or disabled.
⚙️ Prerequisites
To use this script, make sure the following requirements are met:
✅ PowerShell
- PowerShell 7.0+ is recommended for better performance and compatibility.
- You can check your version using:
$PSVersionTable.PSVersion
- You can check your version using:
✅ Microsoft.Graph Module
- This script uses the modern Microsoft Graph PowerShell SDK (not the legacy AzureAD module).
- To install: powershellCopyEdit
Install-Module Microsoft.Graph -Scope CurrentUser
- To install: powershellCopyEdit
✅ Permissions
- You must log in with an account that has delegated access with the scope:
User.Read.All
- When prompted, you’ll sign in interactively.
✅ Input File Format
- The input file should be a CSV with a column named
UserPrincipalName
.
Example:
UserPrincipalName
alice@yourdomain.com
bob@yourdomain.com
🧑💻 Script Walkthrough
🔗 Connect to Microsoft Graph
Connect-MgGraph -Scopes "User.Read.All"
This initiates a sign-in to Microsoft Graph with the necessary permissions to read user data.
📂 Define File Paths
$inputPath = "C:\Temp\input\upncheckentraid.csv"
$outputPath = "C:\Temp\output"
These define where the script looks for the CSV and where to save the output. Make sure the folders exist or allow the script to create them.
🕓 Timestamped Output Filename
$timestamp = Get-Date -Format "ddMMyyyy-HHmm"
$outputFileName = "UserStatusReport-$timestamp.csv"
$outputPathFileName = Join-Path -Path $outputPath -ChildPath $outputFileName
This ensures that each output file is uniquely named and doesn’t overwrite previous reports.
📥 Import CSV and Prepare Output
$usersList = Import-Csv -Path $inputPath
$results = @()
if (-not (Test-Path $outputPath)){
New-Item -ItemType Directory -Path $outputPath -Force | Out-Null
}
The script imports the list of users from CSV and ensures the output folder exists.
🔄 Process Each User
foreach ($user in $usersList) {
$upn = $user.UserPrincipalName
try {
$userInfo = Get-MgUser -UserId $upn -Property Id, DisplayName, UserPrincipalName, AccountEnabled -ErrorAction Stop
$status = if ($userInfo.AccountEnabled) { "Enabled" } else { "Disabled" }
$results += [PSCustomObject]@{
UserPrincipalName = $userInfo.UserPrincipalName
DisplayName = $userInfo.DisplayName
Status = $status
}
}
catch {
$results += [PSCustomObject]@{
UserPrincipalName = $upn
DisplayName = "Not Found"
Status = "Not Found in Entra ID"
}
}
}
This is the core loop:
- For each user:
- Attempts to fetch data from Entra ID.
- If successful, checks the
AccountEnabled
field. - If not found, adds a fallback result showing the user is not in the directory.
📊 Display and Export Results
$results | Format-Table -AutoSize
$results | Export-Csv -Path $outputPathFileName -NoTypeInformation
Write-Output "User status report exported to path: $outputPathFileName"
At the end:
- A neat table is shown in the console.
- The results are saved as a CSV for later use.
🧪 Sample Output
UserPrincipalName | DisplayName | Status |
---|---|---|
alice@yourdomain.com | Alice Johnson | Enabled |
bob@yourdomain.com | Bob Smith | Disabled |
invalid@yourdomain.com | Not Found | Not Found in Entra ID |