PowerShell Script: Pull Domain Info from Any Domain-Joined PC

This script collects a snapshot of everything domain-related on the local machine: join status, logged-on users, secure channel health, time sync source, AD site, network config, and key AD domain details. Run it when you're troubleshooting a domain issue and want all the relevant facts in one shot instead of running eight separate commands.

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