#Requires -Version 5.1 [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$IPRange, [Parameter(Mandatory = $false)] [string]$Username = "", [Parameter(Mandatory = $false)] [string]$Password = "", [Parameter(Mandatory = $false)] [string]$SNMPCommunity = "public", [ValidateSet("v1", "v2c", "v3")] [string]$SNMPVersion = "v2c", [ValidateSet("SSH", "SNMP", "Telnet", "Both", "All")] [string]$Method = "All", [string]$OutputPath = $PSScriptRoot, [ValidateRange(1, 100)] [int]$MaxThreads = 20, [int]$SSHPort = 22, [int]$Timeout = 5 ) Set-StrictMode -Version Latest $ErrorActionPreference = "SilentlyContinue" function Write-Header { param([string]$t); Write-Host "`n$('-'*60)" -ForegroundColor DarkCyan; Write-Host " $t" -ForegroundColor Cyan; Write-Host "$('-'*60)" -ForegroundColor DarkCyan } function Write-Step { param([string]$t); Write-Host " [>] $t" -ForegroundColor Yellow } function Write-OK { param([string]$t); Write-Host " [+] $t" -ForegroundColor Green } function Write-Fail { param([string]$t); Write-Host " [-] $t" -ForegroundColor Red } function Write-Info { param([string]$t); Write-Host " [i] $t" -ForegroundColor Gray } function Test-Dependencies { Write-Header "Bagimlilik Kontrolu" $missing = @() if (-not (Get-Module -ListAvailable -Name Posh-SSH)) { Write-Fail "Posh-SSH bulunamadi"; $missing += "Posh-SSH" } else { Write-OK "Posh-SSH mevcut" } $script:SnmpLibAvailable = $false $dll = Join-Path $PSScriptRoot "lib\SharpSnmpLib.dll" if (Test-Path $dll) { Add-Type -Path $dll -ErrorAction SilentlyContinue $script:SnmpLibAvailable = $true Write-OK "SharpSnmpLib.dll mevcut" } else { Write-Info "SharpSnmpLib.dll yok - yerlesik UDP SNMP kullanilacak" } if ($missing.Count -gt 0) { Write-Host "`n Eksik: Install-Module Posh-SSH -Scope CurrentUser -Force" -ForegroundColor Magenta $ans = Read-Host " Simdi kurulsun mu? (E/H)" if ($ans -match '^[Ee]') { foreach ($m in $missing) { Write-Step "$m kuruluyor..." Install-Module -Name $m -Scope CurrentUser -Force -AllowClobber Write-OK "$m kuruldu" } } } } function Resolve-IPRange { param([string]$Range) $ips = [System.Collections.Generic.List[string]]::new() if ($Range -match '^(\d{1,3}(?:\.\d{1,3}){3})/(\d{1,2})$') { $bytes = [System.Net.IPAddress]::Parse($Matches[1]).GetAddressBytes() [array]::Reverse($bytes) $ipInt = [System.BitConverter]::ToUInt32($bytes, 0) $prefix = [int]$Matches[2] $mask = [uint32]([math]::Pow(2, 32) - [math]::Pow(2, 32 - $prefix)) $net = $ipInt -band $mask $count = [math]::Pow(2, 32 - $prefix) for ($i = 1; $i -lt ($count - 1); $i++) { $b = [System.BitConverter]::GetBytes([uint32]($net + $i)); [array]::Reverse($b) $ips.Add(([System.Net.IPAddress]::new($b)).ToString()) } } elseif ($Range -match '^(\d{1,3}(?:\.\d{1,3}){3})-(\d{1,3}(?:\.\d{1,3}){3})$') { $sb = [System.Net.IPAddress]::Parse($Matches[1]).GetAddressBytes(); [array]::Reverse($sb) $eb = [System.Net.IPAddress]::Parse($Matches[2]).GetAddressBytes(); [array]::Reverse($eb) $s = [System.BitConverter]::ToUInt32($sb, 0); $e = [System.BitConverter]::ToUInt32($eb, 0) for ($i = $s; $i -le $e; $i++) { $b = [System.BitConverter]::GetBytes([uint32]$i); [array]::Reverse($b) $ips.Add(([System.Net.IPAddress]::new($b)).ToString()) } } elseif ($Range -match '^\d{1,3}(?:\.\d{1,3}){3}$') { $ips.Add($Range) } else { throw "Gecersiz IP formati: $Range" } return $ips } function Get-AliveHosts { param([System.Collections.Generic.List[string]]$IPs) Write-Header "Canli Host Taramasi (Ping)" Write-Info "Toplam $($IPs.Count) IP taranacak..." $pool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads) $pool.Open() $jobs = [System.Collections.Generic.List[hashtable]]::new() foreach ($ip in $IPs) { $ps = [powershell]::Create() $ps.RunspacePool = $pool [void]$ps.AddScript({ param($ip, $t) try { $ping = [System.Net.NetworkInformation.Ping]::new() $r = $ping.Send($ip, $t * 1000) if ($r.Status -eq 'Success') { return $ip } } catch { } return $null }).AddArgument($ip).AddArgument($Timeout) $jobs.Add(@{ PS = $ps; Handle = $ps.BeginInvoke() }) } $alive = [System.Collections.Generic.List[string]]::new() foreach ($j in $jobs) { $result = $j.PS.EndInvoke($j.Handle) if ($result) { $alive.Add($result) } $j.PS.Dispose() } $pool.Close(); $pool.Dispose() Write-OK "$($alive.Count) canli host bulundu" return ($alive | Sort-Object { [System.Version]$_ }) } function Invoke-SNMPQuery { param([string]$IP, [string]$Community, [string]$OID) $parts = $OID.TrimStart('.').Split('.') | ForEach-Object { [int]$_ } function eLen([int]$n) { if ($n -lt 128) { return [byte[]]@($n) } $bl = [System.Collections.Generic.List[byte]]::new(); $tmp = $n while ($tmp -gt 0) { $bl.Insert(0, [byte]($tmp -band 0xFF)); $tmp = $tmp -shr 8 } return [byte[]](@([byte](0x80 + $bl.Count)) + $bl) } function eInt([int]$v) { $bl = [System.Collections.Generic.List[byte]]::new(); $tmp = $v do { $bl.Insert(0, [byte]($tmp -band 0xFF)); $tmp = $tmp -shr 8 }while ($tmp -gt 0) if ($bl[0] -band 0x80) { $bl.Insert(0, [byte]0) } return [byte[]](@([byte]0x02) + (eLen $bl.Count) + $bl) } function eOID([int[]]$p) { $enc = [System.Collections.Generic.List[byte]]::new() $enc.Add([byte](40 * $p[0] + $p[1])) for ($i = 2; $i -lt $p.Count; $i++) { $v = $p[$i] if ($v -lt 128) { $enc.Add([byte]$v) } else { $sub = [System.Collections.Generic.List[byte]]::new() while ($v -gt 0) { $sub.Insert(0, [byte]($v -band 0x7F)); $v = $v -shr 7 } for ($j = 0; $j -lt $sub.Count - 1; $j++) { $sub[$j] = [byte]($sub[$j] -bor 0x80) } foreach ($b in $sub) { $enc.Add($b) } } } return [byte[]](@([byte]0x06) + (eLen $enc.Count) + $enc) } try { $oidB = [byte[]](eOID $parts) $nul = [byte[]]@(0x05, 0x00) $vb = [byte[]](@([byte]0x30) + (eLen($oidB.Count + $nul.Count)) + $oidB + $nul) $vbl = [byte[]](@([byte]0x30) + (eLen $vb.Count) + $vb) $cb = [System.Text.Encoding]::ASCII.GetBytes($Community) $cf = [byte[]](@([byte]0x04) + (eLen $cb.Count) + $cb) $ver = eInt 1; $rid = eInt(Get-Random -Min 1 -Max 99999); $es = eInt 0; $ei = eInt 0 $pdu = [byte[]](@([byte]0xA0) + (eLen($rid.Count + $es.Count + $ei.Count + $vbl.Count)) + $rid + $es + $ei + $vbl) $msg = [byte[]]($ver + $cf + $pdu) $pkt = [byte[]](@([byte]0x30) + (eLen $msg.Count) + $msg) $udp = [System.Net.Sockets.UdpClient]::new() $udp.Client.ReceiveTimeout = 2000 $ep = [System.Net.IPEndPoint]::new([System.Net.IPAddress]::Parse($IP), 161) [void]$udp.Send($pkt, $pkt.Count, $ep) $rem = [System.Net.IPEndPoint]::new([System.Net.IPAddress]::Any, 0) $resp = $udp.Receive([ref]$rem); $udp.Close() $skip = $true for ($i = 0; $i -lt $resp.Count - 2; $i++) { if ($resp[$i] -eq 0x04 -and $resp[$i + 1] -gt 0 -and $resp[$i + 1] -lt 200) { $len = $resp[$i + 1]; $st = $i + 2 if (($st + $len) -le $resp.Count) { if ($skip) { $skip = $false; $i = $st + $len - 1; continue } $val = [System.Text.Encoding]::ASCII.GetString($resp, $st, $len).Trim() if ($val -match '\S') { return $val } } } } } catch { } return $null } function Get-Vendor { param([string]$d) if (-not $d) { return "Bilinmiyor" } $dl = $d.ToLower() if ($dl -match "cisco|sg[1-5]\d{2}|cbs\d{3}|catalyst|nexus") { return "Cisco" } if ($dl -match "hp|hewlett|procurve|aruba") { return "HP/Aruba" } if ($dl -match "ubiquiti|unifi|edgeswitch") { return "Ubiquiti" } if ($dl -match "mikrotik") { return "MikroTik" } if ($dl -match "huawei") { return "Huawei" } if ($dl -match "tp-link|tplink") { return "TP-Link" } if ($dl -match "juniper") { return "Juniper" } if ($dl -match "dell|force10") { return "Dell" } if ($dl -match "netgear") { return "Netgear" } if ($dl -match "zyxel") { return "ZyXEL" } if ($dl -match "dlink|d-link") { return "D-Link" } return "Bilinmiyor" } function Get-Model { param([string]$desc, [string]$vendor) if (-not $desc) { return "Bilinmiyor" } switch ($vendor) { "Cisco" { if ($desc -match '(?i)(Catalyst\s*[\w-]+)') { return $Matches[1].Trim() } if ($desc -match '(?i)\b(C\d{4}[A-Za-z0-9-]*|SG[1-5]\d{2}[A-Za-z0-9-]*|CBS\d{3}[A-Za-z0-9-]*|Nexus\s*[\w-]+|N\d{4}[A-Za-z0-9-]*)\b') { return $Matches[1].Trim() } if ($desc -match '(?i)Cisco\s+(?!IOS\b)([\w-]+)') { return $Matches[1].Trim() } } "HP/Aruba" { if ($desc -match 'HP\s+([\w\s-]+?)(?:\s*,|\s*Switch|\s*$)') { return $Matches[1].Trim() } } "Ubiquiti" { if ($desc -match 'EdgeSwitch\s+([\w-]+)') { return "EdgeSwitch $($Matches[1])" } if ($desc -match 'UniFi\s+([\w-]+)') { return "UniFi $($Matches[1])" } } "Huawei" { if ($desc -match 'Huawei\s+([\w-]+)') { return $Matches[1] } } "TP-Link" { if ($desc -match '(TL-[\w-]+)') { return $Matches[1] } } } if ($desc -cmatch '\b([A-Z]{1,5}[\w-]{2,15})\b') { $m = $Matches[1] if ($m -notmatch '(?i)^(User|Password|System|Switch|Terminal|Length|Screen|Display|Show|Version|Login|Name|Host|Line|Console|Ethernet|Vlan|Port|Interface)$') { return $m } } return "Bilinmiyor" } function Get-DeviceViaSNMP { param([string]$IP, [string]$Community) $info = [PSCustomObject]@{IP = "$IP"; Hostname = ""; Vendor = "Bilinmiyor"; Model = "Bilinmiyor"; SysDescr = ""; SysContact = ""; SysLocation = ""; FirmwareVer = ""; Method = "SNMP"; Status = "Basarisiz"; Error = "" } try { $sysDescr = Invoke-SNMPQuery $IP $Community "1.3.6.1.2.1.1.1.0" $sysName = Invoke-SNMPQuery $IP $Community "1.3.6.1.2.1.1.5.0" $sysContact = Invoke-SNMPQuery $IP $Community "1.3.6.1.2.1.1.4.0" $sysLocation = Invoke-SNMPQuery $IP $Community "1.3.6.1.2.1.1.6.0" if ($sysDescr -or $sysName) { $info.SysDescr = "$sysDescr"; $info.Hostname = "$sysName" $info.SysContact = "$sysContact"; $info.SysLocation = "$sysLocation" $info.Vendor = Get-Vendor $sysDescr $m = Get-Model $sysDescr $info.Vendor if ($info.Hostname -and $m -eq $info.Hostname) { $info.Model = "Bilinmiyor" } else { $info.Model = $m } $info.Status = "Basarili" } else { $info.Error = "SNMP yanit vermedi" } } catch { $info.Error = "$($_.Exception.Message)" } return $info } function Get-DeviceViaSSH { param([string]$IP, [string]$User, [string]$Pass, [int]$Port) $info = [PSCustomObject]@{IP = "$IP"; Hostname = ""; Vendor = "Bilinmiyor"; Model = "Bilinmiyor"; SysDescr = ""; SysContact = ""; SysLocation = ""; FirmwareVer = ""; Method = "SSH"; Status = "Basarisiz"; Error = "" } if (-not (Get-Module -ListAvailable -Name Posh-SSH)) { $info.Error = "Posh-SSH yuklu degil"; return $info } Import-Module Posh-SSH -ErrorAction SilentlyContinue try { $secPass = ConvertTo-SecureString $Pass -AsPlainText -Force $cred = [System.Management.Automation.PSCredential]::new($User, $secPass) $session = New-SSHSession -ComputerName $IP -Credential $cred -Port $Port -AcceptKey -ConnectionTimeout($Timeout * 1000) -ErrorAction Stop if (-not $session) { $info.Error = "SSH oturumu acilamadi"; return $info } $stream = $session.Session.CreateShellStream("xterm", 80, 24, 800, 600, 1024) Start-Sleep -Milliseconds 1500; $banner = $stream.Read() $vendor = "Unknown" if ($banner -match "Cisco") { $vendor = "Cisco" } elseif ($banner -match "HP|ProCurve|Aruba") { $vendor = "HP/Aruba" } elseif ($banner -match "Ubiquiti|EdgeOS") { $vendor = "Ubiquiti" } elseif ($banner -match "MikroTik") { $vendor = "MikroTik" } elseif ($banner -match "Huawei") { $vendor = "Huawei" } $cmds = switch ($vendor) { "Cisco" { @("terminal length 0", "show version", "show running-config | include hostname") } "HP/Aruba" { @("no page", "show system information", "show version") } "Ubiquiti" { @("show version", "show system") } "MikroTik" { @("/system identity print", "/system resource print", "/system routerboard print") } "Huawei" { @("screen-length 0 temporary", "display version", "display sysname") } default { @("show version", "show system", "uname -a") } } $out = "" foreach ($cmd in $cmds) { $stream.WriteLine($cmd); Start-Sleep -Milliseconds 800; $out += $stream.Read() } if ($out) { $cleanOut = $out -replace '\x1B\[[0-9;?]*[a-zA-Z]', '' $info.SysDescr = (($cleanOut -split "`n" | Select-Object -First 3) -join " ").Trim() if ($cleanOut -match '(?im)(?:hostname|sysname)[:\s]+([^\r\n]+)') { $info.Hostname = $Matches[1].Trim() } else { $pMatches = [regex]::Matches($cleanOut, '[<\[]*([A-Za-z0-9_-]{3,})[#>\]]') if ($pMatches.Count -gt 0) { $info.Hostname = $pMatches[$pMatches.Count - 1].Groups[1].Value.Trim() } } $info.Vendor = if ($vendor -ne "Unknown") { $vendor }else { Get-Vendor $cleanOut } $m = Get-Model $cleanOut $info.Vendor if ($info.Hostname -and $m -eq $info.Hostname) { $info.Model = "Bilinmiyor" } else { $info.Model = $m } if ($cleanOut -match '(?i)Version[:\s]+([\d\.A-Za-z\(\)]+)') { $info.FirmwareVer = $Matches[1] } $info.Status = "Basarili" } } catch { $info.Error = "$($_.Exception.Message)" } return $info } function Get-DeviceViaTelnet { param([string]$IP, [string]$User, [string]$Pass, [int]$Port = 23) $info = [PSCustomObject]@{IP = "$IP"; Hostname = ""; Vendor = "Bilinmiyor"; Model = "Bilinmiyor"; SysDescr = ""; SysContact = ""; SysLocation = ""; FirmwareVer = ""; Method = "Telnet"; Status = "Basarisiz"; Error = "" } try { $tcp = [System.Net.Sockets.TcpClient]::new() $res = $tcp.BeginConnect($IP, $Port, $null, $null) $wait = $res.AsyncWaitHandle.WaitOne(3000) if (-not $wait -or -not $tcp.Connected) { $info.Error = "Port kapali veya zaman asimi"; return $info } $tcp.EndConnect($res) $stream = $tcp.GetStream() $reader = [System.IO.StreamReader]::new($stream, [System.Text.Encoding]::ASCII) $writer = [System.IO.StreamWriter]::new($stream, [System.Text.Encoding]::ASCII) $writer.AutoFlush = $true $sb = [System.Text.StringBuilder]::new() $start = [datetime]::UtcNow $loggedIn = $false while (([datetime]::UtcNow - $start).TotalSeconds -lt 5) { if ($stream.DataAvailable) { while ($stream.DataAvailable) { [void]$sb.Append([char]$stream.ReadByte()) } $out = $sb.ToString() if ($out -match "(?i)username:|login:") { $writer.WriteLine($User); Start-Sleep -Milliseconds 500; $sb.Clear() } elseif ($out -match "(?i)password:") { $writer.WriteLine($Pass); Start-Sleep -Milliseconds 500; $sb.Clear() } elseif ($out -match ">|#") { $loggedIn = $true; break } } else { Start-Sleep -Milliseconds 200 } } if (-not $loggedIn) { $writer.WriteLine(""); Start-Sleep -Milliseconds 500 } $cmds = @("terminal length 0", "screen-length 0 temporary", "no page", "show version", "show system", "display version") foreach ($cmd in $cmds) { $writer.WriteLine($cmd); Start-Sleep -Milliseconds 500 while ($stream.DataAvailable) { [void]$sb.Append([char]$stream.ReadByte()) } } $tcp.Close() $fullOut = $sb.ToString() if ($fullOut -match '\S') { $cleanOut = $fullOut -replace '\x1B\[[0-9;?]*[a-zA-Z]', '' $info.SysDescr = (($cleanOut -split "`n" | Select-Object -First 3) -join " ").Trim() if ($cleanOut -match '(?im)(?:hostname|sysname)[:\s]+([^\r\n]+)') { $info.Hostname = $Matches[1].Trim() } else { $pMatches = [regex]::Matches($cleanOut, '[<\[]*([A-Za-z0-9_-]{3,})[#>\]]') if ($pMatches.Count -gt 0) { $info.Hostname = $pMatches[$pMatches.Count - 1].Groups[1].Value.Trim() } } $info.Vendor = Get-Vendor $cleanOut $m = Get-Model $cleanOut $info.Vendor if ($info.Hostname -and $m -eq $info.Hostname) { $info.Model = "Bilinmiyor" } else { $info.Model = $m } if ($cleanOut -match '(?i)Version[:\s]+([\d\.A-Za-z\(\)]+)') { $info.FirmwareVer = $Matches[1] } $info.Status = "Basarili" } } catch { $info.Error = "$($_.Exception.Message)" } return $info } function Get-DNS { param([string]$IP) try { return([System.Net.Dns]::GetHostEntry($IP)).HostName }catch { return "" } } function Merge-Info { param($ssh, $telnet, $snmp, [string]$ip) $m = [PSCustomObject]@{IP = "$ip"; Hostname = ""; DNSName = (Get-DNS $ip); Vendor = "Bilinmiyor"; Model = "Bilinmiyor"; FirmwareVer = ""; SysLocation = ""; SysContact = ""; SSHStatus = "Atlandi"; TelnetStatus = "Atlandi"; SNMPStatus = "Atlandi"; SysDescr = "" } if ($snmp) { $m.SNMPStatus = $snmp.Status; if ($snmp.Status -eq "Basarili") { $m.Hostname = $snmp.Hostname; $m.Vendor = $snmp.Vendor; $m.Model = $snmp.Model; $m.SysLocation = $snmp.SysLocation; $m.SysContact = $snmp.SysContact; $m.SysDescr = $snmp.SysDescr } } if ($telnet) { $m.TelnetStatus = $telnet.Status; if ($telnet.Status -eq "Basarili") { if (-not $m.Hostname) { $m.Hostname = $telnet.Hostname }; if ($m.Vendor -eq "Bilinmiyor") { $m.Vendor = $telnet.Vendor }; if ($m.Model -eq "Bilinmiyor") { $m.Model = $telnet.Model }; if (-not $m.FirmwareVer) { $m.FirmwareVer = $telnet.FirmwareVer } } } if ($ssh) { $m.SSHStatus = $ssh.Status; if ($ssh.Status -eq "Basarili") { if (-not $m.Hostname) { $m.Hostname = $ssh.Hostname }; if ($m.Vendor -eq "Bilinmiyor") { $m.Vendor = $ssh.Vendor }; if ($m.Model -eq "Bilinmiyor") { $m.Model = $ssh.Model }; if (-not $m.FirmwareVer) { $m.FirmwareVer = $ssh.FirmwareVer } } } if ((-not $m.Hostname) -and $m.DNSName) { $m.Hostname = $m.DNSName } return $m } function Export-ToCSV { param($res, [string]$path) $ts = Get-Date -Format "yyyyMMdd_HHmmss"; $out = Join-Path $path "SwitchDiscovery_$ts.csv" $res | Select-Object IP, Hostname, DNSName, Vendor, Model, FirmwareVer, SysLocation, SysContact, SSHStatus, TelnetStatus, SNMPStatus, SysDescr | Export-Csv -Path $out -NoTypeInformation -Encoding UTF8 Write-OK "CSV: $out"; return $out } function Export-ToHTML { param($res, [string]$path) $ts = Get-Date -Format "yyyyMMdd_HHmmss"; $outPath = Join-Path $path "SwitchDiscovery_$ts.html" $genDate = Get-Date -Format "dd.MM.yyyy HH:mm:ss" $total = $res.Count $sshOK = ($res | Where-Object { $_.SSHStatus -eq "Basarili" }).Count $telnetOK = ($res | Where-Object { $_.TelnetStatus -eq "Basarili" }).Count $snmpOK = ($res | Where-Object { $_.SNMPStatus -eq "Basarili" }).Count $sb = [System.Text.StringBuilder]::new() foreach ($r in $res) { $s1 = if ($r.SSHStatus -eq "Basarili") { 'SSH OK' }elseif ($r.SSHStatus -eq "Atlandi") { 'SSH -' }else { 'SSH X' } $s3 = if ($r.TelnetStatus -eq "Basarili") { 'TELNET OK' }elseif ($r.TelnetStatus -eq "Atlandi") { 'TELNET -' }else { 'TELNET X' } $s2 = if ($r.SNMPStatus -eq "Basarili") { 'SNMP OK' }elseif ($r.SNMPStatus -eq "Atlandi") { 'SNMP -' }else { 'SNMP X' } [void]$sb.Append("$($r.IP)$($r.Hostname)
$($r.DNSName)$($r.Vendor)$($r.Model)$($r.FirmwareVer)$($r.SysLocation)$s1 $s3 $s2`n") } $lines = [System.Collections.Generic.List[string]]::new() $lines.Add('Switch Discovery

Network Switch Discovery Raporu

') $lines.Add("
Olusturulma: $genDate | IP: $IPRange | Yontem: $Method
") $lines.Add("
$total
Toplam
$sshOK
SSH Basarili
$telnetOK
Telnet Basarili
$snmpOK
SNMP Basarili
") $lines.Add('
') $lines.Add('') $lines.Add($sb.ToString()) $lines.Add('
IPHostnameMarkaModelFirmwareKonumDurum
') [System.IO.File]::WriteAllLines($outPath, $lines, [System.Text.UTF8Encoding]::new($false)) Write-OK "HTML: $outPath"; return $outPath } # ================================================================ ANA AKIS Clear-Host Write-Host " =====================================================" -ForegroundColor Cyan Write-Host " Network Switch Discovery Tool v1.2" -ForegroundColor Cyan Write-Host " SSH + SNMP | Cisco / HP / Ubiquiti / Huawei / TP-Link" -ForegroundColor Cyan Write-Host " =====================================================" -ForegroundColor Cyan if ($Method -ne "SNMP" -and -not $Password) { if (-not $Username) { $Username = Read-Host " SSH Kullanici adi" } $sp = Read-Host " SSH Sifre" -AsSecureString $Password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($sp)) } Test-Dependencies Write-Header "IP Araligi Cozumleniyor" Write-Step "Aralik: $IPRange" $allIPs = Resolve-IPRange -Range $IPRange Write-OK "$($allIPs.Count) IP belirlendi" $aliveHosts = Get-AliveHosts -IPs $allIPs if ($aliveHosts.Count -eq 0) { Write-Fail "Canli host yok."; exit 1 } Write-Header "Cihaz Bilgisi Toplama" Write-Info "Yontem: $Method | Canli: $($aliveHosts.Count)" $scriptRoot = $PSScriptRoot $pool2 = [runspacefactory]::CreateRunspacePool(1, $MaxThreads) $pool2.Open() $jobs2 = [System.Collections.Generic.List[hashtable]]::new() $funcDefs = " function Invoke-SNMPQuery { ${function:Invoke-SNMPQuery} } function Get-Vendor { ${function:Get-Vendor} } function Get-Model { ${function:Get-Model} } function Get-DeviceViaSNMP { ${function:Get-DeviceViaSNMP} } function Get-DeviceViaSSH { ${function:Get-DeviceViaSSH} } function Get-DeviceViaTelnet { ${function:Get-DeviceViaTelnet} } function Get-DNS { ${function:Get-DNS} } function Merge-Info { ${function:Merge-Info} } " $discoverScript = [scriptblock]::Create(' param($ip,$method,$user,$pass,$comm,$port,$tout) ' + $funcDefs + ' $sshR=$null; $snmpR=$null; $telR=$null if($method -in @("SSH","Both","All")) { $sshR = Get-DeviceViaSSH $ip $user $pass $port } if($method -in @("Telnet","Both","All")) { $telR = Get-DeviceViaTelnet $ip $user $pass 23 } if($method -in @("SNMP","Both","All")) { $snmpR = Get-DeviceViaSNMP $ip $comm } return (Merge-Info $sshR $telR $snmpR $ip) ') foreach ($ip in $aliveHosts) { $ps = [powershell]::Create() $ps.RunspacePool = $pool2 [void]$ps.AddScript($discoverScript).AddArgument($ip).AddArgument($Method).AddArgument($Username).AddArgument($Password).AddArgument($SNMPCommunity).AddArgument($SSHPort).AddArgument($Timeout) $jobs2.Add(@{ PS = $ps; Handle = $ps.BeginInvoke(); IP = $ip; Done = $false }) } $allResults = [System.Collections.Generic.List[object]]::new() $total = $jobs2.Count $done = 0 $startTime = [datetime]::UtcNow $lastPrint = [datetime]::MinValue # konsol satirlari icin debounce Write-Host "" while ($done -lt $total) { # O an islenen IP'leri goster if (([datetime]::UtcNow - $lastPrint).TotalSeconds -ge 1) { $runningIPs = $jobs2 | Where-Object { -not $_.Done } | Select-Object -ExpandProperty IP $runningStr = ($runningIPs | Select-Object -First 3) -join ", " if ($runningIPs.Count -gt 3) { $runningStr += " ve $($runningIPs.Count - 3) daha..." } $pct = if ($total -gt 0) { [math]::Round($done / $total * 100) } else { 0 } Write-Progress ` -Activity "Switch kesfi - $done/$total tamamlandi" ` -Status ("Islenen cihazlar: $runningStr") ` -PercentComplete $pct $lastPrint = [datetime]::UtcNow } foreach ($j in $jobs2) { if ($j.Done) { continue } if ($j.Handle.IsCompleted) { $r = $j.PS.EndInvoke($j.Handle) $j.PS.Dispose() $j.Done = $true $done++ $rObj = $null if ($r -and $r.Count -gt 0) { $rObj = $r[0] } # Bulunan cihaz bilgisini al $foundIP = $j.IP $vendor = if ($rObj -and $rObj.Vendor -and $rObj.Vendor -ne "Bilinmiyor") { $rObj.Vendor } else { "?" } $model = if ($rObj -and $rObj.Model -and $rObj.Model -ne "Bilinmiyor") { $rObj.Model } else { "" } $hostname = if ($rObj -and $rObj.Hostname -and $rObj.Hostname -ne "") { $rObj.Hostname } else { "" } $sshStat = if ($rObj -and $rObj.SSHStatus) { $rObj.SSHStatus } else { "Atlandi" } $telStat = if ($rObj -and $rObj.TelnetStatus) { $rObj.TelnetStatus } else { "Atlandi" } $snmpStat = if ($rObj -and $rObj.SNMPStatus) { $rObj.SNMPStatus } else { "Atlandi" } if ($rObj) { $allResults.Add($rObj) } # --- ETA hesabi $elapsed = ([datetime]::UtcNow - $startTime).TotalSeconds $avgPerJob = if ($done -gt 0) { $elapsed / $done } else { 0 } $remaining = $total - $done $etaSec = [math]::Round($avgPerJob * $remaining) $etaStr = if ($etaSec -gt 3600) { "{0}s {1}d {2}sn" -f [math]::Floor($etaSec / 3600), [math]::Floor(($etaSec % 3600) / 60), ($etaSec % 60) } elseif ($etaSec -gt 60) { "{0}d {1}sn" -f [math]::Floor($etaSec / 60), ($etaSec % 60) } else { "${etaSec}sn" } # --- Renk secimi $lineColor = if ($sshStat -eq "Basarili" -or $snmpStat -eq "Basarili" -or $telStat -eq "Basarili") { "Green" } else { "DarkGray" } # --- Konsola yazdir $pctDone = [math]::Round($done / $total * 100) $bar = ("#" * [math]::Floor($pctDone / 5)).PadRight(20) $hostPart = if ($hostname) { " ($hostname)" } else { "" } $modPart = if ($model) { " $model" } else { "" } Write-Host (" [{0,3}%] [{1}] {2}/{3} {4,-16}{5}{6}{7} | Kalan ~{8}" -f ` $pctDone, $bar, $done, $total, $foundIP, $hostPart, " $vendor", $modPart, $etaStr) -ForegroundColor $lineColor } } if ($done -lt $total) { Start-Sleep -Milliseconds 200 } } $pool2.Close(); $pool2.Dispose() Write-Progress -Activity "Switch kesfi..." -Completed # Ozet satiri $elapsed = [math]::Round(([datetime]::UtcNow - $startTime).TotalSeconds) $sshFound = ($allResults | Where-Object { $_.SSHStatus -eq "Basarili" }).Count $telFound = ($allResults | Where-Object { $_.TelnetStatus -eq "Basarili" }).Count $snmpFound = ($allResults | Where-Object { $_.SNMPStatus -eq "Basarili" }).Count Write-Host "" Write-Host (" Tamamlandi: {0} cihaz taranadi | SSH:{1} Telnet:{2} SNMP:{3} Sure:{4}sn" -f $total, $sshFound, $telFound, $snmpFound, $elapsed) -ForegroundColor Cyan $sorted = $allResults | Sort-Object { [System.Version]$_.IP } Write-Header "Kesif Sonuclari" $sorted | Format-Table -AutoSize -Property IP, Hostname, Vendor, Model, FirmwareVer, SSHStatus, TelnetStatus, SNMPStatus Write-Header "Disari Aktarma" $csv = Export-ToCSV $sorted $OutputPath $html = Export-ToHTML $sorted $OutputPath Write-Header "Tamamlandi" Write-OK "Toplam: $($sorted.Count) cihaz" $ans = Read-Host "`n HTML raporu acilsin mi? (E/H)" if ($ans -match '^[Ee]') { Start-Process $html }