Public/ntp/Get-NTPConfiguration.ps1
|
#Requires -Version 5.1 function Get-NTPConfiguration { <# .SYNOPSIS Retrieves the current Windows Time Service (W32Time) NTP configuration and status .DESCRIPTION This function queries the Windows Time Service using w32tm commands to retrieve the complete NTP configuration, including configured servers, poll intervals, synchronization status, peer details, and last successful sync time. Returns a structured PSCustomObject with all relevant NTP configuration data for easy consumption by other scripts or for display purposes. .PARAMETER IncludePeerDetails When specified, includes detailed peer information in the output object. This adds verbose information about each configured NTP peer. .EXAMPLE Get-NTPConfiguration Retrieves the current NTP configuration and displays it as a structured object. .EXAMPLE Get-NTPConfiguration -Verbose | Format-List Retrieves NTP configuration with verbose logging and displays all properties as a list. .EXAMPLE $ntpConfig = Get-NTPConfiguration -IncludePeerDetails $ntpConfig.ConfiguredServers $ntpConfig.Peers Retrieves configuration with peer details and accesses specific properties. .NOTES Author: Ecritel IT Team Version: 1.0.0 Last Modified: 2026-02-20 Requires: PowerShell 5.1+, Windows Time Service (w32time) Permissions: Standard user rights (no elevation required for read-only operations) #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter(Mandatory = $false)] [switch]$IncludePeerDetails ) begin { Write-Verbose "[$($MyInvocation.MyCommand)] Starting - PowerShell $($PSVersionTable.PSVersion)" $ErrorActionPreference = 'Stop' } process { try { # Verify W32Time service exists Write-Verbose "[$($MyInvocation.MyCommand)] Checking Windows Time Service..." $service = Get-Service -Name 'w32time' -ErrorAction Stop Write-Verbose "[$($MyInvocation.MyCommand)] Service status: $($service.Status)" # Query configuration Write-Verbose "[$($MyInvocation.MyCommand)] Querying w32tm configuration..." $configOutput = w32tm /query /configuration 2>&1 # Query status Write-Verbose "[$($MyInvocation.MyCommand)] Querying w32tm status..." $statusOutput = w32tm /query /status /verbose 2>&1 # Query peers Write-Verbose "[$($MyInvocation.MyCommand)] Querying w32tm peers..." $peersOutput = w32tm /query /peers 2>&1 # Parse configuration $ntpServerLine = $configOutput | Select-String -Pattern 'NtpServer:\s*(.+)\s*\(.*\)' | Select-Object -First 1 $configuredServers = if ($ntpServerLine) { ($ntpServerLine.Matches.Groups[1].Value -split '\s+') | Where-Object { $_ -ne '' } } else { @() } $typeMatch = $configOutput | Select-String -Pattern 'Type:\s*(.+)' | Select-Object -First 1 $syncType = if ($typeMatch) { $typeMatch.Matches.Groups[1].Value.Trim() } else { 'Unknown' } # Parse registry values from configuration output $specialPollMatch = $configOutput | Select-String -Pattern 'SpecialPollInterval:\s*(\d+)' | Select-Object -First 1 $specialPollInterval = if ($specialPollMatch) { [int]$specialPollMatch.Matches.Groups[1].Value } else { $null } $minPollMatch = $configOutput | Select-String -Pattern 'MinPollInterval:\s*(\d+)' | Select-Object -First 1 $minPollInterval = if ($minPollMatch) { [int]$minPollMatch.Matches.Groups[1].Value } else { $null } $maxPollMatch = $configOutput | Select-String -Pattern 'MaxPollInterval:\s*(\d+)' | Select-Object -First 1 $maxPollInterval = if ($maxPollMatch) { [int]$maxPollMatch.Matches.Groups[1].Value } else { $null } # Parse status $sourceMatch = $statusOutput | Select-String -Pattern 'Source:\s*(.+)' | Select-Object -First 1 $currentSource = if ($sourceMatch) { $sourceMatch.Matches.Groups[1].Value.Trim() } else { 'Unknown' } $lastSyncMatch = $statusOutput | Select-String -Pattern 'Last Successful Sync Time:\s*(.+)' | Select-Object -First 1 $lastSyncTime = if ($lastSyncMatch) { $lastSyncMatch.Matches.Groups[1].Value.Trim() } else { 'Never' } $stratumMatch = $statusOutput | Select-String -Pattern 'Stratum:\s*(\d+)' | Select-Object -First 1 $stratum = if ($stratumMatch) { [int]$stratumMatch.Matches.Groups[1].Value } else { $null } # Parse leap indicator $leapMatch = $statusOutput | Select-String -Pattern 'Leap Indicator:\s*(.+)' | Select-Object -First 1 $leapIndicator = if ($leapMatch) { $leapMatch.Matches.Groups[1].Value.Trim() } else { 'Unknown' } # Build result object $result = [PSCustomObject]@{ ServiceName = 'w32time' ServiceStatus = $service.Status SyncType = $syncType ConfiguredServers = $configuredServers CurrentSource = $currentSource LastSuccessfulSync = $lastSyncTime Stratum = $stratum LeapIndicator = $leapIndicator SpecialPollInterval = $specialPollInterval MinPollInterval = $minPollInterval MaxPollInterval = $maxPollInterval MinPollIntervalSec = if ($minPollInterval) { [math]::Pow(2, $minPollInterval) } else { $null } MaxPollIntervalSec = if ($maxPollInterval) { [math]::Pow(2, $maxPollInterval) } else { $null } QueryTimestamp = Get-Date -Format 'o' } # Add peer details if requested if ($IncludePeerDetails) { Write-Verbose "[$($MyInvocation.MyCommand)] Including peer details in output" $result | Add-Member -MemberType NoteProperty -Name 'PeerDetails' -Value ($peersOutput -join "`n") } Write-Verbose "[$($MyInvocation.MyCommand)] Configuration retrieved successfully" return $result } catch [Microsoft.PowerShell.Commands.ServiceCommandException] { Write-Error "[$($MyInvocation.MyCommand)] Windows Time Service not found or inaccessible: $_" throw } catch { Write-Error "[$($MyInvocation.MyCommand)] Failed to retrieve NTP configuration: $_" throw } } end { Write-Verbose "[$($MyInvocation.MyCommand)] Completed" } } |