diff --git a/Set-ComputerManagedBy.ps1 b/Set-ComputerManagedBy.ps1 index a7f9323..9623285 100644 --- a/Set-ComputerManagedBy.ps1 +++ b/Set-ComputerManagedBy.ps1 @@ -1,19 +1,20 @@ #Requires -Version 5.1 <# .SYNOPSIS - Sets the Active Directory computer object's "Managed By" attribute to the currently logged-in user. + Sets the AD computer's "Managed By" to the logged-in user, and stamps the + computer name into the user's "Notes" field. .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. + Designed to run as a GPO User Logon Script. On each login it: + 1. Sets the computer object's "managedBy" attribute to the user's DN + 2. Sets the user object's "info" attribute (Notes / Telephones tab) to the computer name 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. + - Users can write their own "info" attribute by default (Personal Information + property set). No extra delegation needed for the Notes field. + - RSAT AD module is optional; the script falls back to ADSI if unavailable. .NOTES Deploy via: GPO > User Configuration > Policies > Windows Settings > Scripts > Logon @@ -29,7 +30,6 @@ 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 } @@ -40,6 +40,7 @@ function Write-Log { $currentUser = $env:USERNAME $computerName = $env:COMPUTERNAME $userDomain = $env:USERDOMAIN +$loginTimestamp = Get-Date -Format "yyyy-MM-dd HH:mm" Write-Log "Script started. User=$userDomain\$currentUser, Computer=$computerName" @@ -59,21 +60,30 @@ try { Write-Log "AD module not available. Falling back to ADSI/DirectorySearcher." "WARN" } +# ── Helper: build the notes string ────────────────────────────────────────── +$notesValue = "Last logon: $computerName ($loginTimestamp)" + try { if ($useADModule) { # ── AD Module path ────────────────────────────────────────────────── - $userObj = Get-ADUser -Identity $currentUser -ErrorAction Stop - $computerObj = Get-ADComputer -Identity $computerName -ErrorAction Stop + $userObj = Get-ADUser -Identity $currentUser -Properties info -ErrorAction Stop + $computerObj = Get-ADComputer -Identity $computerName -Properties managedBy -ErrorAction Stop - $currentManagedBy = (Get-ADComputer -Identity $computerName -Properties managedBy).managedBy - - if ($currentManagedBy -eq $userObj.DistinguishedName) { + # — Set computer ManagedBy —— + if ($computerObj.managedBy -eq $userObj.DistinguishedName) { Write-Log "ManagedBy already set to $currentUser. No change needed." - exit 0 + } else { + Set-ADComputer -Identity $computerName -ManagedBy $userObj.DistinguishedName -ErrorAction Stop + Write-Log "SUCCESS: Set ManagedBy on '$computerName' to '$($userObj.DistinguishedName)'" } - Set-ADComputer -Identity $computerName -ManagedBy $userObj.DistinguishedName -ErrorAction Stop - Write-Log "SUCCESS: Set ManagedBy on '$computerName' to '$($userObj.DistinguishedName)'" + # — Set user Notes (info attribute) —— + if ($userObj.info -eq $notesValue) { + Write-Log "User notes already current. No change needed." + } else { + Set-ADUser -Identity $currentUser -Replace @{info = $notesValue} -ErrorAction Stop + Write-Log "SUCCESS: Set Notes on '$currentUser' to '$notesValue'" + } } else { # ── ADSI fallback (no module required) ────────────────────────────── @@ -83,9 +93,9 @@ try { $searcher = New-Object DirectoryServices.DirectorySearcher $searcher.SearchRoot = [ADSI]"LDAP://$domainDN" - # Find the user DN + # Find the user $searcher.Filter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName=$currentUser))" - $searcher.PropertiesToLoad.Add("distinguishedName") | Out-Null + $searcher.PropertiesToLoad.AddRange(@("distinguishedName", "info")) $userResult = $searcher.FindOne() if (-not $userResult) { @@ -94,11 +104,10 @@ try { } $userDN = $userResult.Properties["distinguishedname"][0] - # Find the computer DN + # Find the computer $searcher.Filter = "(&(objectCategory=computer)(sAMAccountName=$computerName$))" $searcher.PropertiesToLoad.Clear() - $searcher.PropertiesToLoad.Add("distinguishedName") | Out-Null - $searcher.PropertiesToLoad.Add("managedBy") | Out-Null + $searcher.PropertiesToLoad.AddRange(@("distinguishedName", "managedBy")) $computerResult = $searcher.FindOne() if (-not $computerResult) { @@ -108,7 +117,7 @@ try { $computerDN = $computerResult.Properties["distinguishedname"][0] - # Check current value + # — Set computer ManagedBy —— $currentManagedBy = $null if ($computerResult.Properties["managedby"].Count -gt 0) { $currentManagedBy = $computerResult.Properties["managedby"][0] @@ -116,18 +125,30 @@ try { if ($currentManagedBy -eq $userDN) { Write-Log "ManagedBy already set to $currentUser. No change needed." - exit 0 + } else { + $computerEntry = [ADSI]"LDAP://$computerDN" + $computerEntry.Put("managedBy", $userDN) + $computerEntry.SetInfo() + Write-Log "SUCCESS: Set ManagedBy on '$computerName' to '$userDN'" } - # Set the attribute via ADSI - $computerEntry = [ADSI]"LDAP://$computerDN" - $computerEntry.Put("managedBy", $userDN) - $computerEntry.SetInfo() + # — Set user Notes (info attribute) —— + $currentNotes = $null + if ($userResult.Properties["info"].Count -gt 0) { + $currentNotes = $userResult.Properties["info"][0] + } - Write-Log "SUCCESS: Set ManagedBy on '$computerName' to '$userDN'" + if ($currentNotes -eq $notesValue) { + Write-Log "User notes already current. No change needed." + } else { + $userEntry = [ADSI]"LDAP://$userDN" + $userEntry.Put("info", $notesValue) + $userEntry.SetInfo() + Write-Log "SUCCESS: Set Notes on '$currentUser' to '$notesValue'" + } } } catch { - Write-Log "FAILED to set ManagedBy: $($_.Exception.Message)" "ERROR" + Write-Log "FAILED: $($_.Exception.Message)" "ERROR" exit 1 }