373 lines
24 KiB
PowerShell
373 lines
24 KiB
PowerShell
<#PSScriptInfo
|
|
.SYNOPSIS
|
|
Script for Intune to set Primary User on Device
|
|
|
|
.DESCRIPTION
|
|
This script will get the Entra Sign in logs for Windows Sign ins
|
|
The script then determine who has logged on to the device the most times in the last 30 days and set the Primary user to that user
|
|
The script uses Ms Graph with MGGraph modules
|
|
|
|
.EXAMPLE
|
|
.\Intune-Set-PrimaryUser.ps1
|
|
Will set the primary user for devices in Intune
|
|
|
|
.NOTES
|
|
Written by Mr-Tbone (Tbone Granheden) Coligo AB
|
|
torbjorn.granheden@coligo.se
|
|
|
|
.VERSION
|
|
2.0
|
|
|
|
.RELEASENOTES
|
|
1.0 2023-02-14 Initial Build
|
|
2.0 2021-03-01 Large update to use Graph batching and reduce runtime
|
|
|
|
.AUTHOR
|
|
Tbone Granheden
|
|
@MrTbone_se
|
|
|
|
.COMPANYNAME
|
|
Coligo AB
|
|
|
|
.GUID
|
|
00000000-0000-0000-0000-000000000000
|
|
|
|
.COPYRIGHT
|
|
Feel free to use this, But would be grateful if My name is mentioned in Notes
|
|
|
|
.CHANGELOG
|
|
1.0.2202.1 - Initial Version
|
|
2.0.2312.1 - Large update to use Graph batching and reduce runtime
|
|
#>
|
|
|
|
#region ---------------------------------------------------[Set script requirements]-----------------------------------------------
|
|
#
|
|
#Requires -Modules Microsoft.Graph.Authentication
|
|
#Requires -Modules Microsoft.Graph.DeviceManagement
|
|
#Requires -Modules Microsoft.Graph.Reports
|
|
#
|
|
#endregion
|
|
|
|
#region ---------------------------------------------------[Script Parameters]-----------------------------------------------
|
|
#endregion
|
|
|
|
#region ---------------------------------------------------[Modifiable Parameters and defaults]------------------------------------
|
|
# Customizations
|
|
[System.Object]$Enrollmentaccounts = @("install@tbone.se","wds@tbone.se") # @() = No Enrollment accounts. @("wds@tbone.se","wds2@tbone.se") = will filter them out and not assign them as primary users.
|
|
[int]$SigninsTimeSpan = 30 # Number of days back in time to look back for Sign-In logs (Default 30 days)
|
|
[int]$DeviceTimeSpan = 30 # Number of days back in time to look back for active devices (Default 30 days)
|
|
[Bool]$TestMode = $False # $True = No changes will be made on Primary owner, $False = Primary Owner will be changed
|
|
[Bool]$Verboselogging = $False # $Ture = Enable verbose logging for t-shoot. $False = Disable Verbose Logging
|
|
[Bool]$ReturnReport = $True # $True = Will return a report with all devices and primary users. $False = No report will be returned
|
|
#Batch Runtime settings
|
|
[Bool]$RunBatchMode = $true #Run the script in batch mode, faster but uses more memory, recommended for large environments
|
|
[int]$Batchsize = 20 #How many objects to process in each batch
|
|
[int]$waittime = 0 #How many seconds to wait between Batches to avoid throttling
|
|
[int]$MaxRetry = 50 #How many retries of trottled requests before error
|
|
#endregion
|
|
|
|
#region ---------------------------------------------------[Set global script settings]--------------------------------------------
|
|
Set-StrictMode -Version Latest
|
|
#endregion
|
|
|
|
#region ---------------------------------------------------[Import Modules and Extensions]-----------------------------------------
|
|
import-Module Microsoft.Graph.Authentication
|
|
import-Module Microsoft.Graph.DeviceManagement
|
|
import-Module Microsoft.Graph.Reports
|
|
#endregion
|
|
|
|
#region ---------------------------------------------------[Static Variables]------------------------------------------------------
|
|
[Int64]$MemoryUsage = 0
|
|
[System.Object]$report = @()
|
|
[System.Object]$IntuneDevices = @()
|
|
[System.Object]$SignInLogs = @()
|
|
[System.Object]$AllPrimaryUsersHash = @()
|
|
[System.Object]$RequiredScopes = ("DeviceManagementManagedDevices.ReadWrite.All", "AuditLog.Read.All", "User.Read.All")
|
|
[datetime]$scriptStartTime = Get-Date
|
|
[datetime]$SignInsStartTime = (Get-Date).AddDays(-$SigninsTimeSpan )
|
|
[datetime]$DeviceStartTime = (Get-Date).AddDays(-$DeviceTimeSpan )
|
|
if ($Verboselogging){$VerbosePreference = "Continue"}
|
|
else{$VerbosePreference = "SilentlyContinue"}
|
|
#endregion
|
|
|
|
#region ---------------------------------------------------[Functions]------------------------------------------------------------
|
|
function ConnectTo-MgGraph {
|
|
param (
|
|
[System.Object]$RequiredScopes
|
|
)
|
|
Begin {
|
|
$ErrorActionPreference = 'stop'
|
|
[String]$resourceURL = "https://graph.microsoft.com/"
|
|
$GraphAccessToken = $null
|
|
if ($env:AUTOMATION_ASSET_ACCOUNTID) { [Bool]$ManagedIdentity = $true} # Check if running in Azure Automation
|
|
else { [Bool]$ManagedIdentity = $false} # Otherwise running in Local PowerShell
|
|
}
|
|
Process {
|
|
if ($ManagedIdentity){ #Connect to the Microsoft Graph using the ManagedIdentity and get the AccessToken
|
|
Try{$response = [System.Text.Encoding]::Default.GetString((Invoke-WebRequest -UseBasicParsing -Uri "$($env:IDENTITY_ENDPOINT)?resource=$resourceURL" -Method 'GET' -Headers @{'X-IDENTITY-HEADER' = "$env:IDENTITY_HEADER"; 'Metadata' = 'True'}).RawContentStream.ToArray()) | ConvertFrom-Json
|
|
$GraphAccessToken = $response.access_token
|
|
Write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to get an Access Token to Graph for managed identity"
|
|
}
|
|
Catch{Write-Error "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Failed to get an Access Token to Graph for managed identity, with error: $_"}
|
|
$GraphVersion = ($GraphVersion = (Get-Module -Name 'Microsoft.Graph.Authentication' -ErrorAction SilentlyContinue).Version | Sort-Object -Desc | Select-Object -First 1)
|
|
if ('2.0.0' -le $GraphVersion) {
|
|
Try{Connect-MgGraph -ManagedIdentity -Nowelcome
|
|
$GraphAccessToken = convertto-securestring($response.access_token) -AsPlainText -Force
|
|
Write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to connect to Graph with module 2.x and Managedidentity"}
|
|
Catch{Write-Error "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Failed to connect to Graph with module 2.x and Managedidentity, with error: $_"}
|
|
}
|
|
else {#Connect to the Microsoft Graph using the AccessToken
|
|
Try{Connect-mgGraph -AccessToken $GraphAccessToken
|
|
Write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to connect to Graph with module 1.x and Managedidentity"}
|
|
Catch{Write-Error "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Failed to connect to Graph with module 1.x and Managedidentity, with error: $_"}
|
|
}
|
|
}
|
|
else{
|
|
Try{Connect-MgGraph -Scope $RequiredScopes -NoWelcome
|
|
Write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to connect to Graph manually"}
|
|
Catch{Write-Error "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Failed to connect to Graph manually, with error: $_"}
|
|
}
|
|
#Check and cleanup memory after connecting to Graph
|
|
return $GraphAccessToken
|
|
}
|
|
End {$MemoryUsage = [System.GC]::GetTotalMemory($true)
|
|
Write-Verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to cleanup Memory usage after connect to Graph to: $(($MemoryUsage/1024/1024).ToString('N2')) MB"
|
|
}
|
|
}
|
|
function get-mggraphrequestbatch {
|
|
Param(
|
|
[string]$RunProfile,
|
|
[string]$Object,
|
|
[String]$Method,
|
|
[system.object]$Objects,
|
|
[string]$Uri,
|
|
[int]$BatchSize,
|
|
[int]$WaitTime,
|
|
[int]$MaxRetry
|
|
)
|
|
Begin {
|
|
$Retrycount = 0
|
|
$CollectedObjects = [System.Collections.ArrayList]@()
|
|
$LookupHash = @{}
|
|
if ($env:AUTOMATION_ASSET_ACCOUNTID) {$ManagedIdentity = $true} # Check if running in Azure Automation
|
|
else {$ManagedIdentity = $false} # Otherwise running in Local PowerShell
|
|
}
|
|
Process {
|
|
do {
|
|
$TotalObjects = $objects.count
|
|
[int]$i = 0
|
|
$currentObject = 0
|
|
$RetryObjects = [System.Collections.ArrayList]@()
|
|
#Start looping all objects and run batches
|
|
for($i=0;$i -lt $TotalObjects;$i+=$BatchSize){
|
|
# Create Requests of id, method and url
|
|
[System.Object]$req = @()
|
|
if($i + ($BatchSize-1) -lt $TotalObjects){
|
|
$req += ($objects[$i..($i+($BatchSize-1))] | Select-Object @{n='id';e={$_.id}},@{n='method';e={'GET'}},@{n='url';e={"/$($Object)/$($_.id)$($uri)"}})
|
|
} elseif ($TotalObjects -eq 1) {
|
|
$req += ($objects[$i] | Select-Object @{n='id';e={$_.id}},@{n='method';e={'GET'}},@{n='url';e={"/$($Object)/$($_.id)$($uri)"}})
|
|
} else {
|
|
$req += ($objects[$i..($TotalObjects-1)] | Select-Object @{n='id';e={$_.id}},@{n='method';e={'GET'}},@{n='url';e={"/$($Object)/$($_.id)$($uri)"}})
|
|
}
|
|
|
|
#Send the requests in a batch
|
|
$responses = invoke-mggraphrequest -Method POST `
|
|
-URI "https://graph.microsoft.com/$($RunProfile)/`$batch" `
|
|
-body (@{'requests' = $req} | convertto-json)
|
|
#Process the responses and verify status
|
|
foreach ($respons in $responses.responses) {
|
|
$CurrentObject++
|
|
switch ($respons.status) {
|
|
200 {[void] $CollectedObjects.Add($respons)
|
|
Write-Verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to get object $($respons.id) from Graph batches" }
|
|
403 {write-error "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Error Access denied during Graph batches - Status: $($respons.status)"}
|
|
404 {write-error "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Error Result not found during Graph batches- Status: $($respons.status)"}
|
|
429 {[void] $RetryObjects.Add($respons)
|
|
write-warning "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Warning, Throttling occured during Graph batches- Status: $($respons.status)"}
|
|
default {[void] $RetryObjects.Add($respons)
|
|
write-error "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Error Other error occured during Graph batches - Status: $($respons.status)"}
|
|
}
|
|
}
|
|
|
|
#progressbar
|
|
$Elapsedtime = (get-date) - $starttime
|
|
$timeLeft = [TimeSpan]::FromMilliseconds((($ElapsedTime.TotalMilliseconds / $CurrentObject) * ($TotalObjects - $CurrentObject)))
|
|
if (!$ManagedIdentity){
|
|
Write-Progress -Activity "Get $($uri) $($CurrentObject) of $($TotalObjects)" `
|
|
-Status "Est Time Left: $($timeLeft.Hours) Hour, $($timeLeft.Minutes) Min, $($timeLeft.Seconds) Sek - Throttled $($retryObjects.count) - Retry $($Retrycount) of $($MaxRetry)" `
|
|
-PercentComplete $([math]::ceiling($($CurrentObject / $TotalObjects) * 100))
|
|
}
|
|
$throttledResponses = $responses.responses | Select-Object -last 20 | Where-Object {$_.status -eq "429"}
|
|
$throttledResponse = $throttledResponses |select -last 1
|
|
# | Select-Object -Property *,@{Name='HasDelay';Expression={$null -ne $_.headers."retry-after"}} | Where-Object HasDelay -eq $true
|
|
if ($throttledResponse) {
|
|
[int]$recommendedWait = ($throttledResponses.headers.'retry-after' | Measure-object -Maximum).maximum
|
|
write-warning "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Warning Throttling occured during Graph batches, Will wait the recommended $($recommendedWait+1) seconds"
|
|
Start-Sleep -Seconds ($recommendedWait + 1)
|
|
}
|
|
else{Start-Sleep -Milliseconds $WaitTime} #to avoid throttling
|
|
}
|
|
if ($RetryObjects.Count -gt 0 -and $MaxRetry -gt 0){
|
|
$Retrycount++
|
|
$MaxRetry--
|
|
write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to start rerun batches with $($RetryObjects.Count) collected a total of $($CollectedObjects.count))"
|
|
$objects = @()
|
|
$objects = $RetryObjects
|
|
}
|
|
}While ($RetryObjects.Count -gt 0 -and $MaxRetry -gt 0)
|
|
write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success returning $($CollectedObjects.count) objects from Graph batching"
|
|
foreach ($CollectedObject in $CollectedObjects) {$LookupHash[$CollectedObject.id] = $CollectedObject}
|
|
return $LookupHash
|
|
}
|
|
End {$MemoryUsage = [System.GC]::GetTotalMemory($true)
|
|
Write-Verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to cleanup Memory usage after Graph batching to: $(($MemoryUsage/1024/1024).ToString('N2')) MB"
|
|
}
|
|
}
|
|
function Set-IntunePrimaryUsers {
|
|
param (
|
|
[System.Object]$IntuneDevices,
|
|
[System.Object]$SignInLogs,
|
|
[System.Object]$AllPrimaryUsersHash,
|
|
[System.Object]$Enrollmentaccounts,
|
|
[Bool]$Testmode,
|
|
[Bool]$ReturnReport
|
|
)
|
|
Begin {
|
|
$ErrorActionPreference = 'stop'
|
|
[int]$i=0
|
|
[String]$EnrollmentaccountsFilter = ($Enrollmentaccounts|ForEach-Object{[regex]::escape($_)}) -join '|'
|
|
}
|
|
Process {
|
|
[System.Object]$report = @()
|
|
Foreach ($IntuneDevice in $IntuneDevices){
|
|
[System.Object]$SignInLogsOnDevice = $null
|
|
[System.Object]$MostFrequentUser = $null
|
|
[hashtable]$primaryuserHash = @{}
|
|
[String]$MostFrequentUserPrincipalname = $null
|
|
[String]$MostFrequentUserID = $null
|
|
[String]$primaryUser = $null
|
|
$i++
|
|
#Get current Primary User
|
|
if ($AllPrimaryUsersHash.count -gt 0){$PrimaryuserHash = $AllPrimaryUsersHash[$IntuneDevice.id]
|
|
$primaryUserJson = ($primaryuserHash.body.value | ConvertTo-Json -Depth 9 | ConvertFrom-Json)
|
|
if ($primaryUserJson -and $primaryUserJson.PSObject.Properties.Name -contains 'userprincipalname') {
|
|
$primaryuser = $primaryUserJson.userprincipalname}
|
|
write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to get Primary User $($Primaryuser) for $($IntuneDevice.DeviceName) from batch lookup"}
|
|
else {
|
|
try {$primaryUser = (Get-MgDeviceManagementManagedDeviceUser -ManagedDeviceId $IntuneDevice.ID -property "UserPrincipalName").UserPrincipalName
|
|
write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to get Primary User $($Primaryuser) for device $($IntuneDevice.DeviceName) from Graph"
|
|
}
|
|
catch{write-Warning "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Failed to get Primary User $($Primaryuser) for device $($IntuneDevice.DeviceName) from Graph with error: $_"
|
|
}
|
|
}
|
|
if (!$primaryUser){$primaryUser = "";write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success getting Primary user for device $($IntuneDevice.DeviceName) but device has no Primary User"}
|
|
|
|
# Get sign in logs for the device
|
|
if ($enrollmentaccounts.count -ge 1){$SignInLogsOnDevice = $SignInLogs | Where-Object {$_.deviceid -eq $IntuneDevice.AzureAdDeviceId -and $_.userprincipalname -notmatch $EnrollmentaccountsFilter}}
|
|
else {$SignInLogsOnDevice = $SignInLogs | Where-Object {$_.deviceid -eq $IntuneDevice.AzureAdDeviceId}}
|
|
if ($SignInLogsOnDevice){$SignInUsers = $SignInLogsOnDevice | Select-Object userprincipalname, UserId | Group-Object userprincipalname}
|
|
else{
|
|
write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Warning Device $($IntuneDevice.DeviceName) is skipped due to failing to find Sign-In logs"
|
|
if ($ReturnReport){$report += "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Warning Device $($IntuneDevice.DeviceName) is skipped due to failing to find Sign-In logs"}
|
|
continue}
|
|
$MostFrequentUser = $SignInUsers | Sort-Object count | Select-Object -Last 1
|
|
$MostFrequentUserPrincipalname = $MostFrequentUser.group[0].UserPrincipalName
|
|
$MostFrequentUserID = $MostFrequentUser.group[0].UserID
|
|
$IntuneDeviceID = $IntuneDevice.id
|
|
|
|
#Set primary User if needed
|
|
if (($MostFrequentUserPrincipalname) -and ($MostFrequentUserid) -and ($MostFrequentUserPrincipalname -ne $PrimaryUser))
|
|
{
|
|
write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to determine change needed on Device $($IntuneDevice.DeviceName) primaryuser from $($PrimaryUser) to $($MostFrequentUserPrincipalname)"
|
|
$uri = "https://graph.microsoft.com/beta/deviceManagement/managedDevices('$IntuneDeviceID')/users/`$ref"
|
|
$Body = @{ "@odata.id" = "https://graph.microsoft.com/beta/users/$MostFrequentUserid" } | ConvertTo-Json
|
|
$Method = "POST"
|
|
if (!$TestMode){
|
|
try{Invoke-MgGraphRequest -Method $Method -uri $uri -body $Body
|
|
write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to set Primary User $($MostFrequentUserPrincipalname) for device $($IntuneDevice.DeviceName)"
|
|
if ($ReturnReport){$report += "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to set Primary User $($MostFrequentUserPrincipalname) for device $($IntuneDevice.DeviceName)"}}
|
|
catch{write-Warning "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Failed to set Primary User $($MostFrequentUserPrincipalname) for device $($IntuneDevice.DeviceName) with error: $_"
|
|
if ($ReturnReport){$report += "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Failed to set Primary User $($MostFrequentUserPrincipalname) for device $($IntuneDevice.DeviceName) with error: $_"}}
|
|
}
|
|
else{write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Testmode - Will not set Primary User $($MostFrequentUserPrincipalname) for device $($IntuneDevice.DeviceName)"
|
|
if ($ReturnReport){$report += "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Testmode - Will not set Primary User $($MostFrequentUserPrincipalname) for device $($IntuneDevice.DeviceName)"}}
|
|
}
|
|
else{
|
|
if (!$MostFrequentUserPrincipalname){
|
|
write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to determine that Device $($IntuneDevice.DeviceName) has no logins in collected logs"
|
|
if ($ReturnReport){$report += "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to determine that Device $($IntuneDevice.DeviceName) has no logins in collected logs"}}
|
|
else {write-Verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to determine that Device $($IntuneDevice.DeviceName) have correct Primary User $($PrimaryUser)"
|
|
if ($ReturnReport){$report += "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to determine that Device $($IntuneDevice.DeviceName) have correct Primary User $($PrimaryUser)"}}
|
|
}
|
|
}
|
|
return $report
|
|
}
|
|
End {$MemoryUsage = [System.GC]::GetTotalMemory($true)
|
|
Write-Verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to cleanup Memory usage after set Primary Users to: $(($MemoryUsage/1024/1024).ToString('N2')) MB"
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ---------------------------------------------------[[Script Execution]------------------------------------------------------
|
|
$StartTime = Get-Date
|
|
$MgGraphAccessToken = ConnectTo-MgGraph -RequiredScopes $RequiredScopes
|
|
|
|
#Get Intune Devices
|
|
try{
|
|
$IntuneDevices = @(Get-MgDeviceManagementManagedDevice -filter "operatingSystem eq 'Windows'and LastSyncDateTime gt $($DeviceStartTime.ToString("yyyy-MM-ddTHH:mm:ssZ"))" -all -Property "AzureAdDeviceId,DeviceName,Id")
|
|
$IntuneDeviceCount = $IntuneDevices | Measure-Object | Select-Object -ExpandProperty Count
|
|
write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to get $($IntuneDeviceCount) Devices with selected properties for devices synced last $($DeviceTimeSpan) days"
|
|
}
|
|
catch{
|
|
write-Error "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Failed to get Devices with error: $_"
|
|
}
|
|
|
|
#Memory Garbage collection
|
|
$MemoryUsage = [System.GC]::GetTotalMemory($true)
|
|
Write-Verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to cleanup Memory usage after get devices to: $(($MemoryUsage/1024/1024).ToString('N2')) MB"
|
|
|
|
#Get Sign-In logs
|
|
try{
|
|
$SignInLogs = Get-MgAuditLogSignIn -Filter "appDisplayName eq 'Windows Sign In' and CreatedDateTime gt $($SignInsStartTime.ToString("yyyy-MM-ddTHH:mm:ssZ"))" -All | select devicedetail.deviceid,userprincipalname, UserId -ExpandProperty devicedetail
|
|
$SignInLogCount = $SignInLogs | Measure-Object | Select-Object -ExpandProperty Count
|
|
write-verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to get $($SignInLogCount) Sign-In logs with selected properties for last $($SigninsTimeSpan) days"
|
|
}
|
|
catch{
|
|
write-Error "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Failed to get Sign-In logs with error: $_"
|
|
}
|
|
|
|
#Memory Garbage collection
|
|
$MemoryUsage = [System.GC]::GetTotalMemory($true)
|
|
Write-Verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to cleanup Memory usage after get Sign-In logs to: $(($MemoryUsage/1024/1024).ToString('N2')) MB"
|
|
|
|
if (($IntuneDevices) -and ($SignInLogs)){
|
|
If ($RunBatchMode){ #Getting Primary Users in batch mode
|
|
try{
|
|
$AllPrimaryUsersHash = get-mggraphrequestbatch -RunProfile "beta" -method GET -Object "deviceManagement/managedDevices" -objects $IntuneDevices -uri "/users" -BatchSize $Batchsize -WaitTime $waittime -MaxRetry $MaxRetry
|
|
Write-Verbose "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Success to get Primary Users for $($AllPrimaryUsersHash.count) Devices"
|
|
}
|
|
catch{
|
|
write-Error "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),Failed to get Primary Users for Devices with error: $_"
|
|
}
|
|
$report = Set-IntunePrimaryUsers -IntuneDevices $IntuneDevices -SignInLogs $SignInLogs -AllPrimaryUsersHash $AllPrimaryUsersHash -Enrollmentaccounts $Enrollmentaccounts -TestMode $TestMode -ReturnReport $ReturnReport
|
|
}
|
|
else{ #Getting Primary Users in foreach mode
|
|
$report = Set-IntunePrimaryUsers -IntuneDevices $IntuneDevices -SignInLogs $SignInLogs -AllPrimaryUsersHash $AllPrimaryUsersHash -Enrollmentaccounts $Enrollmentaccounts -TestMode $TestMode -ReturnReport $ReturnReport
|
|
}
|
|
}
|
|
else{
|
|
write-Warning "$(Get-Date -Format 'yyyy-MM-dd'),$(Get-Date -format 'HH:mm:ss'),No Devices or Sign-In logs found, exiting script"
|
|
}
|
|
|
|
if ($ReturnReport){
|
|
write-Output -InputObject $report
|
|
}
|
|
|
|
disconnect-mggraph | out-null
|
|
[datetime]$scriptEndTime = Get-Date
|
|
$MemoryUsage = [System.GC]::GetTotalMemory($false)
|
|
write-Output "Script execution time: $(($scriptEndTime-$scriptStartTime).ToString('hh\:mm\:ss'))"
|
|
Write-Output "Memory Usage at the end of script execution: $(($MemoryUsage/1024/1024).ToString('N2')) MB"
|
|
$VerbosePreference = "SilentlyContinue"
|