How It Works
Domain Join Check
Queries Win32_ComputerSystem via CIM to confirm the machine is actually joined to a domain. If it’s not, the script exits early. No point pulling AD data from a workgroup machine.
Logged-On Users
Tries quser first, which catches both console and RDP sessions. If quser returns nothing, it falls back to finding explorer.exe processes and pulling their owner via GetOwner(). That covers edge cases where quser comes up empty but someone is clearly logged in.
Secure Channel, Time Source, and AD Site
Three quick checks that tell you a lot. Test-ComputerSecureChannel confirms the machine can still talk to a DC. w32tm /query /source shows where the clock is syncing from. nltest /dsgetsite returns the AD site the machine currently resolves to. These three together will surface most domain connectivity problems fast.
Network and DNS Configuration
Pulls all IP-enabled adapters from Win32_NetworkAdapterConfiguration and prints IPs, gateways, DNS servers, and DNS suffix search order. Useful for confirming whether the machine is even pointed at the right DNS servers.
Active Directory Details (RSAT Required)
Checks for the ActiveDirectory module before doing anything. If RSAT isn’t installed, it warns you and stops. If it is, it discovers a DC for the domain, then pulls domain mode, FSMO role holders, and a full list of domain controllers with their IPs, sites, and OS versions.
Usage
Running the Script
No parameters. Just dot-source it or run it directly in an elevated PowerShell session.
.Get-DomainInfo.ps1Code language: PowerShell (powershell)
Permissions
Most of the script runs fine as a standard domain user. The AD section at the bottom needs enough rights to query Active Directory, which any authenticated domain account has by default. You do not need Domain Admin.
Dependencies
The AD section requires the ActiveDirectory PowerShell module. That comes with RSAT on Windows 10/11:
Add-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0Code language: PowerShell (powershell)
On Windows Server, add it via Server Manager or:
Install-WindowsFeature RSAT-AD-PowerShellCode language: PowerShell (powershell)
The script handles a missing module gracefully. It warns you and skips that section rather than crashing.
Execution Policy
If your policy blocks unsigned scripts, either sign the script or run it like this:
powershell.exe -ExecutionPolicy Bypass -File .Get-DomainInfo.ps1Code language: PowerShell (powershell)
Caveats
quser Requires the Right Windows Feature
On some stripped-down Server Core installs or heavily customized images, quser may not be present. The script falls back to the explorer.exe method, but that only catches users with a full desktop session. Headless or service-account sessions won’t show up either way.
Test-ComputerSecureChannel Can Take Time
If the machine is off-network or the DC is slow to respond, this call can hang for a bit before returning. There’s no timeout set in the script. On a machine with a dead network path to the DC, expect a delay there.
FSMO and DC Info Hits the Domain, Not Just the Local Machine
Get-ADDomain and Get-ADDomainController -Filter * query AD directly. If the machine can’t reach a DC when you run this, those calls will fail. The script catches the error and prints it in yellow rather than stopping, so you’ll still get the output from the earlier sections.
The explorer.exe Fallback Has a Quirk
The Sort-Object -Unique in the fallback block is piped after Write-Host, so it doesn’t actually deduplicate anything. If the same user has multiple explorer.exe processes running, their name will print more than once. It’s cosmetic, but it’s there.
Run This Locally
The script uses $env:COMPUTERNAME and pulls CIM data from the local machine. It’s not built for remote execution. If you need this for multiple machines, you’d need to wrap it in Invoke-Command with a -ComputerName list, which would require a bit of reworking.
Full Script
Clear-Host
$Computer = $env:COMPUTERNAME
Write-Host "Gathering domain-related information for: $Computer" -ForegroundColor Cyan
# --- Domain join status ---
try {
$cs = Get-CimInstance -ClassName Win32_ComputerSystem -ErrorAction Stop
Write-Host ("Domain Joined: " + $(if ($cs.PartOfDomain) { 'Yes' } else { 'No' }))
} catch {
Write-Host "Could not query Win32_ComputerSystem: $_" -ForegroundColor Red
return
}
if (-not $cs.PartOfDomain) {
Write-Host "The computer is not joined to any domain."
return
}
Write-Host "Domain Name: $($cs.Domain)"
# --- Logged-on users (fixes the "no current user" gap) ---
Write-Host "`nLogged-On Users:"
try {
# quser is the most reliable for interactive + RDP sessions
$quserOutput = quser 2>$null
if ($quserOutput) {
$quserOutput | ForEach-Object { Write-Host " $_" }
} else {
# Fallback: explorer.exe owners = users with an interactive session
Get-CimInstance Win32_Process -Filter "Name='explorer.exe'" |
ForEach-Object {
$owner = Invoke-CimMethod -InputObject $_ -MethodName GetOwner
Write-Host " $($owner.Domain)$($owner.User)"
} | Sort-Object -Unique
}
} catch {
Write-Host " Could not enumerate sessions: $_" -ForegroundColor Yellow
}
# Console user (may be empty if no one is at the physical console)
if ($cs.UserName) {
Write-Host "Console User: $($cs.UserName)"
}
# --- Secure channel + time sync (cheap, high-signal) ---
$secureChannel = try {
Test-ComputerSecureChannel -ErrorAction Stop
} catch {
"Unreachable ($($_.host1.example.com([Environment]::NewLine)[0]))"
}
Write-Host "`nSecure Channel: $secureChannel"
$timeSource = try { (& w32tm /query /source 2>&1 | Out-String).Trim() } catch { "n/a" }
Write-Host "Time Source: $timeSource"
$adSite = try {
$siteOut = & nltest /dsgetsite 2>&1
if ($LASTEXITCODE -eq 0) { ($siteOut | Select-Object -First 1).Trim() } else { "Unknown (DC unreachable)" }
} catch { "n/a" }
Write-Host "Current AD Site: $adSite"
# --- Network / DNS ---
Write-Host "`nNetwork Configuration:"
Get-CimInstance Win32_NetworkAdapterConfiguration -Filter "IPEnabled=TRUE" |
ForEach-Object {
Write-Host " Interface: $($_.Description)"
Write-Host " IP: $($_.IPAddress -join ', ')"
Write-Host " Gateway: $($_.DefaultIPGateway -join ', ')"
Write-Host " DNS Servers: $($_.DNSServerSearchOrder -join ', ')"
Write-Host " DNS Suffixes: $($_.DNSDomainSuffixSearchOrder -join ', ')"
}
# --- AD info (requires RSAT / ActiveDirectory module) ---
if (-not (Get-Module -ListAvailable ActiveDirectory)) {
Write-Host "`nActiveDirectory module not installed — skipping AD details. Install RSAT to enable." -ForegroundColor Yellow
return
}
Import-Module ActiveDirectory -ErrorAction SilentlyContinue
try {
$dc = Get-ADDomainController -DomainName $cs.Domain -Discover -ErrorAction Stop
Write-Host "`nDiscovered DC: $($dc.HostName) (Site: $($dc.Site))"
$domainInfo = Get-ADDomain -Identity $cs.Domain
Write-Host "`nAD Domain Information:"
Write-Host " Forest: $($domainInfo.Forest)"
Write-Host " Domain Mode: $($domainInfo.DomainMode)"
Write-Host " PDC Emulator: $($domainInfo.PDCEmulator)"
Write-Host " Infrastructure Master: $($domainInfo.InfrastructureMaster)"
Write-Host " RID Master: $($domainInfo.RIDMaster)"
Write-Host "`nDomain Controllers:"
Get-ADDomainController -Filter * |
Select-Object Name, IPv4Address, Site, OperatingSystem |
Format-Table -AutoSize
} catch {
Write-Host "AD query failed: $_" -ForegroundColor Yellow
}Code language: PowerShell (powershell)
Sample Output:
Gathering domain-related information for: OPTIMUS
Domain Joined: Yes
Domain Name: frankrobinson.com
Logged-On Users:
USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME
>administrator rdp-tcp#20 2 Active . 3/16/2026 9:56 AM
Secure Channel: Unreachable (Cannot verify the secure channel for the local computer. Operation failed with the following exception: The specifi
ed domain either does not exist or could not be contacted.)
Time Source: Free-running System Clock
Current AD Site: Default-First-Site-Name
Network Configuration:
Interface: Hyper-V Virtual Ethernet Adapter
IP: 192.168.4.2, fe80::3cc8:d6c7:2378:9b9b, fd08:acce:16ab:1:7e53:9494:fc8f:5554
Gateway: 192.168.4.1
DNS Servers: 192.168.4.2, 1.1.1.2, 192.168.4.136
DNS Suffixes: frankrobinson.com
Interface: Hyper-V Virtual Ethernet Adapter #2
IP: 172.18.160.1, fe80::dd3b:56b:8fde:7c62
Gateway:
DNS Servers:
DNS Suffixes: frankrobinson.com
Discovered DC: Optimus.frankrobinson.com (Site: Default-First-Site-Name)
AD Domain Information:
Forest: frankrobinson.com
Domain Mode: Windows2016Domain
PDC Emulator: Optimus.frankrobinson.com
Infrastructure Master: Optimus.frankrobinson.com
RID Master: Optimus.frankrobinson.com
Domain Controllers:
Name IPv4Address Site OperatingSystem
---- ----------- ---- ---------------
OPTIMUS 192.168.4.2 Default-First-Site-Name Windows Server 2019 Standard
EMBY 192.168.4.3 Default-First-Site-Name Windows Server 2019 Standard