This script I use to update employee job titles and managers. It runs monthly for us to sync employee changes in their job titles and managers. This detects if you try and add a manger that is 'below' the user's current status. Meaning you can add yourself as a manger to yourself. Nor could you add an employee that was your subordinate as a manger to yourself.
Create a file called UserUpdates.csv and put in the comma delimited data.
UserPrincipalName,ManagerUPN,JobTitle,Department,OfficeLocation user1@company.com,manager1@company.com,Systems Administrator,IT,NYCuser2@company.com,manager2@company.com,Network Supervisor,ITOP,FLA
Create a new file called UpdateUser.ps1
Change the path in the script to reflect the path your csv file is located
$csvPath = "C:\updates\UserUpdates.csv"
run the script in powershell (as admin) .\UpdateUser.ps1
the script will prompt you for a user with rights to make the changes, usually some administrator of the tenant. Then it will run the script a line at a time.
At time of writing, the prompt that worked for me would look like this style below: And I would select my admin user that had creds. I found that sometimes it would give me a different looking one, and i would have to run the script again, because it would ask for creds every single time it ran a new line in the csv.
# ###########################
# Cobbled together with CoPilot and ChatGTP
# Update the following items via a CSV
# - Manager Job Title Department Office Location
#
# Added circular hierarchy validation
# Uses Microsoft Graph PowerShell SDK
# #############################
# Install module if needed:
# Install-Module Microsoft.Graph -Scope CurrentUser
Import-Module Microsoft.Graph.Users
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "User.ReadWrite.All","Directory.ReadWrite.All"
# UserPrincipalName,ManagerUPN,JobTitle,Department,OfficeLocation
# user1@company.com,manager@company.com,Systems Administrator,IT,NYC
$csvPath = "C:\updates\UserUpdates.csv"
# Import CSV
$users = Import-Csv -Path $csvPath
# ###########################
# Function: Detect/Prevent Circular Management Structure
# ###########################
function Test-ManagerCircularReference {
param (
[string]$UserId,
[string]$ManagerId
)
# Prevent self-manager assignment
if ($UserId -eq $ManagerId) {
return $true
}
$currentManagerId = $ManagerId
while ($currentManagerId) {
# Detect circular hierarchy
if ($currentManagerId -eq $UserId) {
return $true
}
try {
$manager = Get-MgUserManager `
-UserId $currentManagerId `
-ErrorAction Stop
if ($manager.Id) {
$currentManagerId = $manager.Id
}
else {
$currentManagerId = $null
}
}
catch {
$currentManagerId = $null
}
}
return $false
}
# ###########################
# Process the CSV file
# ###########################
foreach ($entry in $users) {
$userUPN = $entry.UserPrincipalName.Trim()
$managerUPN = $entry.ManagerUPN.Trim()
$jobTitle = $entry.JobTitle.Trim()
$department = $entry.Department.Trim()
$officeLocation = $entry.OfficeLocation.Trim()
Write-Host ""
Write-Host "Processing: $userUPN" -ForegroundColor Cyan
try {
# ###########################
# Get User
# ###########################
$user = Get-MgUser `
-UserId $userUPN `
-ErrorAction Stop
# ###########################
# Update User Properties
# ###########################
Update-MgUser `
-UserId $user.Id `
-JobTitle $jobTitle `
-Department $department `
-OfficeLocation $officeLocation
Write-Host "SUCCESS: Updated user profile properties." `
-ForegroundColor Green
# ###########################
# Update Manager (if provided)
# ###########################
if (![string]::IsNullOrWhiteSpace($managerUPN)) {
$manager = Get-MgUser `
-UserId $managerUPN `
-ErrorAction Stop
# Validate hierarchy
$hasCircularReference = Test-ManagerCircularReference `
-UserId $user.Id `
-ManagerId $manager.Id
if ($hasCircularReference) {
Write-Host "SKIPPED: Circular hierarchy detected." `
-ForegroundColor Yellow
}
else {
Set-MgUserManagerByRef `
-UserId $user.Id `
-BodyParameter @{
"@odata.id" = "https://graph.microsoft.com/v1.0/users/$($manager.Id)"
}
Write-Host "SUCCESS: Updated manager." `
-ForegroundColor Green
}
}
else {
Write-Host "INFO: No manager specified." `
-ForegroundColor DarkYellow
}
}
catch {
Write-Host "FAILED: $($_.Exception.Message)" `
-ForegroundColor Red
}
}
# Disconnect Graph Session
Disconnect-MgGraph
Write-Host ""
Write-Host "Processing complete." -ForegroundColor Cyan
No comments:
Post a Comment
Feel free to leave a comment! If you have any information that you think should be included, please do so here and I'll get it added in.