#Requires -Version 5.1 [CmdletBinding()] param( [string]$MonitoringRoot = 'C:\ProgramData\SGU\Monitoring', [string]$ComputerOuDn = 'OU=Laboratorio,DC=lci,DC=lasalle,DC=mx', [ValidateRange(30, 730)] [int]$RetentionDays = 183, [string]$BrokerEventLogName = 'SGU Auth Broker', [switch]$InventoryOnly ) $ErrorActionPreference = 'Stop' Import-Module ActiveDirectory -ErrorAction Stop foreach ($serviceName in 'EventLog','Wecsvc') { Set-Service -Name $serviceName -StartupType Automatic if ((Get-Service $serviceName).Status -ne 'Running') { Start-Service $serviceName } } $archiveRoot = Join-Path $MonitoringRoot 'Archive' $brokerArchiveRoot = Join-Path $archiveRoot 'Broker' $reportRoot = Join-Path $MonitoringRoot 'Reports' New-Item -ItemType Directory -Path $archiveRoot,$brokerArchiveRoot,$reportRoot -Force | Out-Null function Test-TcpEndpoint { param( [Parameter(Mandatory)][string]$ComputerName, [int]$Port = 5985, [int]$TimeoutMilliseconds = 900 ) $client = [Net.Sockets.TcpClient]::new() try { $pending = $client.BeginConnect($ComputerName, $Port, $null, $null) if (-not $pending.AsyncWaitHandle.WaitOne($TimeoutMilliseconds)) { return $false } $client.EndConnect($pending) return $true } catch { return $false } finally { $client.Dispose() } } if (-not $InventoryOnly) { $forwardedLog = Get-WinEvent -ListLog ForwardedEvents -ErrorAction Stop if ($forwardedLog.RecordCount -gt 0) { $archivePath = Join-Path $archiveRoot ("ForwardedEvents-{0:yyyyMMdd-HHmmss}.evtx" -f (Get-Date)) & wevtutil.exe clear-log ForwardedEvents "/backup:$archivePath" if ($LASTEXITCODE -ne 0) { throw "Could not archive ForwardedEvents; wevtutil returned exit code $LASTEXITCODE." } } $brokerLog = Get-WinEvent -ListLog $BrokerEventLogName -ErrorAction SilentlyContinue if ($brokerLog -and $brokerLog.RecordCount -gt 0) { $brokerArchivePath = Join-Path $brokerArchiveRoot ("SguAuthBroker-{0:yyyyMMdd-HHmmss}.evtx" -f (Get-Date)) & wevtutil.exe clear-log $BrokerEventLogName "/backup:$brokerArchivePath" if ($LASTEXITCODE -ne 0) { throw "Could not archive $BrokerEventLogName; wevtutil returned exit code $LASTEXITCODE." } } $cutoff = (Get-Date).AddDays(-$RetentionDays) Get-ChildItem -LiteralPath $archiveRoot -Filter '*.evtx' -File -Recurse -ErrorAction SilentlyContinue | Where-Object LastWriteTime -lt $cutoff | ForEach-Object { Remove-Item -LiteralPath $_.FullName -Force } } $computers = @(Get-ADComputer -SearchBase $ComputerOuDn -SearchScope Subtree -Filter * ` -Properties DNSHostName,IPv4Address,OperatingSystem,LastLogonDate,Enabled | Sort-Object Name) $inventory = @(foreach ($computer in $computers) { $target = if ($computer.DNSHostName) { $computer.DNSHostName } else { $computer.Name } $online = Test-TcpEndpoint -ComputerName $target [pscustomobject]@{ ComputerName = $computer.Name DNSHostName = $computer.DNSHostName IPv4Address = $computer.IPv4Address OperatingSystem = $computer.OperatingSystem Enabled = [bool]$computer.Enabled Status = if ($online) { 'Encendida' } else { 'Apagada o inaccesible' } WinRMReachable = [bool]$online LastDomainLogon = if ($computer.LastLogonDate) { $computer.LastLogonDate.ToUniversalTime().ToString('o') } else { $null } CheckedAt = (Get-Date).ToUniversalTime().ToString('o') } }) $jsonPath = Join-Path $reportRoot 'machine-status.json' $csvPath = Join-Path $reportRoot 'machine-status.csv' [IO.File]::WriteAllText($jsonPath, (ConvertTo-Json -InputObject $inventory -Depth 4), [Text.UTF8Encoding]::new($false)) $inventory | Export-Csv -LiteralPath $csvPath -NoTypeInformation -Encoding UTF8 [pscustomobject]@{ CheckedAt = (Get-Date).ToUniversalTime().ToString('o') ComputerCount = @($inventory).Count OnlineCount = @($inventory | Where-Object WinRMReachable).Count OfflineCount = @($inventory | Where-Object { -not $_.WinRMReachable }).Count RetentionDays = $RetentionDays StatusJson = $jsonPath StatusCsv = $csvPath }