Major feature enhancement: Windows PowerShell network scanning integration
- Added Windows PowerShell network scanner with auto-detection and interactive mode - Implemented dual scanning system (Windows + Linux fallback) - Added computer management features (rename, delete, duplicate checking) - Enhanced UI with modern responsive design and Romanian localization - Added comprehensive Windows-Linux integration with WSL interop - Improved error handling and user feedback throughout - Added hot reload for development and comprehensive documentation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
182
scripts/run-scan.ps1
Normal file
182
scripts/run-scan.ps1
Normal file
@@ -0,0 +1,182 @@
|
||||
# Quick launcher for Windows network scan
|
||||
# Usage: .\run-scan.ps1 [-Network "192.168.1.0/24"] [-BatchSize 5] [-Fast] [-Verbose]
|
||||
# Or run without parameters for interactive menu
|
||||
|
||||
param(
|
||||
[string]$Network = "",
|
||||
[int]$BatchSize = 0,
|
||||
[switch]$Verbose,
|
||||
[switch]$Fast
|
||||
)
|
||||
|
||||
function Show-ScanOptionsMenu {
|
||||
Write-Host "`nWOL Manager - Optiuni de Scanare" -ForegroundColor Yellow
|
||||
Write-Host "=================================" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
# Scan mode selection
|
||||
Write-Host "Selecteaza modul de scanare:" -ForegroundColor White
|
||||
Write-Host " 1. Scan rapid (20 paralele, 500ms timeout)" -ForegroundColor Yellow
|
||||
Write-Host " 2. Scan standard (20 paralele, 1000ms timeout)" -ForegroundColor Cyan
|
||||
Write-Host " 3. Scan conservativ (10 paralele, 1500ms timeout)" -ForegroundColor Green
|
||||
Write-Host " 4. Configurare personalizata" -ForegroundColor Magenta
|
||||
Write-Host ""
|
||||
Write-Host " 0. Anuleaza" -ForegroundColor Red
|
||||
Write-Host ""
|
||||
|
||||
do {
|
||||
$scanChoice = Read-Host "Selecteaza optiunea (0-4)"
|
||||
|
||||
try {
|
||||
$scanChoiceNum = [int]$scanChoice
|
||||
} catch {
|
||||
Write-Host "Te rog introdu un numar valid!" -ForegroundColor Red
|
||||
continue
|
||||
}
|
||||
|
||||
if ($scanChoiceNum -eq 0) {
|
||||
Write-Host "Scanare anulata." -ForegroundColor Yellow
|
||||
exit 0
|
||||
}
|
||||
elseif ($scanChoiceNum -ge 1 -and $scanChoiceNum -le 4) {
|
||||
break
|
||||
} else {
|
||||
Write-Host "Optiune invalida! Selecteaza intre 0 si 4." -ForegroundColor Red
|
||||
}
|
||||
} while ($true)
|
||||
|
||||
# Set scan parameters based on choice
|
||||
$scanParams = @{}
|
||||
|
||||
switch ($scanChoiceNum) {
|
||||
1 {
|
||||
$scanParams.BatchSize = 20
|
||||
$scanParams.TimeoutMs = 500
|
||||
$scanParams.Description = "Rapid"
|
||||
}
|
||||
2 {
|
||||
$scanParams.BatchSize = 20
|
||||
$scanParams.TimeoutMs = 1000
|
||||
$scanParams.Description = "Standard"
|
||||
}
|
||||
3 {
|
||||
$scanParams.BatchSize = 10
|
||||
$scanParams.TimeoutMs = 1500
|
||||
$scanParams.Description = "Conservativ"
|
||||
}
|
||||
4 {
|
||||
Write-Host "`nConfigurare personalizata:" -ForegroundColor Magenta
|
||||
do {
|
||||
$customBatch = Read-Host "Numar de procese paralele (1-50, recomandat: 3-10)"
|
||||
try {
|
||||
$batchNum = [int]$customBatch
|
||||
if ($batchNum -ge 1 -and $batchNum -le 50) {
|
||||
$scanParams.BatchSize = $batchNum
|
||||
break
|
||||
} else {
|
||||
Write-Host "Valoare intre 1 si 50!" -ForegroundColor Red
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Te rog introdu un numar valid!" -ForegroundColor Red
|
||||
}
|
||||
} while ($true)
|
||||
|
||||
do {
|
||||
$customTimeout = Read-Host "Timeout per ping in ms (100-5000, recomandat: 500-2000)"
|
||||
try {
|
||||
$timeoutNum = [int]$customTimeout
|
||||
if ($timeoutNum -ge 100 -and $timeoutNum -le 5000) {
|
||||
$scanParams.TimeoutMs = $timeoutNum
|
||||
break
|
||||
} else {
|
||||
Write-Host "Valoare intre 100 si 5000!" -ForegroundColor Red
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Te rog introdu un numar valid!" -ForegroundColor Red
|
||||
}
|
||||
} while ($true)
|
||||
|
||||
$scanParams.Description = "Personalizat"
|
||||
}
|
||||
}
|
||||
|
||||
# Ask for verbose mode
|
||||
Write-Host ""
|
||||
$verboseChoice = Read-Host "Afiseaza progres detaliat? (y/n, default: n)"
|
||||
$scanParams.Verbose = ($verboseChoice -eq "y" -or $verboseChoice -eq "Y")
|
||||
|
||||
return $scanParams
|
||||
}
|
||||
|
||||
$scriptPath = Join-Path $PSScriptRoot "windows-network-scan.ps1"
|
||||
$outputPath = Join-Path (Split-Path $PSScriptRoot -Parent) "data\network-scan-results.json"
|
||||
|
||||
Write-Host "WOL Manager - Windows Network Scanner" -ForegroundColor Yellow
|
||||
Write-Host "=====================================" -ForegroundColor Yellow
|
||||
|
||||
if (-not (Test-Path $scriptPath)) {
|
||||
Write-Error "Scanner script not found: $scriptPath"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Determine if we should show interactive menu
|
||||
$hasParams = $PSBoundParameters.Count -gt 0 -or $Network -or $BatchSize -gt 0 -or $Verbose -or $Fast
|
||||
|
||||
if (-not $hasParams) {
|
||||
# Show interactive menu
|
||||
$menuParams = Show-ScanOptionsMenu
|
||||
$BatchSize = $menuParams.BatchSize
|
||||
$TimeoutMs = $menuParams.TimeoutMs
|
||||
$Verbose = $menuParams.Verbose
|
||||
$scanMode = $menuParams.Description
|
||||
Write-Host "`nMod selectat: $scanMode ($BatchSize paralele, $($TimeoutMs)ms timeout)" -ForegroundColor Green
|
||||
}
|
||||
|
||||
# Set up scan parameters
|
||||
$params = @{
|
||||
OutputPath = $outputPath
|
||||
}
|
||||
|
||||
# Handle command line parameters vs interactive menu
|
||||
if ($hasParams) {
|
||||
# Command line mode
|
||||
if ($Fast) {
|
||||
$params.TimeoutMs = 200
|
||||
$params.BatchSize = 20
|
||||
Write-Host "Fast scan mode enabled (200ms timeout, 20 parallel)" -ForegroundColor Yellow
|
||||
} else {
|
||||
$params.TimeoutMs = 1000
|
||||
$params.BatchSize = if ($BatchSize -gt 0) { $BatchSize } else { 5 }
|
||||
Write-Host "Standard scan mode ($($params.BatchSize) parallel, $($params.TimeoutMs)ms timeout)" -ForegroundColor Green
|
||||
}
|
||||
|
||||
if ($Verbose) {
|
||||
$params.Verbose = $true
|
||||
}
|
||||
} else {
|
||||
# Interactive menu mode - parameters already set above
|
||||
$params.BatchSize = $BatchSize
|
||||
$params.TimeoutMs = $TimeoutMs
|
||||
|
||||
if ($Verbose) {
|
||||
$params.Verbose = $true
|
||||
}
|
||||
}
|
||||
|
||||
if ($Network) {
|
||||
$params.Network = $Network
|
||||
Write-Host "Scanning network: $Network" -ForegroundColor Cyan
|
||||
} else {
|
||||
Write-Host "Network will be selected interactively" -ForegroundColor Cyan
|
||||
}
|
||||
|
||||
try {
|
||||
& $scriptPath @params
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "`nScan completed successfully!" -ForegroundColor Green
|
||||
Write-Host "Results saved to: $outputPath" -ForegroundColor Green
|
||||
}
|
||||
} catch {
|
||||
Write-Error "Failed to run network scan: $_"
|
||||
exit 1
|
||||
}
|
||||
403
scripts/windows-network-scan.ps1
Normal file
403
scripts/windows-network-scan.ps1
Normal file
@@ -0,0 +1,403 @@
|
||||
# Windows Network Scanner for WOL Manager
|
||||
# This script scans the local network for devices and extracts their MAC addresses
|
||||
# Results are saved to a JSON file that can be read by the Docker container
|
||||
|
||||
param(
|
||||
[string]$Network = "",
|
||||
[string]$OutputPath = ".\data\network-scan-results.json",
|
||||
[int]$TimeoutMs = 1000,
|
||||
[int]$BatchSize = 10,
|
||||
[switch]$Verbose
|
||||
)
|
||||
|
||||
function Write-Log {
|
||||
param([string]$Message)
|
||||
if ($Verbose) {
|
||||
Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $Message" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
|
||||
function Get-LocalNetworks {
|
||||
Write-Log "Detecting local networks..."
|
||||
$networks = @()
|
||||
|
||||
# Get all network adapters that are up and have an IP address
|
||||
$adapters = Get-NetIPAddress -AddressFamily IPv4 | Where-Object {
|
||||
$_.IPAddress -ne "127.0.0.1" -and ($_.PrefixOrigin -eq "Dhcp" -or $_.PrefixOrigin -eq "Manual")
|
||||
}
|
||||
|
||||
foreach ($adapter in $adapters) {
|
||||
$networkAddr = $adapter.IPAddress
|
||||
$prefixLength = $adapter.PrefixLength
|
||||
|
||||
# Simple network calculation for /24 networks (most common)
|
||||
if ($prefixLength -eq 24) {
|
||||
$parts = $networkAddr.Split('.')
|
||||
if ($parts.Length -eq 4) {
|
||||
$networkAddress = "$($parts[0]).$($parts[1]).$($parts[2]).0"
|
||||
$networks += "$networkAddress/24"
|
||||
Write-Log "Found network: $networkAddress/24 from adapter $($adapter.IPAddress)"
|
||||
}
|
||||
}
|
||||
elseif ($prefixLength -eq 16) {
|
||||
$parts = $networkAddr.Split('.')
|
||||
if ($parts.Length -eq 4) {
|
||||
$networkAddress = "$($parts[0]).$($parts[1]).0.0"
|
||||
$networks += "$networkAddress/16"
|
||||
Write-Log "Found network: $networkAddress/16 from adapter $($adapter.IPAddress)"
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Log "Skipping unsupported prefix length /$prefixLength for $networkAddr"
|
||||
}
|
||||
}
|
||||
|
||||
# Add common default networks if none found
|
||||
if ($networks.Count -eq 0) {
|
||||
$networks += "192.168.1.0/24"
|
||||
Write-Log "No networks auto-detected, using default: 192.168.1.0/24"
|
||||
}
|
||||
|
||||
return $networks
|
||||
}
|
||||
|
||||
function Show-NetworkSelectionMenu {
|
||||
Write-Host "`nWOL Manager - Selectare Retea" -ForegroundColor Yellow
|
||||
Write-Host "===============================" -ForegroundColor Yellow
|
||||
|
||||
# Try to detect local networks
|
||||
$detectedNetworks = @()
|
||||
$adapters = Get-NetIPAddress -AddressFamily IPv4 | Where-Object {
|
||||
$_.IPAddress -ne "127.0.0.1" -and ($_.PrefixOrigin -eq "Dhcp" -or $_.PrefixOrigin -eq "Manual")
|
||||
}
|
||||
|
||||
foreach ($adapter in $adapters) {
|
||||
$parts = $adapter.IPAddress.Split('.')
|
||||
if ($parts.Length -eq 4) {
|
||||
$networkAddr = "$($parts[0]).$($parts[1]).$($parts[2]).0/24"
|
||||
if ($detectedNetworks -notcontains $networkAddr) {
|
||||
$detectedNetworks += $networkAddr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Show menu
|
||||
Write-Host "`nSelecteaza reteaua de scanat:" -ForegroundColor White
|
||||
Write-Host ""
|
||||
|
||||
$menuOptions = @()
|
||||
$optionIndex = 1
|
||||
|
||||
# Add detected networks
|
||||
if ($detectedNetworks.Count -gt 0) {
|
||||
Write-Host "Retele detectate automat:" -ForegroundColor Green
|
||||
foreach ($detectedNetwork in $detectedNetworks) {
|
||||
Write-Host " $optionIndex. $detectedNetwork" -ForegroundColor Cyan
|
||||
$menuOptions += $detectedNetwork
|
||||
$optionIndex++
|
||||
}
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# Add common networks
|
||||
Write-Host "Retele comune:" -ForegroundColor Green
|
||||
$commonNetworks = @("192.168.1.0/24", "192.168.0.0/24", "10.0.0.0/24", "10.0.20.0/24", "172.16.0.0/24")
|
||||
|
||||
foreach ($commonNetwork in $commonNetworks) {
|
||||
if ($detectedNetworks -notcontains $commonNetwork) {
|
||||
Write-Host " $optionIndex. $commonNetwork" -ForegroundColor Cyan
|
||||
$menuOptions += $commonNetwork
|
||||
$optionIndex++
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host " $optionIndex. Introdu manual reteaua" -ForegroundColor Yellow
|
||||
$menuOptions += "custom"
|
||||
|
||||
Write-Host ""
|
||||
Write-Host " 0. Iesire" -ForegroundColor Red
|
||||
Write-Host ""
|
||||
|
||||
# Get user choice
|
||||
do {
|
||||
$choice = Read-Host "Selecteaza optiunea (0-$($menuOptions.Count))"
|
||||
|
||||
# Convert to integer for comparison
|
||||
try {
|
||||
$choiceNum = [int]$choice
|
||||
} catch {
|
||||
Write-Host "Te rog introdu un numar valid!" -ForegroundColor Red
|
||||
continue
|
||||
}
|
||||
|
||||
if ($choiceNum -eq 0) {
|
||||
Write-Host "Scanare anulata." -ForegroundColor Yellow
|
||||
exit 0
|
||||
}
|
||||
elseif ($choiceNum -ge 1 -and $choiceNum -le $menuOptions.Count) {
|
||||
if ($menuOptions[$choiceNum - 1] -eq "custom") {
|
||||
do {
|
||||
$customNetwork = Read-Host "Introdu reteaua in format CIDR (ex: 192.168.100.0/24)"
|
||||
if ($customNetwork -match '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2}$') {
|
||||
return @($customNetwork)
|
||||
} else {
|
||||
Write-Host "Format invalid! Foloseste formatul: 192.168.1.0/24" -ForegroundColor Red
|
||||
}
|
||||
} while ($true)
|
||||
} else {
|
||||
return @($menuOptions[$choiceNum - 1])
|
||||
}
|
||||
} else {
|
||||
Write-Host "Optiune invalida! Selecteaza intre 0 si $($menuOptions.Count)." -ForegroundColor Red
|
||||
}
|
||||
} while ($true)
|
||||
}
|
||||
|
||||
function Test-NetworkAddress {
|
||||
param(
|
||||
[string]$IPAddress,
|
||||
[int]$TimeoutMs = 1000
|
||||
)
|
||||
|
||||
try {
|
||||
$ping = New-Object System.Net.NetworkInformation.Ping
|
||||
$result = $ping.Send($IPAddress, $TimeoutMs)
|
||||
return $result.Status -eq "Success"
|
||||
}
|
||||
catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Get-NetworkDevices {
|
||||
param([string]$NetworkCIDR)
|
||||
|
||||
Write-Log "Scanning network: $NetworkCIDR"
|
||||
|
||||
# Parse network CIDR
|
||||
$parts = $NetworkCIDR -split '/'
|
||||
$networkAddress = $parts[0]
|
||||
$prefixLength = [int]$parts[1]
|
||||
|
||||
# Calculate IP range
|
||||
$networkParts = $networkAddress -split '\.'
|
||||
$baseIP = "$($networkParts[0]).$($networkParts[1]).$($networkParts[2])"
|
||||
|
||||
# Determine scan range based on prefix length
|
||||
if ($prefixLength -eq 24) {
|
||||
$startIP = 1
|
||||
$endIP = 254
|
||||
} else {
|
||||
Write-Log "Only /24 networks are supported in this version"
|
||||
return @()
|
||||
}
|
||||
|
||||
$devices = @()
|
||||
$aliveIPs = @()
|
||||
|
||||
# Simplified ping sweep with progress indication
|
||||
Write-Log "Starting ping sweep for $($endIP - $startIP + 1) addresses..."
|
||||
|
||||
# Use the configurable batch size parameter
|
||||
$totalIPs = $endIP - $startIP + 1
|
||||
$processed = 0
|
||||
|
||||
Write-Log "Scanning $totalIPs addresses in batches of $BatchSize..."
|
||||
|
||||
# Process IPs in smaller batches to avoid overwhelming the system
|
||||
for ($batch = $startIP; $batch -le $endIP; $batch += $BatchSize) {
|
||||
$batchEnd = [Math]::Min($batch + $BatchSize - 1, $endIP)
|
||||
$jobs = @()
|
||||
|
||||
Write-Log "Batch progress: $([Math]::Floor(($batch - $startIP) * 100 / $totalIPs))% - Scanning IPs $batch to $batchEnd"
|
||||
|
||||
# Create jobs for current batch
|
||||
for ($i = $batch; $i -le $batchEnd; $i++) {
|
||||
$ip = "$baseIP.$i"
|
||||
$job = Start-Job -ScriptBlock {
|
||||
param($IPAddress, $TimeoutMs)
|
||||
try {
|
||||
$ping = New-Object System.Net.NetworkInformation.Ping
|
||||
$result = $ping.Send($IPAddress, $TimeoutMs)
|
||||
return @{
|
||||
IP = $IPAddress
|
||||
Success = ($result.Status -eq "Success")
|
||||
ResponseTime = if ($result.Status -eq "Success") { $result.RoundtripTime } else { $null }
|
||||
}
|
||||
}
|
||||
catch {
|
||||
return @{
|
||||
IP = $IPAddress
|
||||
Success = $false
|
||||
ResponseTime = $null
|
||||
}
|
||||
}
|
||||
} -ArgumentList $ip, $TimeoutMs
|
||||
|
||||
$jobs += @{ Job = $job; IP = $ip }
|
||||
}
|
||||
|
||||
# Wait for batch to complete with timeout
|
||||
$maxWaitTime = ($TimeoutMs * 2) / 1000 # Convert to seconds, double the ping timeout
|
||||
foreach ($jobInfo in $jobs) {
|
||||
$result = Wait-Job -Job $jobInfo.Job -Timeout $maxWaitTime | Receive-Job
|
||||
Remove-Job -Job $jobInfo.Job -Force
|
||||
|
||||
if ($result -and $result.Success) {
|
||||
$aliveIPs += $result.IP
|
||||
Write-Log "Found alive host: $($result.IP) ($($result.ResponseTime)ms)"
|
||||
}
|
||||
|
||||
$processed++
|
||||
}
|
||||
|
||||
# Show progress more frequently
|
||||
$progressPercent = [Math]::Floor($processed * 100 / $totalIPs)
|
||||
Write-Log "Progress: $processed/$totalIPs addresses scanned ($progressPercent%)"
|
||||
|
||||
# Small delay between batches to prevent system overload
|
||||
Start-Sleep -Milliseconds 100
|
||||
}
|
||||
|
||||
Write-Log "Found $($aliveIPs.Count) alive hosts"
|
||||
|
||||
# Get ARP table to find MAC addresses
|
||||
Write-Log "Retrieving MAC addresses from ARP table..."
|
||||
$arpEntries = @{}
|
||||
|
||||
try {
|
||||
# Use Get-NetNeighbor for Windows 8/Server 2012 and later
|
||||
$neighbors = Get-NetNeighbor -AddressFamily IPv4 | Where-Object { $_.State -ne "Unreachable" }
|
||||
foreach ($neighbor in $neighbors) {
|
||||
if ($neighbor.LinkLayerAddress -and $neighbor.LinkLayerAddress -ne "00-00-00-00-00-00") {
|
||||
$arpEntries[$neighbor.IPAddress] = $neighbor.LinkLayerAddress.Replace('-', ':').ToLower()
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Log "Get-NetNeighbor failed, trying arp command..."
|
||||
|
||||
# Fallback to arp command
|
||||
try {
|
||||
$arpOutput = arp -a
|
||||
foreach ($line in $arpOutput) {
|
||||
if ($line -match '(\d+\.\d+\.\d+\.\d+)\s+([0-9a-fA-F-]{17})\s+\w+') {
|
||||
$ip = $matches[1]
|
||||
$mac = $matches[2].Replace('-', ':').ToLower()
|
||||
if ($mac -ne "00:00:00:00:00:00") {
|
||||
$arpEntries[$ip] = $mac
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Log "Warning: Could not retrieve ARP table"
|
||||
}
|
||||
}
|
||||
|
||||
# Build device list
|
||||
foreach ($ip in $aliveIPs) {
|
||||
$device = @{
|
||||
ip = $ip
|
||||
mac = if ($arpEntries.ContainsKey($ip)) { $arpEntries[$ip] } else { "" }
|
||||
hostname = ""
|
||||
status = "online"
|
||||
}
|
||||
|
||||
# Try to resolve hostname
|
||||
try {
|
||||
$hostname = [System.Net.Dns]::GetHostEntry($ip).HostName
|
||||
if ($hostname -and $hostname -ne $ip) {
|
||||
$device.hostname = $hostname
|
||||
}
|
||||
}
|
||||
catch {
|
||||
# Hostname resolution failed, leave empty
|
||||
}
|
||||
|
||||
$devices += $device
|
||||
|
||||
if ($device.mac) {
|
||||
Write-Log "Device found: $ip -> $($device.mac) ($($device.hostname))"
|
||||
} else {
|
||||
Write-Log "Device found: $ip (no MAC address available)"
|
||||
}
|
||||
}
|
||||
|
||||
return $devices
|
||||
}
|
||||
|
||||
# Main execution
|
||||
try {
|
||||
Write-Log "Starting Windows network scan..."
|
||||
|
||||
# Determine networks to scan
|
||||
$networksToScan = @()
|
||||
|
||||
if ($Network) {
|
||||
# Use specified network
|
||||
$networksToScan += $Network
|
||||
} else {
|
||||
# Show interactive menu for network selection
|
||||
$networksToScan = Show-NetworkSelectionMenu
|
||||
}
|
||||
|
||||
if ($networksToScan.Count -eq 0) {
|
||||
Write-Error "No networks to scan found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$allDevices = @()
|
||||
|
||||
# Scan each network
|
||||
foreach ($net in $networksToScan) {
|
||||
Write-Log "Processing network: $net"
|
||||
$devices = Get-NetworkDevices -NetworkCIDR $net
|
||||
$allDevices += $devices
|
||||
}
|
||||
|
||||
# Prepare result object
|
||||
$result = @{
|
||||
success = $true
|
||||
timestamp = (Get-Date -Format "yyyy-MM-ddTHH:mm:ss.fffZ")
|
||||
networks_scanned = $networksToScan
|
||||
computers = $allDevices
|
||||
message = "Scanare completata cu succes. Gasite $($allDevices.Count) dispozitive."
|
||||
}
|
||||
|
||||
# Ensure output directory exists
|
||||
$outputDir = Split-Path -Parent $OutputPath
|
||||
if (-not (Test-Path $outputDir)) {
|
||||
New-Item -ItemType Directory -Path $outputDir -Force | Out-Null
|
||||
}
|
||||
|
||||
# Save results to JSON
|
||||
$result | ConvertTo-Json -Depth 10 | Out-File -FilePath $OutputPath -Encoding UTF8
|
||||
|
||||
Write-Log "Results saved to: $OutputPath"
|
||||
Write-Log "Scan completed successfully. Found $($allDevices.Count) devices."
|
||||
|
||||
# Also output to console for immediate feedback
|
||||
if ($allDevices.Count -gt 0) {
|
||||
Write-Host "`nDevices found:" -ForegroundColor Yellow
|
||||
foreach ($device in $allDevices) {
|
||||
$macInfo = if ($device.mac) { $device.mac } else { "No MAC" }
|
||||
$hostInfo = if ($device.hostname) { " ($($device.hostname))" } else { "" }
|
||||
Write-Host " $($device.ip) -> $macInfo$hostInfo" -ForegroundColor Cyan
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
$errorResult = @{
|
||||
success = $false
|
||||
timestamp = (Get-Date -Format "yyyy-MM-ddTHH:mm:ss.fffZ")
|
||||
message = "Eroare la scanare: $($_.Exception.Message)"
|
||||
computers = @()
|
||||
}
|
||||
|
||||
$errorResult | ConvertTo-Json -Depth 10 | Out-File -FilePath $OutputPath -Encoding UTF8
|
||||
|
||||
Write-Error "Scan failed: $($_.Exception.Message)"
|
||||
exit 1
|
||||
}
|
||||
Reference in New Issue
Block a user