#Requires -Version 5.1 <# .SYNOPSIS Sets the Active Directory computer object's "Managed By" attribute to the currently logged-in user. .DESCRIPTION Designed to run as a GPO User Logon Script. On each login, it resolves the current user and computer in AD, then stamps the user's Distinguished Name into the computer object's "managedBy" attribute. PREREQUISITES: - The RSAT ActiveDirectory PowerShell module must be installed on client machines, OR the script can fall back to ADSI/DirectorySearcher (no module needed). - AD permissions must be delegated so that Authenticated Users (or Domain Users) can WRITE the "managedBy" attribute on Computer objects in the relevant OU(s). See README.md for delegation instructions. .NOTES Deploy via: GPO > User Configuration > Policies > Windows Settings > Scripts > Logon Filename: Set-ComputerManagedBy.ps1 #> # ── Configuration ──────────────────────────────────────────────────────────── $LogFile = "$env:TEMP\Set-ComputerManagedBy.log" $MaxLogSizeKB = 256 # ── Logging helper ─────────────────────────────────────────────────────────── function Write-Log { param([string]$Message, [string]$Level = "INFO") $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $entry = "[$timestamp] [$Level] $Message" # Rotate log if oversized if ((Test-Path $LogFile) -and ((Get-Item $LogFile).Length / 1KB -gt $MaxLogSizeKB)) { Remove-Item $LogFile -Force -ErrorAction SilentlyContinue } Add-Content -Path $LogFile -Value $entry -ErrorAction SilentlyContinue } # ── Gather environment ────────────────────────────────────────────────────── $currentUser = $env:USERNAME $computerName = $env:COMPUTERNAME $userDomain = $env:USERDOMAIN Write-Log "Script started. User=$userDomain\$currentUser, Computer=$computerName" # ── Skip if local/non-domain login ────────────────────────────────────────── if ($userDomain -eq $computerName) { Write-Log "Local login detected (domain = computername). Skipping." "WARN" exit 0 } # ── Try AD module first, fall back to ADSI ────────────────────────────────── $useADModule = $false try { Import-Module ActiveDirectory -ErrorAction Stop $useADModule = $true Write-Log "Using ActiveDirectory PowerShell module." } catch { Write-Log "AD module not available. Falling back to ADSI/DirectorySearcher." "WARN" } try { if ($useADModule) { # ── AD Module path ────────────────────────────────────────────────── $userObj = Get-ADUser -Identity $currentUser -ErrorAction Stop $computerObj = Get-ADComputer -Identity $computerName -ErrorAction Stop $currentManagedBy = (Get-ADComputer -Identity $computerName -Properties managedBy).managedBy if ($currentManagedBy -eq $userObj.DistinguishedName) { Write-Log "ManagedBy already set to $currentUser. No change needed." exit 0 } Set-ADComputer -Identity $computerName -ManagedBy $userObj.DistinguishedName -ErrorAction Stop Write-Log "SUCCESS: Set ManagedBy on '$computerName' to '$($userObj.DistinguishedName)'" } else { # ── ADSI fallback (no module required) ────────────────────────────── $rootDSE = [ADSI]"LDAP://RootDSE" $domainDN = $rootDSE.defaultNamingContext $searcher = New-Object DirectoryServices.DirectorySearcher $searcher.SearchRoot = [ADSI]"LDAP://$domainDN" # Find the user DN $searcher.Filter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName=$currentUser))" $searcher.PropertiesToLoad.Add("distinguishedName") | Out-Null $userResult = $searcher.FindOne() if (-not $userResult) { Write-Log "Could not find user '$currentUser' in AD." "ERROR" exit 1 } $userDN = $userResult.Properties["distinguishedname"][0] # Find the computer DN $searcher.Filter = "(&(objectCategory=computer)(sAMAccountName=$computerName$))" $searcher.PropertiesToLoad.Clear() $searcher.PropertiesToLoad.Add("distinguishedName") | Out-Null $searcher.PropertiesToLoad.Add("managedBy") | Out-Null $computerResult = $searcher.FindOne() if (-not $computerResult) { Write-Log "Could not find computer '$computerName' in AD." "ERROR" exit 1 } $computerDN = $computerResult.Properties["distinguishedname"][0] # Check current value $currentManagedBy = $null if ($computerResult.Properties["managedby"].Count -gt 0) { $currentManagedBy = $computerResult.Properties["managedby"][0] } if ($currentManagedBy -eq $userDN) { Write-Log "ManagedBy already set to $currentUser. No change needed." exit 0 } # Set the attribute via ADSI $computerEntry = [ADSI]"LDAP://$computerDN" $computerEntry.Put("managedBy", $userDN) $computerEntry.SetInfo() Write-Log "SUCCESS: Set ManagedBy on '$computerName' to '$userDN'" } } catch { Write-Log "FAILED to set ManagedBy: $($_.Exception.Message)" "ERROR" exit 1 } exit 0