2023-07-17 13:28:22 +05:30
<#
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Name : Export Microsoft 365 Inactive Users Report using MS Graph PowerShell
Version : 2.0
website : o365reports . com
Script Highlights :
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
1 . The single script allows you to generate 10 + different inactive user reports .
2 . The script can be executed with an MFA-enabled account too .
3 . The script supports Certificate-based authentication ( CBA ) .
4 . Provides details about non-interactive sign-ins too .
5 . You can generate reports based on inactive days .
6 . Helps to filter never logged-in users alone .
7 . Generates report for sign-in enabled users alone .
8 . Supports filter inglicensed users alone .
9 . Gets inactive external users report .
10 . Export results to CSV file .
11 . The assigned licenses column will show you the user-friendly -name like ‘ Office 365 Enterprise E3 ’ rather than ‘ ENTERPRISEPACK ’ .
12 . Automatically installs the MS Graph PowerShell module ( if not installed already ) upon your confirmation .
13 . The script is scheduler friendly .
For detailed Script execution : https : / / o365reports . com / 2023 / 06 / 21 / microsoft - 365 -inactive -user -report -ms -graph -powershell
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
#>
Param
(
[ int ] $InactiveDays ,
[ int ] $InactiveDays_NonInteractive ,
[ switch ] $ReturnNeverLoggedInUser ,
[ switch ] $EnabledUsersOnly ,
[ switch ] $DisabledUsersOnly ,
[ switch ] $LicensedUsersOnly ,
[ switch ] $ExternalUsersOnly ,
[ switch ] $CreateSession ,
[ string ] $TenantId ,
[ string ] $ClientId ,
[ string ] $CertificateThumbprint
)
Function Connect_MgGraph
{
#Check for module installation
$Module = Get-Module -Name microsoft . graph -ListAvailable
if ( $Module . count -eq 0 )
{
Write-Host Microsoft Graph PowerShell SDK is not available -ForegroundColor yellow
$Confirm = Read-Host Are you sure you want to install module ? [ Y] Yes [N ] No
if ( $Confirm -match " [yY] " )
{
Write-host " Installing Microsoft Graph PowerShell module... "
Install-Module Microsoft . Graph -Repository PSGallery -Scope CurrentUser -AllowClobber -Force
}
else
{
Write-Host " Microsoft Graph PowerShell module is required to run this script. Please install module using Install-Module Microsoft.Graph cmdlet. "
Exit
}
}
#Disconnect Existing MgGraph session
if ( $CreateSession . IsPresent )
{
Disconnect-MgGraph
}
#Connecting to MgGraph beta
Select-MgProfile -Name beta
Write-Host Connecting to Microsoft Graph . . .
if ( ( $TenantId -ne " " ) -and ( $ClientId -ne " " ) -and ( $CertificateThumbprint -ne " " ) )
{
Connect-MgGraph -TenantId $TenantId -AppId $ClientId -CertificateThumbprint $CertificateThumbprint
}
else
{
Connect-MgGraph -Scopes " User.Read.All " , " AuditLog.read.All "
}
}
Connect_MgGraph
$ExportCSV = " .\InactiveM365UserReport_ $( ( Get-Date -format yyyy-MMM -dd -ddd ` hh-mm -ss ` tt ) . ToString ( ) ) .csv "
$ExportResult = " "
$ExportResults = @ ( )
#Get friendly name of license plan from external file
$FriendlyNameHash = Get-Content -Raw -Path . \ LicenseFriendlyName . txt -ErrorAction Stop | ConvertFrom-StringData
$Count = 0
$PrintedUser = 0
#retrieve users
$RequiredProperties = @ ( 'UserPrincipalName' , 'EmployeeId' , 'CreatedDateTime' , 'AccountEnabled' , 'Department' , 'JobTitle' , 'RefreshTokensValidFromDateTime' , 'SigninActivity' )
Get-MgUser -All -Property $RequiredProperties | select $RequiredProperties | ForEach-Object {
$Count + +
$UPN = $_ . UserPrincipalName
Write-Progress -Activity " `n Processing user: $Count - $UPN "
$EmployeeId = $_ . EmployeeId
$LastInteractiveSignIn = $_ . SignInActivity . LastSignInDateTime
$LastNon_InteractiveSignIn = $_ . SignInActivity . LastNonInteractiveSignInDateTime
$CreatedDate = $_ . CreatedDateTime
$AccountEnabled = $_ . AccountEnabled
$Department = $_ . Department
$JobTitle = $_ . JobTitle
$RefreshTokenValidFrom = $_ . RefreshTokensValidFromDateTime
#Calculate Inactive days
if ( $LastInteractiveSignIn -eq $null )
{
$LastInteractiveSignIn = " Never Logged In "
$InactiveDays_InteractiveSignIn = " - "
}
else
{
$InactiveDays_InteractiveSignIn = ( New-TimeSpan -Start $LastInteractiveSignIn ) . Days
}
if ( $LastNon_InteractiveSignIn -eq $null )
{
$LastNon_InteractiveSignIn = " Never Logged In "
$InactiveDays_NonInteractiveSignIn = " - "
}
else
{
$InactiveDays_NonInteractiveSignIn = ( New-TimeSpan -Start $LastNon_InteractiveSignIn ) . Days
}
if ( $AccountEnabled -eq $true )
{
$AccountStatus = 'Enabled'
}
else
{
$AccountStatus = 'Disabled'
}
#Get licenses assigned to mailboxes
$Licenses = ( Get-MgUserLicenseDetail -UserId $UPN ) . SkuPartNumber
$AssignedLicense = @ ( )
#Convert license plan to friendly name
if ( $Licenses . count -eq 0 )
{
$LicenseDetails = " No License Assigned "
}
else
{
foreach ( $License in $Licenses )
{
$EasyName = $FriendlyNameHash [ $License ]
if ( ! ( $EasyName ) )
{ $NamePrint = $License }
else
{ $NamePrint = $EasyName }
$AssignedLicense + = $NamePrint
}
$LicenseDetails = $AssignedLicense -join " , "
}
$Print = 1
#Inactive days based on interactive signins filter
if ( $InactiveDays_InteractiveSignIn -ne " - " )
{
if ( ( $InactiveDays -ne " " ) -and ( $InactiveDays -gt $InactiveDays_InteractiveSignIn ) )
{
$Print = 0
}
}
#Inactive days based on non-interactive signins filter
if ( $InactiveDays_NonInteractiveSignIn -ne " - " )
{
if ( ( $InactiveDays_NonInteractive -ne " " ) -and ( $InactiveDays_NonInteractive -gt $InactiveDays_NonInteractiveSignIn ) )
{
$Print = 0
}
}
#Never Logged In user
if ( ( $ReturnNeverLoggedInUser . IsPresent ) -and ( $LastInteractiveSignIn -ne " Never Logged In " ) )
{
$Print = 0
}
#Filter for external users
if ( ( $ExternalUsersOnly . IsPresent ) -and ( $UPN -notmatch '#EXT#' ) )
{
$Print = 0
}
#Signin Allowed Users
if ( $EnabledUsersOnly . IsPresent -and $AccountStatus -eq 'Disabled' )
{
$Print = 0
}
#Signin disabled users
if ( $DisabledUsersOnly . IsPresent -and $AccountStatus -eq 'Enabled' )
{
$Print = 0
}
#Licensed Users ony
if ( $LicensedUsersOnly -and $Licenses . Count -eq 0 )
{
$Print = 0
}
#Export users to output file
if ( $Print -eq 1 )
{
$PrintedUser + +
$ExportResult = [ PSCustomObject ] @ { 'UPN' = $UPN ; 'Creation Date' = $CreatedDate ; 'Last Interactive SignIn Date' = $LastInteractiveSignIn ; 'Last Non Interactive SignIn Date' = $LastNon_InteractiveSignIn ; 'Inactive Days(Interactive SignIn)' = $InactiveDays_InteractiveSignIn ; 'Inactive Days(Non-Interactive Signin)' = $InactiveDays_NonInteractiveSignin ; 'Refresh Token Valid From' = $RefreshTokenValidFrom ; 'Emp id' = $EmployeeId ; 'License Details' = $LicenseDetails ; 'Account Status' = $AccountStatus ; 'Department' = $Department ; 'Job Title' = $JobTitle }
$ExportResult | Export-Csv -Path $ExportCSV -Notype -Append
}
}
#Open output file after execution
Write-Host ` nScript executed successfully
if ( ( Test-Path -Path $ExportCSV ) -eq " True " )
{
Write-Host " Exported report has $PrintedUser user(s) "
$Prompt = New-Object -ComObject wscript . shell
$UserInput = $Prompt . popup ( " Do you want to open output file? " , ` 0 , " Open Output File " , 4 )
if ( $UserInput -eq 6 )
{
Invoke-Item " $ExportCSV "
}
Write-Host " Detailed report available in: $ExportCSV "
}
else
{
Write-Host " No user found " -ForegroundColor Red
2023-09-28 13:01:37 +05:30
}
Write-Host ` n ~ ~ Script prepared by AdminDroid Community ~ ~ ` n -ForegroundColor Green
Write-Host " ~~ Check out " -NoNewline -ForegroundColor Green ; Write-Host " admindroid.com " -ForegroundColor Yellow -NoNewline ; Write-Host " to get access to 1800+ Microsoft 365 reports. ~~ " -ForegroundColor Green ` n ` n