Add user Notes field stamping with computer name and login timestamp

This commit is contained in:
2026-04-21 14:59:28 +10:00
parent 7f23edc31e
commit cac43b4304
+50 -29
View File
@@ -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
}