IPScanner.ps1
<#PSScriptInfo
.VERSION 1.0.3 .GUID 6f7b8c9a-4b2e-4c1d-9f3a-8d5e6c7b8c9a .AUTHOR illsk1lls .COMPANYNAME illsk1lls .COPYRIGHT Copyright (c) 2025 illsk1lls. Licensed under the MIT License. .TAGS IPScanner NetworkScanner TCPMonitor WPF PowerShell .LICENSEURI https://github.com/illsk1lls/IPScanner/blob/main/LICENSE .PROJECTURI https://github.com/illsk1lls/IPScanner .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES Clarified hybrid launch functionality in project description. #> <# .DESCRIPTION Simple IP Scanner is a GUI based powershell network scanner. It has zero dependencies, is roughly ~200x smaller, and ~66% faster than the most popular alternatives. Features include: Discovery of devices on a local subnet, displaying their IP, MAC, hostname, and vendor details. It also monitors active TCP connections and network performance in real-time, with options to export results and check connectivity. (The file can be renamed and launched with either a PS1 or CMD extension, but project notes/desc sections need to be removed from the top of the script to allow CMD usage. See main GitHub/Project Site for example) #> <# :: Hybrid CMD / Powershell Launcher - Rename file to .CMD to Autolaunch with console settings (Double-Click) - Rename to .PS1 to run as Powershell script without console settings @ECHO OFF SET "0=%~f0"&SET "LEGACY={B23D10C0-E52E-411E-9D5B-C09FDF709C7D}"&SET "LETWIN={00000000-0000-0000-0000-000000000000}"&SET "TERMINAL={2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69}"&SET "TERMINAL2={E12CFF52-A866-4C77-9A90-F570A7AA2C6B}" POWERSHELL -nop -c "Get-WmiObject -Class Win32_OperatingSystem | Select -ExpandProperty Caption | Find 'Windows 11'">nul IF ERRORLEVEL 0 ( SET isEleven=1 >nul 2>&1 REG QUERY "HKCU\Console\%%%%Startup" /v DelegationConsole IF ERRORLEVEL 1 ( REG ADD "HKCU\Console\%%%%Startup" /v DelegationConsole /t REG_SZ /d "%LETWIN%" /f>nul REG ADD "HKCU\Console\%%%%Startup" /v DelegationTerminal /t REG_SZ /d "%LETWIN%" /f>nul ) FOR /F "usebackq tokens=3" %%# IN (`REG QUERY "HKCU\Console\%%%%Startup" /v DelegationConsole 2^>nul`) DO ( IF NOT "%%#"=="%LEGACY%" ( SET "DEFAULTCONSOLE=%%#" REG ADD "HKCU\Console\%%%%Startup" /v DelegationConsole /t REG_SZ /d "%LEGACY%" /f>nul REG ADD "HKCU\Console\%%%%Startup" /v DelegationTerminal /t REG_SZ /d "%LEGACY%" /f>nul ) ) ) START /MIN "" POWERSHELL -nop -c "iex ([io.file]::ReadAllText('%~f0'))">nul IF "%isEleven%"=="1" ( IF DEFINED DEFAULTCONSOLE ( IF "%DEFAULTCONSOLE%"=="%TERMINAL%" ( REG ADD "HKCU\Console\%%%%Startup" /v DelegationConsole /t REG_SZ /d "%TERMINAL%" /f>nul REG ADD "HKCU\Console\%%%%Startup" /v DelegationTerminal /t REG_SZ /d "%TERMINAL2%" /f>nul ) ELSE ( REG ADD "HKCU\Console\%%%%Startup" /v DelegationConsole /t REG_SZ /d "%DEFAULTCONSOLE%" /f>nul REG ADD "HKCU\Console\%%%%Startup" /v DelegationTerminal /t REG_SZ /d "%DEFAULTCONSOLE%" /f>nul ) ) ) EXIT #>if($env:0){$PSCommandPath="$env:0"} ###POWERSHELL BELOW THIS LINE### # Hide Console - Show GUI Only - Only works for Legacy console Add-Type -MemberDefinition '[DllImport("User32.dll")]public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);' -Namespace Win32 -Name Functions $closeConsoleUseGUI=[Win32.Functions]::ShowWindow((Get-Process -Id $PID).MainWindowHandle,0) # Allow Single Instance Only $AppId = 'Simple IP Scanner' $singleInstance = $false $script:SingleInstanceEvent = New-Object Threading.EventWaitHandle $true,([Threading.EventResetMode]::ManualReset),"Global\$AppId",([ref] $singleInstance) if (-not $singleInstance){ $shell = New-Object -ComObject Wscript.Shell $shell.Popup("$AppId is already running!",0,'ERROR:',0x0) | Out-Null Exit } # Check if .NET Framework version is at least 3.0, which is required for WPF applications $frameworks = Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse | Get-ItemProperty -Name Version -EA 0 | Where-Object { $_.PSChildName -Match '^(?!S)\p{L}'} | Select-Object -ExpandProperty Version $highestVersion = $frameworks | ForEach-Object { [version]$_ } | Measure-Object -Maximum | Select-Object -ExpandProperty Maximum if ($highestVersion -lt [version]'3.0') { $dotnetchecker = New-Object -ComObject Wscript.Shell $dotnetchecker.Popup("dotNET 3.0 or higher is required!",0,'ERROR:',0x0) | Out-Null Exit } # GUI Main Dispatcher function Update-uiMain(){ $Main.Dispatcher.Invoke([Windows.Threading.DispatcherPriority]::Background, [action]{}) } function Update-Progress { param ($value, $text) $Progress.Value = $value $BarText.Text = $text Update-uiMain } # Find gateway $route = Get-NetRoute -DestinationPrefix 0.0.0.0/0 | Select-Object -First 1 $global:gateway = $route.NextHop $gatewayParts = $global:gateway -split '\.' $global:gatewayPrefix = (($gatewayParts[0..2] -join '.') + '.') # Store the original gateway prefix for reset functionality $originalGatewayPrefix = $global:gatewayPrefix # Initialize RunspacePool $SessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() $RunspacePool = [runspacefactory]::CreateRunspacePool(1, [System.Environment]::ProcessorCount, $SessionState, $Host) $RunspacePool.Open() # Get Host Info function Get-HostInfo { param( [string]$gateway, [string]$gatewayPrefix, [string]$originalGatewayPrefix ) $getHostInfoScriptBlock = { param( [string]$gateway, [string]$gatewayPrefix, [string]$originalGatewayPrefix ) # Get Hostname $hostName = [System.Net.Dns]::GetHostName() # Check internet connection and get external IP $ProgressPreference = 'SilentlyContinue' try { $ncsiCheck = Invoke-RestMethod "http://www.msftncsi.com/ncsi.txt" if ($ncsiCheck -eq "Microsoft NCSI") { $externalIP = Invoke-RestMethod "http://ifconfig.me/ip" } else { $externalIP = "No Internet or Redirection" } } catch { $externalIP = "No Internet or Error" } $ProgressPreference = 'Continue' # Use the passed gateway and gatewayPrefix $internalIP = (Get-NetIPAddress | Where-Object { $_.AddressFamily -eq 'IPv4' -and $_.InterfaceAlias -ne 'Loopback Pseudo-Interface 1' -and $_.IPAddress -like "$originalGatewayPrefix*" }).IPAddress # Get current adapter $adapter = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.InterfaceAlias -match 'Ethernet|Wi-Fi' -and $_.IPAddress -like "$originalGatewayPrefix*" }).InterfaceAlias # Get MAC address $myMac = (Get-NetAdapter -Name $adapter).MacAddress -replace '-', ':' # Get domain $domain = (Get-CimInstance -ClassName Win32_ComputerSystem).Domain # Init ARP cache data $arpInit = Get-NetNeighbor | Where-Object {($_.State -eq "Reachable" -or $_.State -eq "Stale") -and ($_.IPAddress -like "$gatewayPrefix*") -and -not $_.IPAddress.Contains(':')} | Select-Object -Property IPAddress, LinkLayerAddress # Mark empty as unknown $variables = @('hostName', 'externalIP', 'internalIP', 'gateway', 'domain') foreach ($item in $variables) { if (-not (Get-Variable -Name $item -ValueOnly)) { Set-Variable -Name $item -Value 'Unknown' } } return @{ 'hostName' = $hostName; 'externalIP' = $externalIP; 'internalIP' = $internalIP; 'gateway' = $gateway; 'gatewayPrefix' = $gatewayPrefix; 'adapter' = $adapter; 'myMac' = $myMac; 'domain' = $domain; 'arpInit' = $arpInit; } } $getHostInfoThread = [powershell]::Create().AddScript($getHostInfoScriptBlock) $getHostInfoThread.AddArgument($global:gateway) $getHostInfoThread.AddArgument($global:gatewayPrefix) $getHostInfoThread.AddArgument($originalGatewayPrefix) $getHostInfoThread.RunspacePool = $RunspacePool $getHostInfoAsync = $getHostInfoThread.BeginInvoke() $getHostInfoAsync.AsyncWaitHandle.WaitOne() $hostInfoResults = $getHostInfoThread.EndInvoke($getHostInfoAsync) $global:hostName = $hostInfoResults.hostName $global:externalIP = $hostInfoResults.externalIP $global:internalIP = $hostInfoResults.internalIP $global:gateway = $hostInfoResults.gateway $global:gatewayPrefix = $hostInfoResults.gatewayPrefix $global:adapter = $hostInfoResults.adapter $global:myMac = $hostInfoResults.myMac $global:domain = $hostInfoResults.domain $global:arpInit = $hostInfoResults.arpInit Update-Progress 0 'Scanning' $getHostInfoThread.Dispose() } # Send packets across subnet (progress values adjusted for proper display) function Scan-Subnet { $progressCounter = 0 1..254 | ForEach-Object { $progressCounter++ $percentComplete = [math]::Min([math]::Round(($progressCounter / 240) * 100), 100) Test-Connection -ComputerName "$global:gatewayPrefix$_" -Count 1 -AsJob | Out-Null if($percentComplete -ge 100){ Update-Progress -value $percentComplete -text "Listening" } else { Update-Progress -value $percentComplete -text "Sending Packets" } } Update-Progress -value 100 -text "Listening" Get-Job | Wait-Job -ErrorAction Stop | Out-Null $results = Get-Job | Receive-Job -ErrorAction Stop $global:successfulPings = @($results | Where-Object { $_.StatusCode -eq 0 } | Select-Object -ExpandProperty Address) Get-Job | Remove-Job -Force } # Create peer list function List-Machines { Update-Progress 0 'Identifying Devices' # Convert IP Addresses from string to int by each section $arpOutput = $arpInit | Where-Object { $_.IPAddress -match "^\d+\.\d+\.\d+\.\d+$" } | Sort-Object -Property { $ip = $_.IPAddress; [version]($ip) } $self = 0 $myLastOctet = [int]($internalIP -split '\.')[-1] # Get Vendor via Mac (thanks to u/mprz) $ProgressPreference = 'SilentlyContinue' $tryMyVendor = (irm "https://www.macvendorlookup.com/api/v2/$($myMac.Replace(':','').Substring(0,6))" -Method Get).Company $ProgressPreference = 'Continue' $myVendor = if($tryMyVendor){$tryMyVendor.substring(0, [System.Math]::Min(35, $tryMyVendor.Length))} else {'Unable to Identify'} # Cycle through ARP table to populate initial ListView data and start async lookups $totalItems = ($arpOutput.Count - 1) # First, add all known ARP entries and hostnames foreach ($line in $arpOutput) { $ip = $line.IPAddress $mac = $line.LinkLayerAddress.Replace('-',':') $quickNameLookup = ((Resolve-DnsName -Name $ip -DnsOnly -ErrorAction SilentlyContinue).NameHost) if(-not $quickNameLookup){$quickNameLookup = 'Resolving...'} $name = if ($ip -eq $internalIP) {"$hostName (This Device)"} else {"$quickNameLookup"} $vendor = if ($ip -eq $internalIP) {$myVendor} else {'Identifying...'} # Determine if the IP was pingable $pingResult = $ip -in $global:successfulPings # Format and display $item = [pscustomobject]@{ 'MACaddress' = $mac; 'Vendor' = $vendor; 'IPaddress' = $ip; 'HostName' = $name; 'Ping' = $pingResult; 'PingImage' = Create-GradientEllipse -isPingSuccessful $pingResult } $listView.Items.Add($item) } # Now add entries for successful pings not in ARP data, and add self $successfulPingsNotInARP = $global:successfulPings | Where-Object { $_ -notin $arpOutput.IPAddress } foreach ($ip in $successfulPingsNotInARP) { if ($global:gatewayPrefix -ne $originalGatewayPrefix) { $mac = 'Unreachable' } else { $mac = [MacAddressResolver]::GetMacFromIP($ip) } if ($ip -eq $internalIP) { $item = [pscustomobject]@{ 'MACaddress' = $myMac; 'Vendor' = $myVendor; 'IPaddress' = $internalIP; 'HostName' = "$hostName (This Device)"; 'Ping' = $true; 'PingImage' = Create-GradientEllipse -isPingSuccessful $true } $listView.Items.Add($item) } else { $item = [pscustomobject]@{ 'MACaddress' = $mac; 'Vendor' = $vendor; 'IPaddress' = $ip; 'HostName' = 'Resolving...'; 'Ping' = $true; 'PingImage' = Create-GradientEllipse -isPingSuccessful $true } $listView.Items.Add($item) } } # Sort ListView items by IP address in ascending order $sortedItems = $listView.Items | Sort-Object -Property {[version]$_.IPaddress} $listView.Items.Clear() $sortedItems | ForEach-Object { $listView.Items.Add($_) } $listView.Items.Refresh() if ($totalItems -ge 21) { $hostNameColumn.Width = 270 } $global:totalCount = $listView.Items.Count $TotalListed.Text = "$totalCount devices found" Update-uiMain } # Background Vendor Lookup function processVendors { $runspace = [runspacefactory]::CreateRunspace() $runspace.Open() $vendorLookup = [powershell]::Create() $vendorLookup.Runspace = $runspace $lookupBlock = { param ($listView, $internalIP) $vendorJobs = @{} # Process found devices foreach ($item in $listView.Items) { $ip = $item.IPaddress $mac = $item.MACaddress if ($ip -ne $internalIP) { if($item.Vendor -eq 'Identifying...'){ $vendorJob = Start-Job -ScriptBlock { param($mac) $ProgressPreference = 'SilentlyContinue' $response = (irm "https://www.macvendorlookup.com/api/v2/$($mac.Replace(':','').Substring(0,6))" -Method Get) $ProgressPreference = 'Continue' if([string]::IsNullOrEmpty($response.Company)){ return $null } else { return $response } } -ArgumentList $mac $vendorJobs[$ip] = $vendorJob do { # Limit maximum vendor tasks and process foreach ($ipCheck in @($vendorJobs.Keys)) { if ($vendorJobs[$ipCheck].State -eq "Completed") { $result = Receive-Job -Job $vendorJobs[$ipCheck] $vendorResult = if ($result -and $result.Company) { $result.Company.substring(0, [System.Math]::Min(30, $result.Company.Length)) } else { 'Unable to Identify' } foreach ($it in $listView.Items) { if ($it.IPaddress -eq $ipCheck) { $it.Vendor = $vendorResult } } $vendorJobs.Remove($ipCheck) } } Start-Sleep -Milliseconds 50 } while ($vendorJobs.Count -ge 5) } } } # Process remaining tasks while ($vendorJobs.Count -ge 1) { # Process vendor tasks foreach ($ipCheck in @($vendorJobs.Keys)) { if ($vendorJobs[$ipCheck].State -eq "Completed") { $result = Receive-Job -Job $vendorJobs[$ipCheck] $vendorResult = if ($result -and $result.Company) { $result.Company.substring(0, [System.Math]::Min(30, $result.Company.Length)) } else { 'Unable to Identify' } foreach ($it in $listView.Items) { if ($it.IPaddress -eq $ipCheck) { $it.Vendor = $vendorResult } } $vendorJobs.Remove($ipCheck) } } Start-Sleep -Milliseconds 50 } # Clean up jobs Remove-Job -Job $vendorJobs.Values -Force } # Script block params $null = $vendorLookup.AddScript($lookupBlock).AddArgument($listView).AddArgument($internalIP) $asyncResult = $vendorLookup.BeginInvoke() # Cleanup $vendorLookup.EndInvoke($asyncResult) $vendorLookup.Dispose() $runspace.Close() $runspace.Dispose() } # Background Hostname Lookup function processHostnames { $hostnameLookupThread = [powershell]::Create().AddScript({ param ($listView, $internalIP, $RunspacePool, $gatewayPrefix, $originalGatewayPrefix) $pingItems = @() $nonPingItems = @() # Separate items into pingable and non-pingable foreach ($item in $listView.Items) { if ($item.Ping -eq $true -and $item.IPaddress -ne $internalIP) { $pingItems += $item } elseif ($item.IPaddress -ne $internalIP) { $nonPingItems += $item } } # Hostname resolution with timeout $timeout = if ($gatewayPrefix -ne $originalGatewayPrefix) { 4500 } else { 3000 } $resolveScript = { param ($ip, $timeout) $dnsTask = [System.Net.Dns]::GetHostEntryAsync($ip) $timeoutTask = [System.Threading.Tasks.Task]::Delay($timeout) $task = [System.Threading.Tasks.Task]::WhenAny($dnsTask, $timeoutTask) $task.Wait() $result = $task.Result if ($result -eq $dnsTask -and $dnsTask.Status -eq [System.Threading.Tasks.TaskStatus]::RanToCompletion) { return [PSCustomObject]@{IP = $ip; HostName = $dnsTask.Result.HostName} } else { return [PSCustomObject]@{IP = $ip; HostName = "Unable to Resolve"} } } # Setup separate RunspacePool $iss = [system.management.automation.runspaces.initialsessionstate]::CreateDefault() $rsHost = [runspacefactory]::CreateRunspace($iss) $rsHost.Open() $rsPool = [runspacefactory]::CreateRunspacePool(1, 10, $rsHost, $RunspacePool.ApartmentState) $rsPool.Open() # Start hostNameJobs - responses first $hostNameJobs = @() foreach ($item in $pingItems) { if($item.Hostname -eq 'Resolving...'){ $hostNameJob = [powershell]::Create().AddScript($resolveScript).AddArgument($item.IPaddress).AddArgument($timeout) $hostNameJob.RunspacePool = $rsPool $hostNameJobHandle = $hostNameJob.BeginInvoke() $hostNameJobs += [PSCustomObject]@{ Pipeline = $hostNameJob Handle = $hostNameJobHandle IP = $item.IPaddress } } } foreach ($item in $nonPingItems) { if($item.Hostname -eq 'Resolving...'){ $hostNameJob = [powershell]::Create().AddScript($resolveScript).AddArgument($item.IPaddress).AddArgument($timeout) $hostNameJob.RunspacePool = $rsPool $hostNameJobHandle = $hostNameJob.BeginInvoke() $hostNameJobs += [PSCustomObject]@{ Pipeline = $hostNameJob Handle = $hostNameJobHandle IP = $item.IPaddress } } } # Process hostNameJobs while ($hostNameJobs.Count -gt 0) { for ($i = $hostNameJobs.Count - 1; $i -ge 0; $i--) { $hostNameJob = $hostNameJobs[$i] if ($hostNameJob.Handle.IsCompleted) { $result = $hostNameJob.Pipeline.EndInvoke($hostNameJob.Handle) foreach ($it in $listView.Items) { if ($it.IPaddress -eq $hostNameJob.IP) { $it.HostName = $result.HostName break } } $hostNameJob.Pipeline.Dispose() $hostNameJobs.RemoveAt($i) } } Start-Sleep -Milliseconds 10 } # Cleanup $rsPool.Close() $rsPool.Dispose() $rsHost.Close() $rsHost.Dispose() }, $true).AddArgument($listView).AddArgument($internalIP).AddArgument($RunspacePool).AddArgument($global:gatewayPrefix).AddArgument($originalGatewayPrefix) $hostnameLookupThread.RunspacePool = $RunspacePool $hostnameScan = $hostnameLookupThread.BeginInvoke() } # Portscan function Test-Port { param ( [string]$computer, [int]$port, [int]$timeout = 5 ) $tcp = New-Object System.Net.Sockets.TcpClient try { $result = $tcp.BeginConnect($computer, $port, $null, $null) $success = $result.AsyncWaitHandle.WaitOne($timeout, $true) if ($success) { return "Port`: $port is open" } else { return $null } } catch { return $null } finally { $tcp.Close() } } # Check common ports function CheckConnectivity { param ( [string]$selectedhost ) # Disable all buttons for 'This Device' if ($selectedhost -match $internalIP) { @('btnRDP', 'btnWebInterface', 'btnShare') | ForEach-Object { Get-Variable $_ -ValueOnly | ForEach-Object { $_.IsEnabled = $false $_.Visibility = 'Collapsed' } } $btnNone.IsEnabled = $true $btnNone.Visibility = 'Visible' return } $global:tryToConnect = $selectedhost -replace ' (This Device)', '' # Find the item in ListView based on IP or HostName $selectedItem = $listView.Items | Where-Object { $_.IPaddress -eq $tryToConnect -or $_.HostName -eq $selectedhost } | Select-Object -First 1 # Check connectivity for different protocols $ports = @{ HTTP = 80 HTTPS = 443 SMBv2 = 445 SMB = 139 RDP = 3389 } $results = @{} foreach ($protocol in $ports.Keys) { $results[$protocol] = Test-Port -computer $tryToConnect -port $ports[$protocol] -timeout 200 } # Update button states based on connectivity results $btnShare.IsEnabled = ($results.SMBv2 -or $results.SMB) -and $HostName -ne $tryToConnect $btnShare.Visibility = if ($btnShare.IsEnabled) { 'Visible' } else { 'Collapsed' } if ($btnShare.Visibility -eq 'Visible') {$btnWebInterface.Margin = "0,0,25,0"} else {$btnWebInterface.Margin = "0,0,0,0"} $btnWebInterface.IsEnabled = ($results.HTTP -or $results.HTTPS) -and $HostName -ne $tryToConnect $btnWebInterface.Visibility = if ($btnWebInterface.IsEnabled) { 'Visible' } else { 'Collapsed' } $global:httpAvailable = if ($results.HTTP) { 1 } else { 0 } if ($btnShare.Visibility -eq 'Visible' -or $btnWebInterface.Visibility -eq 'Visible') {$btnRDP.Margin = "0,0,25,0"} else {$btnRDP.Margin = "0,0,0,0"} $btnRDP.IsEnabled = $results.RDP -and $HostName -ne $tryToConnect $btnRDP.Visibility = if ($btnRDP.IsEnabled) { 'Visible' } else { 'Collapsed' } # Show no connections icon if nothing is available if (-not $btnRDP.IsEnabled -and -not $btnWebInterface.IsEnabled -and -not $btnShare.IsEnabled) { $btnNone.IsEnabled = $true $btnNone.Visibility = 'Visible' } else { $btnNone.IsEnabled = $false $btnNone.Visibility = 'Collapsed' } # Show ping response status in popup window $pingStatusImage.Content = Create-GradientEllipse -isPingSuccessful $selectedItem.Ping -width 12 -height 12 $pingStatusText.Text = if ($selectedItem.Ping) { "ICMP response received" } else { "No ICMP response received" } } # Listview column sort logic $sortDirections = @{} $listViewSortColumn = { param([System.Object]$sender, [System.EventArgs]$Event) $column = $Event.OriginalSource.Column # Determine current direction, toggle if column has been sorted before switch ($true) { {$sortDirections.ContainsKey($column.Header)} { $sortDirections[$column.Header] = -not $sortDirections[$column.Header] } default { # false for descending, true for ascending $sortDirections[$column.Header] = $false } } $direction = if ($sortDirections[$column.Header]) { "Ascending" } else { "Descending" } # Sort items $sortedItems = switch ($column.Header) { "IP Address" { $Sender.Items | Sort-Object -Property {[version]$_.IPaddress} -Descending:($direction -eq "Descending") } default { if ($column.DisplayMemberBinding.Path.Path) { $Sender.Items | Sort-Object -Property $column.DisplayMemberBinding.Path.Path -Descending:($direction -eq "Descending") } else { $Sender.Items } } } # Rebuild sorted list $Sender.Items.Clear() $sortedItems | ForEach-Object { $Sender.Items.Add($_) } } function Create-GradientEllipse { param ( [bool]$isPingSuccessful, [double]$width = 9, [double]$height = 9 ) $ellipse = [Windows.Shapes.Ellipse]::new() $ellipse.Width = $width $ellipse.Height = $height if ($isPingSuccessful) { # Lighter blue gradient for successful ping $gradient = New-Object System.Windows.Media.RadialGradientBrush $gradient.GradientOrigin = New-Object System.Windows.Point(0.5, 0.5) $gradient.Center = New-Object System.Windows.Point(0.5, 0.5) $gradient.RadiusX = 0.5 $gradient.RadiusY = 0.5 $stop1 = New-Object System.Windows.Media.GradientStop $stop1.Color = [System.Windows.Media.Color]::FromArgb(255, 51, 204, 255) $stop1.Offset = 0 $gradient.GradientStops.Add($stop1) $stop2 = New-Object System.Windows.Media.GradientStop $stop2.Color = [System.Windows.Media.Color]::FromArgb(255, 25, 153, 204) $stop2.Offset = 0.8 $gradient.GradientStops.Add($stop2) $stop3 = New-Object System.Windows.Media.GradientStop $stop3.Color = [System.Windows.Media.Color]::FromArgb(255, 0, 102, 153) $stop3.Offset = 1 $gradient.GradientStops.Add($stop3) } else { # Shades of gray for unsuccessful ping $gradient = New-Object System.Windows.Media.RadialGradientBrush $gradient.GradientOrigin = New-Object System.Windows.Point(0.5, 0.5) $gradient.Center = New-Object System.Windows.Point(0.5, 0.5) $gradient.RadiusX = 0.5 $gradient.RadiusY = 0.5 $stop4 = New-Object System.Windows.Media.GradientStop $stop4.Color = [System.Windows.Media.Color]::FromArgb(255, 220, 220, 220) $stop4.Offset = 0 $gradient.GradientStops.Add($stop4) $stop5 = New-Object System.Windows.Media.GradientStop $stop5.Color = [System.Windows.Media.Color]::FromArgb(255, 160, 160, 160) $stop5.Offset = 0.8 $gradient.GradientStops.Add($stop5) $stop6 = New-Object System.Windows.Media.GradientStop $stop6.Color = [System.Windows.Media.Color]::FromArgb(255, 100, 100, 100) $stop6.Offset = 1 $gradient.GradientStops.Add($stop6) } $ellipse.Fill = $gradient return $ellipse } # Display network speed as KB/s -MB/s -GB/s function Format-Speed { param ([double]$speedInKBs) if ($speedInKBs -ge 1024 * 1024) { return "{0:N1}gb" -f ($speedInKBs / (1024 * 1024)) } elseif ($speedInKBs -ge 1024) { return "{0:N1}mb" -f ($speedInKBs / 1024) } else { return "{0:N0}kb" -f $speedInKBs } } # Initialize hashtable for Monitor Mode $global:syncHash = [Hashtable]::Synchronized(@{ NetworkStats = @{} TCPConnections = @() LastUpdate = [DateTime]::Now Error = $null }) function Start-NetMonBackgroundTask { $backgroundScript = { param($syncHash, $adapters) function Get-NetworkStatsWithTimeout { $statsPerAdapter = @{} $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() $timeoutMs = 100 $retryCount = 2 for ($i = 0; $i -lt $retryCount; $i++) { try { $currentAdapters = Get-NetAdapter | Where-Object { $_.Status -eq "Up" -and $_.InterfaceDescription -notlike "*Loopback*" -and $_.InterfaceDescription -notlike "*ISATAP*" } if (-not $currentAdapters) { return $statsPerAdapter } foreach ($adapter in $currentAdapters) { $adapterName = $adapter.Name $stats = Get-NetAdapterStatistics -Name $adapterName -ErrorAction SilentlyContinue if ($stats) { $statsPerAdapter[$adapterName] = @{ RxBytes = [double]$stats.ReceivedBytes TxBytes = [double]$stats.SentBytes Timestamp = [double](Get-Date).Ticks } } else { $global:syncHash.Error = "No stats returned for adapter: $adapterName" } } if ($statsPerAdapter.Count -gt 0) { break } Start-Sleep -Milliseconds 100 } catch { $global:syncHash.Error = "Network stats error: $_" } $stopwatch.Stop() if ($stopwatch.ElapsedMilliseconds -gt $timeoutMs) { break } $stopwatch.Restart() } return $statsPerAdapter } function Get-TCPConnections { try { $connections = Get-NetTCPConnection | Where-Object { $_.State -eq "Established" } $tcpList = @() foreach ($conn in $connections) { $process = Get-CimInstance Win32_Process -Filter "ProcessId = $($conn.OwningProcess)" -ErrorAction SilentlyContinue $processName = if ($process) { $process.Name } else { "Unknown" } $tcpList += [PSCustomObject]@{ LocalAddress = $conn.LocalAddress; LocalPort = $conn.LocalPort; RemoteAddress = $conn.RemoteAddress; RemotePort = $conn.RemotePort; ProcessName = $processName } } return $tcpList } catch { $global:syncHash.Error = "TCP connections error: $_" return @() } } while ($true) { try { $stats = Get-NetworkStatsWithTimeout $tcp = Get-TCPConnections $global:syncHash.NetworkStats = $stats $global:syncHash.TCPConnections = $tcp $global:syncHash.LastUpdate = [DateTime]::Now $global:syncHash.Error = $null } catch { Write-Host "Background task error: $_" $global:syncHash.Error = $_.ToString() } Start-Sleep -Milliseconds 1000 } } $runspace = [PowerShell]::Create().AddScript($backgroundScript).AddArgument($syncHash).AddArgument($adapters) $runspace.RunspacePool = $RunspacePool return $runspace.BeginInvoke() } # Direct MAC request via iphlpapi.dll Add-Type -TypeDefinition @" using System; using System.Collections.Generic; using System.Runtime.InteropServices; public class MacAddressResolver { [DllImport("iphlpapi.dll", ExactSpelling = true)] public static extern int SendARP(uint DestIP, uint SrcIP, byte[] pMacAddr, ref int PhyAddrLen); public static string GetMacFromIP(string ipAddress) { try { System.Net.IPAddress ip = System.Net.IPAddress.Parse(ipAddress); byte[] macAddr = new byte[6]; int macAddrLen = macAddr.Length; if (SendARP(BitConverter.ToUInt32(ip.GetAddressBytes(), 0), 0, macAddr, ref macAddrLen) == 0) { string[] str = new string[macAddr.Length]; for (int i = 0; i < macAddr.Length; i++) { str[i] = macAddr[i].ToString("X2"); } return string.Join(":", str); } else { return "Unknown"; } } catch { return "Unknown"; } } } "@ # Get icons from DLL or EXE files via shell32.dll $getIcons = @" using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Interop; using System.Windows.Media.Imaging; using System.Windows; namespace System { public class IconExtractor { public static Icon Extract(string file, int number, bool largeIcon) { IntPtr large; IntPtr small; ExtractIconEx(file, number, out large, out small, 1); try { return Icon.FromHandle(largeIcon ? large : small); } catch { return null; } } public static BitmapSource IconToBitmapSource(Icon icon) { return Imaging.CreateBitmapSourceFromHIcon( icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } [DllImport("Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] private static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons); } } "@ # Define WPF GUI Structure Add-Type -TypeDefinition $getIcons -ReferencedAssemblies System.Windows.Forms, System.Drawing, PresentationCore, PresentationFramework, WindowsBase [xml]$XAML = @' <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="500" Width="900" Background="Transparent" AllowsTransparency="True" WindowStyle="None"> <Window.Resources> <ControlTemplate x:Key="NoMouseOverButtonTemplate" TargetType="Button"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Background" Value="{x:Static SystemColors.ControlLightBrush}"/> <Setter Property="Foreground" Value="{x:Static SystemColors.GrayTextBrush}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> <ControlTemplate x:Key="CloseButtonTemplate" TargetType="Button"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="0,5,0,0"> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Background" Value="{x:Static SystemColors.ControlLightBrush}"/> <Setter Property="Foreground" Value="{x:Static SystemColors.GrayTextBrush}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> <ControlTemplate x:Key="NoMouseOverColumnHeaderTemplate" TargetType="{x:Type GridViewColumnHeader}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Background" Value="{x:Static SystemColors.ControlLightBrush}"/> <Setter Property="Foreground" Value="{x:Static SystemColors.GrayTextBrush}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> <Style x:Key="ScrollThumbs" TargetType="{x:Type Thumb}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Thumb}"> <Grid x:Name="Grid"> <Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" Fill="Transparent"/> <Border x:Name="Rectangle1" CornerRadius="5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" Background="{TemplateBinding Background}"/> </Grid> <ControlTemplate.Triggers> <Trigger Property="Tag" Value="Horizontal"> <Setter TargetName="Rectangle1" Property="Width" Value="Auto"/> <Setter TargetName="Rectangle1" Property="Height" Value="7"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="{x:Type ScrollBar}" TargetType="{x:Type ScrollBar}"> <Setter Property="Stylus.IsPressAndHoldEnabled" Value="True"/> <Setter Property="Stylus.IsFlicksEnabled" Value="True" /> <Setter Property="Background" Value="#333333"/> <Setter Property="BorderThickness" Value="1,0"/> <Setter Property="BorderBrush" Value="#000000"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ScrollBar}"> <Grid x:Name="GridRoot" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" SnapsToDevicePixels="True"> <Track x:Name="PART_Track" IsDirectionReversed="true" Focusable="false"> <Track.Thumb> <Thumb x:Name="Thumb" Style="{StaticResource ScrollThumbs}" Background="#777777" /> </Track.Thumb> </Track> </Grid> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <Trigger Property="Orientation" Value="Vertical"> <Setter Property="Width" Value="10" /> <Setter Property="Height" Value="396" /> <Setter Property="MinHeight" Value="396" /> <Setter Property="MinWidth" Value="10" /> </Trigger> <Trigger Property="Orientation" Value="Horizontal"> <Setter Property="Width" Value="845" /> <Setter Property="Height" Value="10" /> <Setter Property="MinHeight" Value="10" /> <Setter Property="MinWidth" Value="845" /> <Setter Property="Margin" Value="-2,0,0,0" /> </Trigger> </Style.Triggers> </Style> <Style x:Key="ColumnHeaderStyle" TargetType="{x:Type GridViewColumnHeader}"> <Setter Property="Template" Value="{StaticResource NoMouseOverColumnHeaderTemplate}" /> <Setter Property="Background" Value="#CCCCCC" /> <Setter Property="Foreground" Value="Black" /> <Setter Property="BorderBrush" Value="#333333" /> <Setter Property="BorderThickness" Value="0,0,2,0" /> <Setter Property="Cursor" Value="Arrow" /> <Setter Property="FontWeight" Value="Bold"/> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="#EEEEEE" /> <Setter Property="Foreground" Value="Black" /> <Setter Property="BorderBrush" Value="#333333" /> </Trigger> </Style.Triggers> </Style> <Style x:Key="CustomContextMenuStyle" TargetType="{x:Type ContextMenu}"> <Setter Property="Background" Value="#666666"/> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="BorderBrush" Value="#333333"/> <Setter Property="BorderThickness" Value="0,0,2,0"/> <Setter Property="OverridesDefaultStyle" Value="True"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ContextMenu}"> <Border CornerRadius="2,4,4,2" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <StackPanel> <ItemsPresenter/> </StackPanel> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="CustomMenuItemStyle" TargetType="{x:Type MenuItem}"> <Setter Property="Background" Value="#666666"/> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type MenuItem}"> <Border x:Name="Border" BorderThickness="0.70" CornerRadius="2,4,4,4" Background="Transparent" SnapsToDevicePixels="True" Padding="12,3,12,3"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <ContentPresenter Margin="1" ContentSource="Header" RecognizesAccessKey="True" Grid.Column="0"/> <Popup x:Name="PART_Popup" Placement="Right" VerticalOffset="-5" HorizontalOffset="5" AllowsTransparency="True" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="Fade"> <Border x:Name="SubMenuBorder" CornerRadius="2,4,4,4" SnapsToDevicePixels="True" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0.70"> <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/> </Border> </Popup> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsHighlighted" Value="true"> <Setter Property="Background" TargetName="Border" Value="#4000B7FF"/> <Setter Property="BorderBrush" TargetName="Border" Value="#FF00BFFF"/> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Foreground" Value="#888888"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="MainMenuItemStyle" TargetType="{x:Type MenuItem}"> <Setter Property="Background" Value="#666666"/> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type MenuItem}"> <Border x:Name="Border" BorderThickness="0.70" CornerRadius="2,4,4,4" Background="Transparent" SnapsToDevicePixels="True" Padding="12,3,12,3"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <ContentPresenter Margin="1" ContentSource="Header" RecognizesAccessKey="True" Grid.Column="0"/> <Path x:Name="BlackArrow" Data="M0 0 L5 2.5 L0 5 Z" Width="5" Height="5" Margin="7,2,0,0" Grid.Column="1"> <Path.Fill> <SolidColorBrush Color="#EEEEEE"/> </Path.Fill> </Path> <Path x:Name="GrayArrow" Data="M0 0 L5 2.5 L0 5 Z" Width="5" Height="5" Margin="7,2,0,0" Grid.Column="1"> <Path.Fill> <SolidColorBrush Color="#888888"/> </Path.Fill> </Path> <Popup x:Name="PART_Popup" Placement="Right" VerticalOffset="-5" HorizontalOffset="5" AllowsTransparency="True" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="Fade"> <Border x:Name="SubMenuBorder" CornerRadius="2,4,4,4" SnapsToDevicePixels="True" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0.70"> <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/> </Border> </Popup> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsHighlighted" Value="true"> <Setter Property="Background" TargetName="Border" Value="#555555"/> <Setter Property="BorderBrush" TargetName="Border" Value="#FF00BFFF"/> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Foreground" Value="#888888"/> <Setter TargetName="BlackArrow" Property="Visibility" Value="Collapsed"/> <Setter TargetName="GrayArrow" Property="Visibility" Value="Visible"/> </Trigger> <Trigger Property="IsEnabled" Value="True"> <Setter TargetName="BlackArrow" Property="Visibility" Value="Visible"/> <Setter TargetName="GrayArrow" Property="Visibility" Value="Collapsed"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="CustomComboBoxStyle" TargetType="{x:Type ComboBox}"> <Setter Property="Width" Value="50"/> <Setter Property="Height" Value="25"/> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="Margin" Value="0,0,5,0"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ComboBox}"> <Grid> <ToggleButton Name="ToggleButton" ClickMode="Press" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Background="#333333" Foreground="#EEEEEE" BorderThickness="0.85" BorderBrush="#FF00BFFF"> <TextBlock Text="{Binding SelectedItem, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Left" VerticalAlignment="Center" Foreground="#EEEEEE" Margin="5,0,0,0"/> <ToggleButton.Template> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="BorderBrush" Value="#FF00BFFF"/> </Trigger> <Trigger Property="IsChecked" Value="True"> <Setter Property="BorderBrush" Value="#FF00BFFF"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </ToggleButton.Template> </ToggleButton> <Popup IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Bottom" AllowsTransparency="True" Focusable="False" PopupAnimation="Slide" Width="50"> <Border Name="DropDownBorder" BorderBrush="#CCCCCC" BorderThickness="0.80" Background="#444444"> <ScrollViewer MaxHeight="150" VerticalScrollBarVisibility="Hidden"> <StackPanel IsItemsHost="True"> <StackPanel.Resources> <Style TargetType="{x:Type ComboBoxItem}"> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="Background" Value="#444444"/> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Style.Triggers> <Trigger Property="IsHighlighted" Value="True"> <Setter Property="Background" Value="#555555"/> </Trigger> <Trigger Property="IsSelected" Value="True"> <Setter Property="Background" Value="#555555"/> </Trigger> </Style.Triggers> </Style> </StackPanel.Resources> </StackPanel> </ScrollViewer> </Border> </Popup> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="ToggleButton" Property="BorderBrush" Value="#EEEEEE"/> </Trigger> <Trigger Property="IsDropDownOpen" Value="True"> <Setter TargetName="DropDownBorder" Property="BorderBrush" Value="#FF00BFFF"/> <Setter TargetName="ToggleButton" Property="BorderBrush" Value="#EEEEEE"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="CustomComboBoxStyle2" TargetType="{x:Type ComboBox}"> <Setter Property="Width" Value="98"/> <Setter Property="Height" Value="25"/> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="Margin" Value="0,0,5,0"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ComboBox}"> <Grid> <ToggleButton Name="ToggleButton" ClickMode="Press" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Background="#333333" Foreground="#EEEEEE" BorderThickness="0.85" BorderBrush="#FF00BFFF"> <TextBlock Text="{Binding SelectedItem, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Left" VerticalAlignment="Center" Foreground="#EEEEEE" Margin="5,0,0,0"/> <ToggleButton.Template> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="BorderBrush" Value="#FF00BFFF"/> </Trigger> <Trigger Property="IsChecked" Value="True"> <Setter Property="BorderBrush" Value="#FF00BFFF"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </ToggleButton.Template> </ToggleButton> <Popup IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Bottom" AllowsTransparency="True" Focusable="False" PopupAnimation="Slide" Width="98"> <Border Name="DropDownBorder" BorderBrush="#CCCCCC" BorderThickness="0.80" Background="#444444"> <ScrollViewer MaxHeight="135" VerticalScrollBarVisibility="Hidden"> <StackPanel IsItemsHost="True"> <StackPanel.Resources> <Style TargetType="{x:Type ComboBoxItem}"> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="Background" Value="#444444"/> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Style.Triggers> <Trigger Property="IsHighlighted" Value="True"> <Setter Property="Background" Value="#555555"/> </Trigger> <Trigger Property="IsSelected" Value="True"> <Setter Property="Background" Value="#555555"/> </Trigger> </Style.Triggers> </Style> </StackPanel.Resources> </StackPanel> </ScrollViewer> </Border> </Popup> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="ToggleButton" Property="BorderBrush" Value="#EEEEEE"/> </Trigger> <Trigger Property="IsDropDownOpen" Value="True"> <Setter TargetName="DropDownBorder" Property="BorderBrush" Value="#FF00BFFF"/> <Setter TargetName="ToggleButton" Property="BorderBrush" Value="#EEEEEE"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="NetMonComboBoxStyle" TargetType="{x:Type ComboBox}"> <Setter Property="Width" Value="150"/> <Setter Property="Height" Value="25"/> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="Margin" Value="0,0,5,0"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ComboBox}"> <Grid> <ToggleButton Name="ToggleButton" ClickMode="Press" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Background="#333333" Foreground="#EEEEEE" BorderThickness="0.85" BorderBrush="#FF00BFFF"> <ToggleButton.Template> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="BorderBrush" Value="#FF00BFFF"/> </Trigger> <Trigger Property="IsChecked" Value="True"> <Setter Property="BorderBrush" Value="#FF00BFFF"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </ToggleButton.Template> <DockPanel LastChildFill="False"> <TextBlock Text="{Binding SelectedItem, RelativeSource={RelativeSource TemplatedParent}}" DockPanel.Dock="Left" VerticalAlignment="Center" Foreground="#EEEEEE" Margin="5,0,5,0"/> <Path x:Name="ComboArrow" DockPanel.Dock="Right" Data="M0 0 L5 2.5 L10 0 Z" Width="10" Height="5" Margin="5,0,5,0" Stretch="Fill" VerticalAlignment="Center"> <Path.Fill><SolidColorBrush Color="#EEEEEE"/></Path.Fill> </Path> </DockPanel> </ToggleButton> <Popup IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Bottom" AllowsTransparency="True" Focusable="False" PopupAnimation="Slide" Width="150"> <Border Name="DropDownBorder" BorderBrush="#CCCCCC" BorderThickness="0.80" Background="#444444"> <ScrollViewer MaxHeight="150" VerticalScrollBarVisibility="Auto"> <StackPanel IsItemsHost="True"> <StackPanel.Resources> <Style TargetType="{x:Type ComboBoxItem}"> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="Background" Value="#444444"/> <Setter Property="HorizontalContentAlignment" Value="Left"/> <Style.Triggers> <Trigger Property="IsHighlighted" Value="True"> <Setter Property="Background" Value="#555555"/> </Trigger> <Trigger Property="IsSelected" Value="True"> <Setter Property="Background" Value="#555555"/> </Trigger> </Style.Triggers> </Style> </StackPanel.Resources> </StackPanel> </ScrollViewer> </Border> </Popup> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="ToggleButton" Property="BorderBrush" Value="#EEEEEE"/> </Trigger> <Trigger Property="IsDropDownOpen" Value="True"> <Setter TargetName="DropDownBorder" Property="BorderBrush" Value="#FF00BFFF"/> <Setter TargetName="ToggleButton" Property="BorderBrush" Value="#EEEEEE"/> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter TargetName="ComboArrow" Property="Fill" Value="#888888"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="NetMonListViewStyle" TargetType="{x:Type ListView}"> <Setter Property="Background" Value="#333333"/> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="FontWeight" Value="Normal"/> <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/> <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden"/> <Setter Property="ScrollViewer.CanContentScroll" Value="False"/> <Setter Property="AlternationCount" Value="2"/> <Setter Property="ItemContainerStyle"> <Setter.Value> <Style TargetType="{x:Type ListViewItem}"> <Setter Property="Background" Value="Transparent"/> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="BorderBrush" Value="Transparent"/> <Setter Property="BorderThickness" Value="0.70"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListViewItem}"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"> <GridViewRowPresenter HorizontalAlignment="Stretch" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Width="Auto" Margin="0" Content="{TemplateBinding Content}"/> </Border> <ControlTemplate.Triggers> <Trigger Property="ItemsControl.AlternationIndex" Value="0"> <Setter Property="Background" Value="#111111"/> </Trigger> <Trigger Property="ItemsControl.AlternationIndex" Value="1"> <Setter Property="Background" Value="#000000"/> </Trigger> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="#4000B7FF"/> <Setter Property="BorderBrush" Value="#FF00BFFF"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsSelected" Value="true"/> <Condition Property="Selector.IsSelectionActive" Value="true"/> </MultiTrigger.Conditions> <Setter Property="Background" Value="#4000B7FF"/> <Setter Property="FontWeight" Value="Bold"/> <Setter Property="BorderBrush" Value="#FF00BFFF"/> </MultiTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </Setter.Value> </Setter> </Style> <Style x:Key="NetMonColumnHeaderStyle" TargetType="{x:Type GridViewColumnHeader}"> <Setter Property="Template" Value="{StaticResource NoMouseOverColumnHeaderTemplate}" /> <Setter Property="Background" Value="#CCCCCC" /> <Setter Property="Foreground" Value="Black" /> <Setter Property="BorderBrush" Value="#333333" /> <Setter Property="BorderThickness" Value="0,0,2,0" /> <Setter Property="Cursor" Value="Arrow" /> <Setter Property="FontWeight" Value="Bold"/> <Setter Property="IsHitTestVisible" Value="False" /> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="#CCCCCC" /> <Setter Property="Foreground" Value="Black" /> <Setter Property="BorderBrush" Value="#333333" /> </Trigger> </Style.Triggers> </Style> <ContextMenu x:Key="NetMonRightClickContextMenu" Style="{StaticResource CustomContextMenuStyle}"> <MenuItem Header=" Export " Name="NetMonExportContext" Style="{StaticResource MainMenuItemStyle}"> <MenuItem Header=" HTML " Name="NetMonExportToHTML" Style="{StaticResource CustomMenuItemStyle}"/> <MenuItem Header=" CSV " Name="NetMonExportToCSV" Style="{StaticResource CustomMenuItemStyle}"/> <MenuItem Header=" Text " Name="NetMonExportToText" Style="{StaticResource CustomMenuItemStyle}"/> </MenuItem> </ContextMenu> <ContextMenu x:Key="NetMonDoubleClickContextMenu" Style="{StaticResource CustomContextMenuStyle}"> <MenuItem Header=" Copy " Style="{StaticResource MainMenuItemStyle}"> <MenuItem Header=" Local Address " Name="CopyLocalAddress" Style="{StaticResource CustomMenuItemStyle}"/> <MenuItem Header=" Local Port " Name="CopyLocalPort" Style="{StaticResource CustomMenuItemStyle}"/> <MenuItem Header=" Remote Address " Name="CopyRemoteAddress" Style="{StaticResource CustomMenuItemStyle}"/> <MenuItem Header=" Remote Port " Name="CopyRemotePort" Style="{StaticResource CustomMenuItemStyle}"/> <MenuItem Header=" Process Name " Name="CopyProcessName" Style="{StaticResource CustomMenuItemStyle}"/> <Separator Background="#222222"/> <MenuItem Header=" All " Name="CopyAll" Style="{StaticResource CustomMenuItemStyle}"/> </MenuItem> </ContextMenu> </Window.Resources> <Border Background="#222222" CornerRadius="5,5,5,5"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="30"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Border Background="#DDDDDD" Grid.Row="0" CornerRadius="5,5,0,0"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Image Name="WindowIconImage" Width="24" Height="24" VerticalAlignment="Center" Margin="8,0,8,0"> <Image.Effect> <DropShadowEffect BlurRadius="5" ShadowDepth="1" Opacity="0.8" Direction="270" Color="Black"/> </Image.Effect> </Image> <TextBlock Name="TitleBar" Foreground="Black" FontWeight="Bold" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="0,0,5,0" Grid.Column="1"/> <Grid Grid.Column="2"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <TextBlock Name="externalIPt" Foreground="Black" FontWeight="Bold" VerticalAlignment="Center" Margin="0,0,5,0"/> <TextBlock Name="domainName" Foreground="Black" FontWeight="Bold" VerticalAlignment="Center" Margin="0,0,5,0" Grid.Column="1"/> </Grid> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Column="3"> <Button Name="ToggleMonitorButton" Background="Transparent" BorderThickness="0" ToolTip="Monitor Mode" Template="{StaticResource NoMouseOverButtonTemplate}"> <Button.Effect> <DropShadowEffect BlurRadius="4" ShadowDepth="1" Opacity="0.7" Direction="270" Color="Black"/> </Button.Effect> <Button.Resources> <Storyboard x:Key="mouseEnterAnimation"> <DoubleAnimation Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" To="-1" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.ShadowDepth" To="3" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.BlurRadius" To="3" Duration="0:0:0.2"/> </Storyboard> <Storyboard x:Key="mouseLeaveAnimation"> <DoubleAnimation Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" To="0" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.ShadowDepth" To="1" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.BlurRadius" To="4" Duration="0:0:0.2"/> </Storyboard> </Button.Resources> <Button.RenderTransform> <TranslateTransform/> </Button.RenderTransform> <Viewbox Width="35" Height="24"> <Canvas Width="35" Height="24"> <Canvas Name="HideGraphic" Width="35" Height="24" Visibility="Hidden" IsHitTestVisible="False"> <Path Canvas.Left="0" Canvas.Top="0"> <Path.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <GradientStop Color="#FF66D9FF" Offset="0"/> <GradientStop Color="#FF00BFFF" Offset="0.5"/> <GradientStop Color="#FF0077CC" Offset="1"/> </LinearGradientBrush> </Path.Fill> <Path.Data> M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5A6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z </Path.Data> </Path> </Canvas> <Canvas Name="ShowGraphic" Width="35" Height="24" Visibility="Visible" IsHitTestVisible="False"> <Path Canvas.Left="0" Canvas.Top="0"> <Path.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <GradientStop Color="#FFCC66CC" Offset="0"/> <GradientStop Color="#FF800080" Offset="0.5"/> <GradientStop Color="#FF400040" Offset="1"/> </LinearGradientBrush> </Path.Fill> <Path.Data> M3,13H5.79L10.1,4.79L11.28,13.75L14.5,9.66L17.83,13H21V15H17L14.67,12.67L9.92,18.73L8.94,11.31L7,15H3V13Z </Path.Data> </Path> </Canvas> </Canvas> </Viewbox> </Button> <Button Name="btnMinimize" Width="40" Height="30" Background="Transparent" Foreground="Black" BorderThickness="0" Template="{StaticResource NoMouseOverButtonTemplate}"> <Path Width="15" Height="2" Stretch="Fill" Stroke="Black" StrokeThickness="1" Data="M0,0 L15,0" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Button> <Button Name="btnClose" Content="X" Width="40" Height="30" Background="Transparent" Foreground="Black" FontWeight="Bold" BorderThickness="0" Template="{StaticResource CloseButtonTemplate}"/> </StackPanel> </Grid> </Border> <Grid Grid.Row="1"> <Grid Name="IPScannerContentGrid" Margin="0,0,50,0"> <Grid Name="ScanContainer" Grid.Column="0" VerticalAlignment="Top" HorizontalAlignment="Center" Width="777" MinHeight="25" Margin="53,11,0,0"> <Button Name="Scan" Width="777" Height="30" Background="#777777" Foreground="#000000" FontWeight="Bold" Template="{StaticResource NoMouseOverButtonTemplate}"> <Button.ContextMenu> <ContextMenu Style="{StaticResource CustomContextMenuStyle}"> <MenuItem Header="Subnet" Style="{StaticResource MainMenuItemStyle}" Name="ChangeSubnet"/> </ContextMenu> </Button.ContextMenu> <Button.Content> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock Name="ScanButtonText" Text="Scan" Foreground="#000000" FontWeight="Bold" /> <Image Name="scanAdminIcon" Width="16" Height="16" Margin="5,0,0,0" Visibility="Collapsed"/> </StackPanel> </Button.Content> <Button.BorderBrush> <SolidColorBrush x:Name="CycleBrush" Color="White"/> </Button.BorderBrush> </Button> <ProgressBar Name="Progress" Foreground="#FF00BFFF" Background="#777777" Value="0" Maximum="100" Width="777" Height="30" Visibility="Collapsed"/> <TextBlock Name="BarText" Foreground="#000000" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Grid> <ListView Name="listView" Background="#333333" FontWeight="Normal" HorizontalAlignment="Left" Height="400" Margin="19,52,-140,0" VerticalAlignment="Top" Width="860" VerticalContentAlignment="Top" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.CanContentScroll="False" AlternationCount="2"> <ListView.ItemContainerStyle> <Style TargetType="{x:Type ListViewItem}"> <Setter Property="Background" Value="Transparent" /> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="BorderBrush" Value="Transparent"/> <Setter Property="BorderThickness" Value="0.70"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListViewItem}"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"> <GridViewRowPresenter HorizontalAlignment="Stretch" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Width="Auto" Margin="0" Content="{TemplateBinding Content}"/> </Border> <ControlTemplate.Triggers> <Trigger Property="ItemsControl.AlternationIndex" Value="0"> <Setter Property="Background" Value="#111111"/> <Setter Property="Foreground" Value="#EEEEEE"/> </Trigger> <Trigger Property="ItemsControl.AlternationIndex" Value="1"> <Setter Property="Background" Value="#000000"/> <Setter Property="Foreground" Value="#EEEEEE"/> </Trigger> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="#4000B7FF"/> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="BorderBrush" Value="#FF00BFFF"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsSelected" Value="true"/> <Condition Property="Selector.IsSelectionActive" Value="true"/> </MultiTrigger.Conditions> <Setter Property="Background" Value="#4000B7FF"/> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="FontWeight" Value="Bold"/> <Setter Property="BorderBrush" Value="#FF00BFFF"/> </MultiTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </ListView.ItemContainerStyle> <ListView.View> <GridView> <GridViewColumn Header="MAC Address" DisplayMemberBinding="{Binding MACaddress}" Width="150" HeaderContainerStyle="{StaticResource ColumnHeaderStyle}" /> <GridViewColumn Header="Vendor" DisplayMemberBinding="{Binding Vendor}" Width="230" HeaderContainerStyle="{StaticResource ColumnHeaderStyle}" /> <GridViewColumn Header="IP Address" Width="190" HeaderContainerStyle="{StaticResource ColumnHeaderStyle}"> <GridViewColumn.CellTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <ContentControl Content="{Binding PingImage}" Width="16" Height="16" Margin="0,0,10,0"/> <TextBlock Text="{Binding IPaddress}"/> </StackPanel> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> <GridViewColumn Header="Host Name" DisplayMemberBinding="{Binding HostName}" Width="284" HeaderContainerStyle="{StaticResource ColumnHeaderStyle}" /> </GridView> </ListView.View> <ListView.ContextMenu> <ContextMenu Style="{StaticResource CustomContextMenuStyle}"> <MenuItem Header=" Export " Name="ExportContext" Style="{StaticResource MainMenuItemStyle}"> <MenuItem Header=" HTML " Name="ExportToHTML" Style="{StaticResource CustomMenuItemStyle}"/> <MenuItem Header=" CSV " Name="ExportToCSV" Style="{StaticResource CustomMenuItemStyle}"/> <MenuItem Header=" Text " Name="ExportToText" Style="{StaticResource CustomMenuItemStyle}"/> </MenuItem> </ContextMenu> </ListView.ContextMenu> </ListView> <TextBlock Name="TotalListed" Foreground="{x:Static SystemColors.GrayTextBrush}" FontWeight="Normal" FontSize="11" Margin="55,453,0,0" HorizontalAlignment="Center"/> <Canvas Name="PopupCanvas" Background="#222222" Visibility="Hidden" Width="350" Height="240" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="53,40,0,0"> <Border Name="PopupBorder" CornerRadius="5" Width="350" Height="240" BorderThickness="0.70"> <Border.BorderBrush> <SolidColorBrush Color="#CCCCCC"/> </Border.BorderBrush> <Grid Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel Margin="10" Grid.Row="0"> <StackPanel Orientation="Horizontal"> <ContentControl Name="pingStatusImage" Width="12" Height="12" Margin="15,10,10,0"/> <TextBlock Name="pingStatusText" FontSize="14" Foreground="#EEEEEE" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0"/> </StackPanel> </StackPanel> <StackPanel Margin="10" Grid.Row="1"> <TextBlock Name="pHost" FontSize="14" Foreground="#EEEEEE" FontWeight="Bold" Margin="15,0,0,0"/> <StackPanel Orientation="Horizontal"> <TextBlock Name="pIP" FontSize="14" Foreground="#EEEEEE" Margin="15,2,5,2" /> <Button Name="btnPortScan" Width="13" Height="13" ToolTip="Scan Ports" BorderThickness="0" BorderBrush="#FF00BFFF" IsEnabled="True" Background="Transparent" Template="{StaticResource NoMouseOverButtonTemplate}"> <Button.Effect> <DropShadowEffect ShadowDepth="5" BlurRadius="5" Color="Black" Direction="270"/> </Button.Effect> <Button.Resources> <Storyboard x:Key="mouseEnterAnimation"> <DoubleAnimation Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" To="-1" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.ShadowDepth" To="3" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.BlurRadius" To="3" Duration="0:0:0.2"/> </Storyboard> <Storyboard x:Key="mouseLeaveAnimation"> <DoubleAnimation Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" To="0" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.ShadowDepth" To="1.5" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.BlurRadius" To="1.5" Duration="0:0:0.2"/> </Storyboard> </Button.Resources> <Button.RenderTransform> <TranslateTransform/> </Button.RenderTransform> <Viewbox Width="13" Height="13"> <Path> <Path.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <GradientStop Color="#FF66D9FF" Offset="0"/> <GradientStop Color="#FF00BFFF" Offset="0.5"/> <GradientStop Color="#FF0077CC" Offset="1"/> </LinearGradientBrush> </Path.Fill> <Path.Data> M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5A6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z </Path.Data> </Path> </Viewbox> </Button> </StackPanel> <TextBlock Name="pMAC" FontSize="14" Foreground="#EEEEEE" Margin="15,0,0,0" /> <TextBlock Name="pVendor" FontSize="14" Foreground="#EEEEEE" Margin="15,0,0,0" /> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,28,0,0"> <Button Name="btnRDP" Width="40" Height="32" ToolTip="Connect via RDP" BorderThickness="0" BorderBrush="#FF00BFFF" IsEnabled="False" Background="Transparent" Margin="0,0,25,0" Template="{StaticResource NoMouseOverButtonTemplate}"> <Button.Effect> <DropShadowEffect ShadowDepth="5" BlurRadius="5" Color="Black" Direction="270"/> </Button.Effect> <Button.Resources> <Storyboard x:Key="mouseEnterAnimation"> <DoubleAnimation Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" To="-3" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.ShadowDepth" To="10" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.BlurRadius" To="10" Duration="0:0:0.2"/> </Storyboard> <Storyboard x:Key="mouseLeaveAnimation"> <DoubleAnimation Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" To="0" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.ShadowDepth" To="5" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.BlurRadius" To="5" Duration="0:0:0.2"/> </Storyboard> </Button.Resources> <Button.RenderTransform> <TranslateTransform/> </Button.RenderTransform> </Button> <Button Name="btnWebInterface" Width="40" Height="32" ToolTip="Connect via Web Interface" BorderThickness="0" BorderBrush="#FF00BFFF" IsEnabled="False" Background="Transparent" Margin="0,0,25,0" Template="{StaticResource NoMouseOverButtonTemplate}"> <Button.Effect> <DropShadowEffect ShadowDepth="5" BlurRadius="5" Color="Black" Direction="270"/> </Button.Effect> <Button.Resources> <Storyboard x:Key="mouseEnterAnimation"> <DoubleAnimation Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" To="-3" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.ShadowDepth" To="10" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.BlurRadius" To="10" Duration="0:0:0.2"/> </Storyboard> <Storyboard x:Key="mouseLeaveAnimation"> <DoubleAnimation Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" To="0" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.ShadowDepth" To="5" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.BlurRadius" To="5" Duration="0:0:0.2"/> </Storyboard> </Button.Resources> <Button.RenderTransform> <TranslateTransform/> </Button.RenderTransform> </Button> <Button Name="btnShare" Width="40" Height="32" ToolTip="Connect via Share" BorderThickness="0" BorderBrush="#FF00BFFF" IsEnabled="False" Background="Transparent" Template="{StaticResource NoMouseOverButtonTemplate}"> <Button.Effect> <DropShadowEffect ShadowDepth="5" BlurRadius="5" Color="Black" Direction="270"/> </Button.Effect> <Button.Resources> <Storyboard x:Key="mouseEnterAnimation"> <DoubleAnimation Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" To="-3" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.ShadowDepth" To="10" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.BlurRadius" To="10" Duration="0:0:0.2"/> </Storyboard> <Storyboard x:Key="mouseLeaveAnimation"> <DoubleAnimation Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" To="0" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.ShadowDepth" To="5" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.BlurRadius" To="5" Duration="0:0:0.2"/> </Storyboard> </Button.Resources> <Button.RenderTransform> <TranslateTransform/> </Button.RenderTransform> </Button> <Button Name="btnNone" Width="40" Height="32" ToolTip="No Connections Found" BorderThickness="0" BorderBrush="#FF00BFFF" IsEnabled="False" Background="Transparent" Template="{StaticResource NoMouseOverButtonTemplate}"> <Button.Effect> <DropShadowEffect ShadowDepth="5" BlurRadius="5" Color="Black" Direction="270"/> </Button.Effect> <Button.Resources> <Storyboard x:Key="mouseEnterAnimation"> <DoubleAnimation Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" To="-3" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.ShadowDepth" To="10" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.BlurRadius" To="10" Duration="0:0:0.2"/> </Storyboard> <Storyboard x:Key="mouseLeaveAnimation"> <DoubleAnimation Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" To="0" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.ShadowDepth" To="5" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.BlurRadius" To="5" Duration="0:0:0.2"/> </Storyboard> </Button.Resources> <Button.RenderTransform> <TranslateTransform/> </Button.RenderTransform> <Viewbox Width="28" Height="28"> <Path> <Path.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <GradientStop Color="#FF66D9FF" Offset="0"/> <GradientStop Color="#FF00BFFF" Offset="0.5"/> <GradientStop Color="#FF0077CC" Offset="1"/> </LinearGradientBrush> </Path.Fill> <Path.Data> M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M7,13H17V11H7 </Path.Data> </Path> </Viewbox> </Button> </StackPanel> </StackPanel> <Button Name="pCloseButton" Background="#111111" Foreground="#EEEEEE" BorderThickness="0" Content="X" Margin="300,10,10,10" Height="18" Width="22" Template="{StaticResource NoMouseOverButtonTemplate}" Panel.ZIndex="1"/> </Grid> </Border> <Canvas.ContextMenu> <ContextMenu Style="{StaticResource CustomContextMenuStyle}"> <MenuItem Header=" Copy " Style="{StaticResource MainMenuItemStyle}"> <MenuItem Header=" IP Address " Name="PopupContextCopyIP" Style="{StaticResource CustomMenuItemStyle}"/> <MenuItem Header=" Hostname " Name="PopupContextCopyHostname" Style="{StaticResource CustomMenuItemStyle}"/> <MenuItem Header=" MAC Address " Name="PopupContextCopyMAC" Style="{StaticResource CustomMenuItemStyle}"/> <MenuItem Header=" Vendor " Name="PopupContextCopyVendor" Style="{StaticResource CustomMenuItemStyle}"/> <Separator Background="#222222"/> <MenuItem Header=" All " Name="PopupContextCopyAll" Style="{StaticResource CustomMenuItemStyle}"/> </MenuItem> </ContextMenu> </Canvas.ContextMenu> </Canvas> </Grid> <Grid Name="NetMonContentGrid" Margin="10,10,10,0" Visibility="Hidden" Panel.ZIndex="1"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="280"/> </Grid.RowDefinitions> <ComboBox Name="AdapterDropdown" Grid.Row="0" HorizontalAlignment="Left" Width="150" Margin="17,3,0,0" Style="{StaticResource NetMonComboBoxStyle}"/> <StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,3,10,0"> <StackPanel Orientation="Horizontal" Margin="5"> <TextBlock Text="Connection / Performance Monitor" Foreground="#FFFFFFFF" FontSize="12" FontWeight="Bold" Margin="10,0,0,0" HorizontalAlignment="Center"/> </StackPanel> </StackPanel> <StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,3,10,0"> <StackPanel Orientation="Horizontal" Margin="5"> <Rectangle Width="20" Height="2" Fill="#FF00BFFF" Margin="0,0,5,0"/> <TextBlock Text="Download" Foreground="#FFFFFFFF" FontSize="12"/> </StackPanel> <StackPanel Orientation="Horizontal" Margin="5"> <Rectangle Width="20" Height="2" Fill="#FFB200B2" Margin="0,0,5,0"/> <TextBlock Text="Upload" Foreground="#FFFFFFFF" FontSize="12"/> </StackPanel> </StackPanel> <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="30"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="100"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <TextBlock Name="YAxisTitle" Grid.Column="0" Grid.Row="0" Text="Speed" Foreground="#FFFFFFFF" FontSize="12" Margin="-3,73,0,0"> <TextBlock.RenderTransform> <RotateTransform Angle="-90"/> </TextBlock.RenderTransform> </TextBlock> <Canvas Name="GraphCanvas" Grid.Column="1" Grid.Row="0" Width="830" Height="100" Background="#FF252526" ClipToBounds="True" Margin="-29,13,0,0"> <TextBlock Name="YLabelMax" Canvas.Left="5" Canvas.Top="0" Foreground="#FFFFFFFF" FontSize="10"/> <TextBlock Name="YLabel75" Canvas.Left="5" Canvas.Top="25" Foreground="#FFFFFFFF" FontSize="10"/> <TextBlock Name="YLabel50" Canvas.Left="5" Canvas.Top="50" Foreground="#FFFFFFFF" FontSize="10"/> <TextBlock Name="YLabel25" Canvas.Left="5" Canvas.Top="75" Foreground="#FFFFFFFF" FontSize="10"/> </Canvas> <TextBlock Name="XAxisTitle" Grid.Column="1" Grid.Row="1" Text="Time (60s)" Foreground="#FFFFFFFF" FontSize="12" Margin="382,13,0,0"/> </Grid> <ListView Name="NetMonTCPList" Grid.Row="2" Margin="9,-19,11,18" Style="{StaticResource NetMonListViewStyle}"> <ListView.View> <GridView> <GridViewColumn Header="Local Address" DisplayMemberBinding="{Binding LocalAddress}" Width="120" HeaderContainerStyle="{StaticResource NetMonColumnHeaderStyle}"/> <GridViewColumn Header="Local Port" DisplayMemberBinding="{Binding LocalPort}" Width="120" HeaderContainerStyle="{StaticResource NetMonColumnHeaderStyle}"/> <GridViewColumn Header="Remote Address" DisplayMemberBinding="{Binding RemoteAddress}" Width="120" HeaderContainerStyle="{StaticResource NetMonColumnHeaderStyle}"/> <GridViewColumn Header="Remote Port" DisplayMemberBinding="{Binding RemotePort}" Width="120" HeaderContainerStyle="{StaticResource NetMonColumnHeaderStyle}"/> <GridViewColumn Header="Process" DisplayMemberBinding="{Binding ProcessName}" Width="375" HeaderContainerStyle="{StaticResource NetMonColumnHeaderStyle}"/> </GridView> </ListView.View> </ListView> <TextBlock Name="NetMonTotalConnections" Foreground="{x:Static SystemColors.GrayTextBrush}" FontWeight="Normal" FontSize="11" Margin="0,263,0,0" HorizontalAlignment="Center" Grid.Row="2"/> </Grid> <Canvas Name="PopupCanvas2" Background="#222222" Visibility="Hidden" Width="330" Height="220" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,40,0,0" Panel.ZIndex="10"> <Border Name="PopupBorder2" Width="330" Height="220" BorderThickness="0.70" CornerRadius="5" Background="#222222" Opacity="0.95"> <Border.BorderBrush> <SolidColorBrush Color="#CCCCCC"/> </Border.BorderBrush> <Border.RenderTransform> <TransformGroup> <ScaleTransform/> <SkewTransform/> <RotateTransform/> <TranslateTransform/> </TransformGroup> </Border.RenderTransform> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,15,0,0" Visibility="Visible"> <Path Name="subnetIcon" Grid.Row="0" Width="24" Height="24" Margin="0,-2,6,0" Visibility="Collapsed"> <Path.Effect> <DropShadowEffect ShadowDepth="5" BlurRadius="5" Color="Black" Direction="270"/> </Path.Effect> <Path.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <GradientStop Color="#FF66D9FF" Offset="0"/> <GradientStop Color="#FF00BFFF" Offset="0.5"/> <GradientStop Color="#FF0077CC" Offset="1"/> </LinearGradientBrush> </Path.Fill> <Path.Data> M10,2C8.89,2 8,2.89 8,4V7C8,8.11 8.89,9 10,9H11V11H2V13H6V15H5C3.89,15 3,15.89 3,17V20C3,21.11 3.89,22 5,22H9C10.11,22 11,21.11 11,20V17C11,15.89 10.11,15 9,15H8V13H16V15H15C13.89,15 13,15.89 13,17V20C13,21.11 13.89,22 15,22H19C20.11,22 21,21.11 21,20V17C21,15.89 20.11,15 19,15H18V13H22V11H13V9H14C15.11,9 16,8.11 16,7V4C16,2.89 15.11,2 14,2H10M10,4H14V7H10V4M5,17H9V20H5V17M15,17H19V20H15V17Z </Path.Data> </Path> <Path Name="imgPortScan" Grid.Row="0" Width="24" Height="24" Margin="0,-1,5,0" Visibility="Collapsed"> <Path.Effect> <DropShadowEffect ShadowDepth="5" BlurRadius="5" Color="Black" Direction="270"/> </Path.Effect> <Path.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <GradientStop Color="#FF66D9FF" Offset="0"/> <GradientStop Color="#FF00BFFF" Offset="0.5"/> <GradientStop Color="#FF0077CC" Offset="1"/> </LinearGradientBrush> </Path.Fill> <Path.Data> M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5A6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z </Path.Data> </Path> <TextBlock Name="PopupTitle2" HorizontalAlignment="Center" FontSize="14" Foreground="#EEEEEE" FontWeight="Bold"/> </StackPanel> <TextBlock Name="PopupText2" TextWrapping="Wrap" Margin="10,45,10,0" FontSize="14" Foreground="#EEEEEE" FontWeight="Bold" VerticalAlignment="Top" HorizontalAlignment="Center" Grid.Row="1" Visibility="Collapsed"/> <StackPanel Name="SubnetInput" Grid.Row="1" Margin="10,55,10,0" Visibility="Collapsed"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <TextBlock Text="Subnet" FontSize="14" Foreground="#EEEEEE" Margin="-7,2,5,5"/> <ComboBox Name="subnetOctet1" Style="{StaticResource CustomComboBoxStyle}"/> <ComboBox Name="subnetOctet2" Style="{StaticResource CustomComboBoxStyle}"/> <ComboBox Name="subnetOctet3" Style="{StaticResource CustomComboBoxStyle}"/> <TextBlock Text="1-254" FontSize="14" Foreground="#EEEEEE" Margin="0,2,0,0"/> </StackPanel> <Button Name="btnReset" Width="24" Height="24" ToolTip="Reset Subnet" Margin="0,12,0,0" BorderThickness="0" BorderBrush="#FF00BFFF" IsEnabled="True" Background="Transparent" Template="{StaticResource NoMouseOverButtonTemplate}"> <Button.Effect> <DropShadowEffect ShadowDepth="5" BlurRadius="5" Color="Black" Direction="270"/> </Button.Effect> <Button.Resources> <Storyboard x:Key="mouseEnterAnimation"> <DoubleAnimation Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" To="-2" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.ShadowDepth" To="6" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.BlurRadius" To="6" Duration="0:0:0.2"/> </Storyboard> <Storyboard x:Key="mouseLeaveAnimation"> <DoubleAnimation Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" To="0" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.ShadowDepth" To="3" Duration="0:0:0.2"/> <DoubleAnimation Storyboard.TargetProperty="Effect.BlurRadius" To="3" Duration="0:0:0.2"/> </Storyboard> </Button.Resources> <Button.RenderTransform> <TranslateTransform/> </Button.RenderTransform> <Viewbox Width="19" Height="19"> <Path> <Path.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <GradientStop Color="#FF66D9FF" Offset="0"/> <GradientStop Color="#FF00BFFF" Offset="0.5"/> <GradientStop Color="#FF0077CC" Offset="1"/> </LinearGradientBrush> </Path.Fill> <Path.Data> M19,8L15,12H18A6,6 0 0,1 12,18C11,18 10.03,17.75 9.2,17.3L7.74,18.76C8.97,19.54 10.43,20 12,20A8,8 0 0,0 20,12H23M6,12A6,6 0 0,1 12,6C13,6 13.97,6.25 14.8,6.7L16.26,5.24C15.03,4.46 13.57,4 12,4A8,8 0 0,0 4,12H1L5,16L9,12 </Path.Data> </Path> </Viewbox> </Button> </StackPanel> <StackPanel Orientation="Horizontal" Grid.Row="1" Margin="10,5,10,5" HorizontalAlignment="Center" Visibility="Collapsed" Name="ScanPanel"> <Button Name="btnScan" Background="#777777" Width="200" Height="25" Margin="0,5,5,0" Template="{StaticResource NoMouseOverButtonTemplate}"> <Button.Content> <TextBlock Name="btnScanText" FontWeight="Bold" HorizontalAlignment="Center"/> </Button.Content> <Button.BorderBrush> <SolidColorBrush x:Name="CycleBrush2" Color="White"/> </Button.BorderBrush> </Button> <Grid> <ProgressBar Name="ProgressBar" Foreground="#FF00BFFF" Background="#777777" Width="200" Height="25" Value="0" Minimum="0" Maximum="100" HorizontalAlignment="Left" Margin="0,5,5,0" Visibility="Collapsed"/> <TextBlock Name="ProgressText" Foreground="#000000" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" Margin="0,5,0,0"/> </Grid> <ComboBox Name="cmbPortRange" Width="98" Height="25" Margin="5,5,0,0" Style="{StaticResource CustomComboBoxStyle2}"/> </StackPanel> <ListBox Name="ResultsList" Grid.Row="2" Margin="10,10,10,10" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="#333333" Foreground="#EEEEEE" Visibility="Collapsed"> <ListBox.ItemContainerStyle> <Style TargetType="{x:Type ListBoxItem}"> <Setter Property="Background" Value="Transparent" /> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="BorderBrush" Value="Transparent"/> <Setter Property="BorderThickness" Value="0.70"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBoxItem}"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"> <ContentPresenter HorizontalAlignment="Stretch" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Content="{TemplateBinding Content}"/> </Border> <ControlTemplate.Triggers> <Trigger Property="ItemsControl.AlternationIndex" Value="0"> <Setter Property="Background" Value="#111111"/> <Setter Property="Foreground" Value="#EEEEEE"/> </Trigger> <Trigger Property="ItemsControl.AlternationIndex" Value="1"> <Setter Property="Background" Value="#000000"/> <Setter Property="Foreground" Value="#EEEEEE"/> </Trigger> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="#4000B7FF"/> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="BorderBrush" Value="#FF00BFFF"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsSelected" Value="true"/> <Condition Property="Selector.IsSelectionActive" Value="true"/> </MultiTrigger.Conditions> <Setter Property="Background" Value="#4000B7FF"/> <Setter Property="Foreground" Value="#EEEEEE"/> <Setter Property="FontWeight" Value="Bold"/> <Setter Property="BorderBrush" Value="#FF00BFFF"/> </MultiTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </ListBox.ItemContainerStyle> <ListBox.AlternationCount>2</ListBox.AlternationCount> </ListBox> <Button Name="pCloseButton2" Content="X" Background="#111111" Foreground="#EEEEEE" BorderThickness="0" HorizontalAlignment="Right" Margin="0,5,9,5" Height="18" Width="22" Grid.Row="0" Template="{StaticResource NoMouseOverButtonTemplate}"/> <StackPanel Name="ButtonStackPanel2" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="3" Margin="0,10,0,10"> <Button Name="btnOK2" Content="OK" Margin="5,10,5,10" Background="#111111" Foreground="#EEEEEE" Width="75" Height="25" Template="{StaticResource NoMouseOverButtonTemplate}"/> </StackPanel> </Grid> </Border> </Canvas> </Grid> </Grid> </Border> <Window.Triggers> <EventTrigger RoutedEvent="Window.Loaded"> <BeginStoryboard> <Storyboard> <ColorAnimationUsingKeyFrames Storyboard.TargetName="CycleBrush" Storyboard.TargetProperty="Color" RepeatBehavior="Forever" Duration="0:0:6"> <LinearColorKeyFrame Value="#CCCCCC" KeyTime="0:0:0"/> <LinearColorKeyFrame Value="#FF00BFFF" KeyTime="0:0:3"/> <LinearColorKeyFrame Value="#CCCCCC" KeyTime="0:0:6"/> </ColorAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetName="CycleBrush2" Storyboard.TargetProperty="Color" RepeatBehavior="Forever" Duration="0:0:6"> <LinearColorKeyFrame Value="#CCCCCC" KeyTime="0:0:0"/> <LinearColorKeyFrame Value="#FF00BFFF" KeyTime="0:0:3"/> <LinearColorKeyFrame Value="#CCCCCC" KeyTime="0:0:6"/> </ColorAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetName="PopupBorder" Storyboard.TargetProperty="BorderBrush.Color" RepeatBehavior="Forever" Duration="0:0:6"> <LinearColorKeyFrame Value="#CCCCCC" KeyTime="0:0:0"/> <LinearColorKeyFrame Value="#FF00BFFF" KeyTime="0:0:3"/> <LinearColorKeyFrame Value="#CCCCCC" KeyTime="0:0:6"/> </ColorAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetName="PopupBorder2" Storyboard.TargetProperty="BorderBrush.Color" RepeatBehavior="Forever" Duration="0:0:6"> <LinearColorKeyFrame Value="#CCCCCC" KeyTime="0:0:0"/> <LinearColorKeyFrame Value="#FF00BFFF" KeyTime="0:0:3"/> <LinearColorKeyFrame Value="#CCCCCC" KeyTime="0:0:6"/> </ColorAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> </Window.Triggers> <Window.TaskbarItemInfo> <TaskbarItemInfo/> </Window.TaskbarItemInfo> </Window> '@ # Load XAML $reader = (New-Object System.Xml.XmlNodeReader $xaml) try{$Main = [Windows.Markup.XamlReader]::Load( $reader )} catch{$shell = New-Object -ComObject Wscript.Shell; $shell.Popup("$_",0,'XAML ERROR:',0x0) | Out-Null; Exit} # Store Form Objects In PowerShell $xaml.SelectNodes("//*[@Name]") | %{Set-Variable -Name "$($_.Name)" -Value $Main.FindName($_.Name)} # Set Title $Main.Title = "$AppId" $titleBar.Text = "$AppId" # Window Closing $Main.Add_Closing({ if ($global:timer) { try { $global:timer.Stop() } catch { Write-Host "Error stopping timer: $_" } } if ($Runspace) { try { $global:Runspace.EndInvoke($global:netMonHandle) $global:Runspace.Dispose() } catch { Write-Host "Error disposing netMonHandle: $_" } } Get-Job | Remove-Job -Force if ($RunspacePool) { try { $RunspacePool.Close(); $RunspacePool.Dispose() } catch { Write-Host "Error disposing RunspacePool: $_" } } $Main.Add_Closed({ [Environment]::Exit(0) }) }) $Main.Add_ContentRendered({ # Define icons $icons = @( @{File = 'C:\Windows\System32\imageres.dll'; Index = 73; ElementName = "scanAdminIcon"; Type = "Image"}, @{File = 'C:\Windows\System32\mstscax.dll'; Index = 0; ElementName = "btnRDP"; Type = "Button"}, @{File = 'C:\Windows\System32\shell32.dll'; Index = 13; ElementName = "btnWebInterface"; Type = "Button"}, @{File = 'C:\Windows\System32\shell32.dll'; Index = 266; ElementName = "btnShare"; Type = "Button"} ) # Extract and set icons foreach ($icon in $icons) { $extractedIcon = [System.IconExtractor]::Extract($icon.File, $icon.Index, $true) if ($extractedIcon) { $bitmapSource = [System.IconExtractor]::IconToBitmapSource($extractedIcon) $element = $Main.FindName($icon.ElementName) switch ($icon.Type) { "Image" { $element.Source = $bitmapSource $element.SetValue([System.Windows.Media.RenderOptions]::BitmapScalingModeProperty, [System.Windows.Media.BitmapScalingMode]::HighQuality) } "Button" { $imageWidth = 24 $imageHeight = 24 $image = New-Object System.Windows.Controls.Image -Property @{ Source = $bitmapSource; Width = $imageWidth; Height = $imageHeight; Stretch = [System.Windows.Media.Stretch]::Fill } $image.SetValue([System.Windows.Media.RenderOptions]::BitmapScalingModeProperty, [System.Windows.Media.BitmapScalingMode]::HighQuality) $element.Content = $image } } } } # Populate the ComboBoxes function Initialize-IPCombo { param($comboBox) for ($i = 0; $i -le 255; $i++) { $comboBox.Items.Add($i) } $comboBox.SelectedIndex = 0 } # Initialize Comboboxes @('subnetOctet1', 'subnetOctet2', 'subnetOctet3') | ForEach-Object { Initialize-IPCombo -comboBox ($Main.FindName($_)) } # Register ToggleMonitorButton mouse event handlers $ToggleMonitorButton.Add_MouseEnter({ $storyboard = $ToggleMonitorButton.Resources["mouseEnterAnimation"] $storyboard.Begin($ToggleMonitorButton) }) $ToggleMonitorButton.Add_MouseLeave({ $storyboard = $ToggleMonitorButton.Resources["mouseLeaveAnimation"] $storyboard.Begin($ToggleMonitorButton) }) # Initialize Monitor Mode Variables $global:adapters = @() $global:adapterStats = @{} $global:speedHistory = @{} $global:lastTime = $null $global:canvasWidth = 830 $global:canvasHeight = 100 $global:maxPoints = 60 $global:historySize = 2 $global:resetThreshold = 100000 $global:maxSpeed = 1000 $global:LastSelectedItem = $null # Start Monitor Mode Background Task try { if (-not $RunspacePool) { Show-Popup2 -Message "RunspacePool is not initialized." -Title "Error:" return } if ($RunspacePool.RunspacePoolStateInfo.State -ne 'Opened') { Show-Popup2 -Message "RunspacePool is not open." -Title "Error:" return } $global:netMonHandle = Start-NetMonBackgroundTask } catch { Show-Popup2 -Message "Failed to start Monitor Mode background task: $_" -Title "Error:" return } # Initialize Adapters try { $initialAdapters = Get-NetAdapter | Where-Object { $_.Status -eq "Up" -and $_.InterfaceDescription -notlike "*Loopback*" -and $_.InterfaceDescription -notlike "*ISATAP*" } if (-not $initialAdapters) { Show-Popup2 -Message "No network adapters available." -Title "Error:" return } foreach ($adapter in $initialAdapters) { $adapterName = $adapter.Name $global:adapters += $adapterName $global:adapterStats[$adapterName] = @{ RxHistory = @() TxHistory = @() TimeHistory = @() LastRxBytes = 0 LastTxBytes = 0 } $global:speedHistory[$adapterName] = @{ RxSpeeds = @() TxSpeeds = @() } if ($AdapterDropdown) { $AdapterDropdown.Items.Add($adapterName) | Out-Null } } if ($AdapterDropdown -and $AdapterDropdown.Items.Count -gt 0) { $AdapterDropdown.SelectedIndex = 0 } } catch { Show-Popup2 -Message "Error initializing adapters: $_" -Title "Error:" } # Initialize Timer $global:timer = New-Object System.Windows.Threading.DispatcherTimer $global:timer.Interval = [TimeSpan]::FromMilliseconds(1000) $global:timer.Add_Tick({ try { if ($global:syncHash.Error) { if ($NetMonContentGrid -and $NetMonContentGrid.Visibility -eq [System.Windows.Visibility]::Visible) { Show-Popup2 -Message "Background task error: $($global:syncHash.Error)" -Title "Error:" } return } $statsPerAdapter = $global:syncHash.NetworkStats $tcpConnections = $global:syncHash.TCPConnections $currentTime = [DateTime]::Now if ($null -eq $global:lastTime) { $global:lastTime = $currentTime } $deltaTime = [Math]::Max(0.2, ($currentTime - $global:lastTime).TotalSeconds) $global:lastTime = $currentTime foreach ($adapterName in $global:adapters) { $adapterStat = $global:adapterStats[$adapterName] if ($statsPerAdapter.ContainsKey($adapterName)) { $currentStats = $statsPerAdapter[$adapterName] $rxBytes = $currentStats.RxBytes $txBytes = $currentStats.TxBytes $timestamp = $currentStats.Timestamp if ($adapterStat.LastRxBytes -gt 0 -and $adapterStat.LastTxBytes -gt 0) { $resetRx = $rxBytes -lt $adapterStat.LastRxBytes -and ($adapterStat.LastRxBytes - $rxBytes) -gt $global:resetThreshold $resetTx = $txBytes -lt $adapterStat.LastTxBytes -and ($adapterStat.LastTxBytes - $txBytes) -gt $global:resetThreshold if ($resetRx -or $resetTx) { $adapterStat.RxHistory = @() $adapterStat.TxHistory = @() $adapterStat.TimeHistory = @() $global:speedHistory[$adapterName].RxSpeeds = @() $global:speedHistory[$adapterName].TxSpeeds = @() } } $adapterStat.RxHistory += $rxBytes $adapterStat.TxHistory += $txBytes $adapterStat.TimeHistory += $timestamp if ($adapterStat.RxHistory.Count -gt $global:historySize) { $adapterStat.RxHistory = $adapterStat.RxHistory | Select-Object -Last $global:historySize $adapterStat.TxHistory = $adapterStat.TxHistory | Select-Object -Last $global:historySize $adapterStat.TimeHistory = $adapterStat.TimeHistory | Select-Object -Last $global:historySize } $adapterStat.LastRxBytes = $rxBytes $adapterStat.LastTxBytes = $txBytes $rxSpeed = 0 $txSpeed = 0 if ($adapterStat.RxHistory.Count -ge 2 -and $adapterStat.TimeHistory.Count -ge 2) { $totalRxDiff = 0 $totalTxDiff = 0 $totalTicks = 0 for ($i = 1; $i -lt $adapterStat.RxHistory.Count; $i++) { $rxDiff = [double]($adapterStat.RxHistory[$i] - $adapterStat.RxHistory[$i-1]) $txDiff = [double]($adapterStat.TxHistory[$i] - $adapterStat.TxHistory[$i-1]) $tickDiff = [double]($adapterStat.TimeHistory[$i] - $adapterStat.TimeHistory[$i-1]) $totalRxDiff += $rxDiff $totalTxDiff += $txDiff $totalTicks += $tickDiff } $totalTime = $totalTicks / 10000000.0 if ($totalTime -gt 0) { $rxSpeed = [Math]::Max(0, $totalRxDiff / $totalTime / 1024) $txSpeed = [Math]::Max(0, $totalTxDiff / $totalTime / 1024) } } $global:speedHistory[$adapterName].RxSpeeds += $rxSpeed $global:speedHistory[$adapterName].TxSpeeds += $txSpeed if ($global:speedHistory[$adapterName].RxSpeeds.Count -gt $global:maxPoints) { $global:speedHistory[$adapterName].RxSpeeds = $global:speedHistory[$adapterName].RxSpeeds | Select-Object -Last $global:maxPoints $global:speedHistory[$adapterName].TxSpeeds = $global:speedHistory[$adapterName].TxSpeeds | Select-Object -Last $global:maxPoints } } } if ($NetMonContentGrid -and $NetMonContentGrid.Visibility -eq [System.Windows.Visibility]::Visible) { $Main.Dispatcher.Invoke([Action]{ if (-not $GraphCanvas -or -not $YLabelMax -or -not $YLabel75 -or -not $YLabel50 -or -not $YLabel25 -or -not $NetMonTCPList) { return } $childrenToRemove = $GraphCanvas.Children | Where-Object { $_.GetType().Name -eq "Line" } foreach ($child in $childrenToRemove) { $GraphCanvas.Children.Remove($child) } $selectedAdapter = if ($AdapterDropdown -and $AdapterDropdown.Items.Count -gt 0) { $AdapterDropdown.SelectedItem } else { $global:adapters[0] } if (-not $selectedAdapter) { Show-Popup2 -Message "No adapter selected." -Title "Warning:" return } $rxSpeeds = $global:speedHistory[$selectedAdapter].RxSpeeds $txSpeeds = $global:speedHistory[$selectedAdapter].TxSpeeds $maxRx = if ($rxSpeeds) { ($rxSpeeds | Measure-Object -Maximum).Maximum } else { 0 } $maxTx = if ($txSpeeds) { ($txSpeeds | Measure-Object -Maximum).Maximum } else { 0 } $maxSpeedCalc = [Math]::Max($maxRx, $maxTx) if ($maxSpeedCalc -le 25) { $global:maxSpeed = 25 } elseif ($maxSpeedCalc -le 250) { $global:maxSpeed = 250 } elseif ($maxSpeedCalc -le 500) { $global:maxSpeed = 500 } elseif ($maxSpeedCalc -le 1000) { $global:maxSpeed = 1000 } else { $global:maxSpeed = [Math]::Ceiling($maxSpeedCalc / 250) * 250 } $YLabelMax.Text = Format-Speed -speedInKBs $global:maxSpeed $YLabel75.Text = Format-Speed -speedInKBs ($global:maxSpeed * 0.75) $YLabel50.Text = Format-Speed -speedInKBs ($global:maxSpeed * 0.5) $YLabel25.Text = Format-Speed -speedInKBs ($global:maxSpeed * 0.25) $yScale = $global:canvasHeight / $global:maxSpeed $xScale = $global:canvasWidth / $global:maxPoints for ($i = 1; $i -le 3; $i++) { $gridLine = New-Object System.Windows.Shapes.Line $gridLine.X1 = 0 $gridLine.X2 = $global:canvasWidth $gridLine.Y1 = $i * ($global:canvasHeight / 4) $gridLine.Y2 = $i * ($global:canvasHeight / 4) $gridLine.Stroke = New-Object System.Windows.Media.SolidColorBrush -ArgumentList ([System.Windows.Media.Color]::FromRgb(63, 63, 70)) $gridLine.StrokeThickness = 1 $GraphCanvas.Children.Add($gridLine) } for ($i = 1; $i -lt $rxSpeeds.Count; $i++) { $x1 = $global:canvasWidth - ($rxSpeeds.Count - $i) * $xScale $y1 = $global:canvasHeight - ($rxSpeeds[$i-1] * $yScale) $x2 = $global:canvasWidth - ($rxSpeeds.Count - 1 - $i) * $xScale $y2 = $global:canvasHeight - ($rxSpeeds[$i] * $yScale) $line = New-Object System.Windows.Shapes.Line $line.X1 = $x1; $line.Y1 = $y1; $line.X2 = $x2; $line.Y2 = $y2 $line.Stroke = New-Object System.Windows.Media.SolidColorBrush -ArgumentList ([System.Windows.Media.Color]::FromRgb(0, 191, 255)) $line.StrokeThickness = 2 $GraphCanvas.Children.Add($line) } for ($i = 1; $i -lt $txSpeeds.Count; $i++) { $x1 = $global:canvasWidth - ($txSpeeds.Count - $i) * $xScale $y1 = $global:canvasHeight - ($txSpeeds[$i-1] * $yScale) $x2 = $global:canvasWidth - ($txSpeeds.Count - 1 - $i) * $xScale $y2 = $global:canvasHeight - ($txSpeeds[$i] * $yScale) $line = New-Object System.Windows.Shapes.Line $line.X1 = $x1; $line.Y1 = $y1; $line.X2 = $x2; $line.Y2 = $y2 $line.Stroke = New-Object System.Windows.Media.SolidColorBrush -ArgumentList ([System.Windows.Media.Color]::FromRgb(178, 0, 178)) $line.StrokeThickness = 2 $GraphCanvas.Children.Add($line) } if ($tcpConnections) { $NetMonTCPList.ItemsSource = $tcpConnections $NetMonTotalConnections.Text = "$($tcpConnections.Count) active connections" if ($global:LastSelectedItem) { foreach ($item in $NetMonTCPList.Items) { # Compare key properties to find the matching item if ($item.LocalAddress -eq $global:LastSelectedItem.LocalAddress -and $item.LocalPort -eq $global:LastSelectedItem.LocalPort -and $item.RemoteAddress -eq $global:LastSelectedItem.RemoteAddress -and $item.RemotePort -eq $global:LastSelectedItem.RemotePort -and $item.ProcessName -eq $global:LastSelectedItem.ProcessName) { $NetMonTCPList.SelectedItem = $item break } } } } }, [System.Windows.Threading.DispatcherPriority]::Render) } } catch { if ($NetMonContentGrid -and $NetMonContentGrid.Visibility -eq [System.Windows.Visibility]::Visible) { Show-Popup2 -Message "UI update error: $_" -Title "Error:" } } }) # Start Timer $global:timer.Start() # Toggle Scanner/Monitor Mode button Click Handler $ToggleMonitorButton.Add_Click({ try { if (-not $NetMonContentGrid -or -not $IPScannerContentGrid -or -not $HideGraphic -or -not $ShowGraphic) { Show-Popup2 -Message "UI elements not found." -Title "Error:" return } if ($NetMonContentGrid.Visibility -eq [System.Windows.Visibility]::Visible) { $ToggleMonitorButton.ToolTip = "Monitor Mode" $NetMonContentGrid.Visibility = [System.Windows.Visibility]::Hidden $IPScannerContentGrid.Visibility = [System.Windows.Visibility]::Visible $HideGraphic.Visibility = [System.Windows.Visibility]::Hidden $ShowGraphic.Visibility = [System.Windows.Visibility]::Visible } else { $ToggleMonitorButton.ToolTip = "Scanner Mode" $NetMonContentGrid.Visibility = [System.Windows.Visibility]::Visible $IPScannerContentGrid.Visibility = [System.Windows.Visibility]::Hidden $HideGraphic.Visibility = [System.Windows.Visibility]::Visible $ShowGraphic.Visibility = [System.Windows.Visibility]::Hidden } } catch { Show-Popup2 -Message "Error toggling view: $_" -Title "Error:" } }) # Monitor Mode Context Menu Handlers $contextMenuElements = @('NetMonExportContext', 'CopyLocalAddress', 'CopyLocalPort', 'CopyRemoteAddress', 'CopyRemotePort', 'CopyProcessName', 'CopyAll', 'NetMonExportToHTML', 'NetMonExportToCSV', 'NetMonExportToText') $NetMonTCPList.Add_SelectionChanged({ $NetMonExportContext.IsEnabled = $NetMonTCPList.Items.Count -gt 0 }) $NetMonTCPList.Add_PreviewMouseLeftButtonUp({ param($sender, $e) $originalSource = $e.OriginalSource $listViewItem = $null $currentElement = $originalSource while ($currentElement -ne $null -and $listViewItem -eq $null) { if ($currentElement -is [System.Windows.Controls.ListViewItem]) { $listViewItem = $currentElement } $currentElement = [System.Windows.Media.VisualTreeHelper]::GetParent($currentElement) } if ($listViewItem -ne $null) { $NetMonTCPList.SelectedItems.Clear() $listViewItem.IsSelected = $true $global:LastSelectedItem = $listViewItem.Content } $e.Handled = $true }) $NetMonTCPList.Add_PreviewMouseRightButtonDown({ param($sender, $e) $originalSource = $e.OriginalSource $listViewItem = $null $currentElement = $originalSource while ($currentElement -ne $null -and $listViewItem -eq $null) { if ($currentElement -is [System.Windows.Controls.ListViewItem]) { $listViewItem = $currentElement } $currentElement = [System.Windows.Media.VisualTreeHelper]::GetParent($currentElement) } $NetMonTCPList.SelectedItems.Clear() if ($listViewItem -ne $null) { $listViewItem.IsSelected = $true } $NetMonTCPList.ContextMenu = $Main.FindResource("NetMonRightClickContextMenu") $NetMonTCPList.ContextMenu.IsOpen = $true $e.Handled = $true }) $NetMonTCPList.Add_MouseDoubleClick({ param($sender, $e) $originalSource = $e.OriginalSource $listViewItem = $null $currentElement = $originalSource while ($currentElement -ne $null -and $listViewItem -eq $null) { if ($currentElement -is [System.Windows.Controls.ListViewItem]) { $listViewItem = $currentElement } $currentElement = [System.Windows.Media.VisualTreeHelper]::GetParent($currentElement) } $NetMonTCPList.SelectedItems.Clear() if ($listViewItem -ne $null) { $listViewItem.IsSelected = $true $global:LastSelectedItem = $listViewItem.Content $NetMonTCPList.ContextMenu = $Main.FindResource("NetMonDoubleClickContextMenu") $NetMonTCPList.ContextMenu.IsOpen = $true } $e.Handled = $true }) $CopyLocalAddress.Add_Click({ $item = if ($NetMonTCPList.SelectedItem) { $NetMonTCPList.SelectedItem } else { $global:LastSelectedItem } if ($item) { Set-Clipboard -Value $item.LocalAddress; Show-Popup2 -Message "Local Address copied!" -Title "Info:" } else { Show-Popup2 -Message "No item selected!" -Title "Warning:" } }) $CopyLocalPort.Add_Click({ $item = if ($NetMonTCPList.SelectedItem) { $NetMonTCPList.SelectedItem } else { $global:LastSelectedItem } if ($item) { Set-Clipboard -Value $item.LocalPort; Show-Popup2 -Message "Local Port copied!" -Title "Info:" } else { Show-Popup2 -Message "No item selected!" -Title "Warning:" } }) $CopyRemoteAddress.Add_Click({ $item = if ($NetMonTCPList.SelectedItem) { $NetMonTCPList.SelectedItem } else { $global:LastSelectedItem } if ($item) { Set-Clipboard -Value $item.RemoteAddress; Show-Popup2 -Message "Remote Address copied!" -Title "Info:" } else { Show-Popup2 -Message "No item selected!" -Title "Warning:" } }) $CopyRemotePort.Add_Click({ $item = if ($NetMonTCPList.SelectedItem) { $NetMonTCPList.SelectedItem } else { $global:LastSelectedItem } if ($item) { Set-Clipboard -Value $item.RemotePort; Show-Popup2 -Message "Remote Port copied!" -Title "Info:" } else { Show-Popup2 -Message "No item selected!" -Title "Warning:" } }) $CopyProcessName.Add_Click({ $item = if ($NetMonTCPList.SelectedItem) { $NetMonTCPList.SelectedItem } else { $global:LastSelectedItem } if ($item) { Set-Clipboard -Value $item.ProcessName; Show-Popup2 -Message "Process Name copied!" -Title "Info:" } else { Show-Popup2 -Message "No item selected!" -Title "Warning:" } }) $CopyAll.Add_Click({ $item = if ($NetMonTCPList.SelectedItem) { $NetMonTCPList.SelectedItem } else { $global:LastSelectedItem } if ($item) { $details = "Local Address: $($item.LocalAddress)`nLocal Port: $($item.LocalPort)`nRemote Address: $($item.RemoteAddress)`nRemote Port: $($item.RemotePort)`nProcess Name: $($item.ProcessName)" Set-Clipboard -Value $details Show-Popup2 -Message "All details copied!" -Title "Info:" } else { Show-Popup2 -Message "No item selected!" -Title "Warning:" } }) $NetMonExportToHTML.Add_Click({ if ($NetMonTCPList.Items.Count -eq 0) { Show-Popup2 -Message "No data to export!" -Title "Warning:"; return } $saveFileDialog = New-Object System.Windows.Forms.SaveFileDialog $saveFileDialog.Filter = "HTML files (*.html)|*.html|All files (*.*)|*.*" $saveFileDialog.FileName = "TCP_Connections" if ($saveFileDialog.ShowDialog() -eq "OK") { $path = $saveFileDialog.FileName try { $htmlContent = "<!DOCTYPE html><html><head><title>TCP Connections</title><style>table, th, td { border: 1px solid black; border-collapse: collapse; padding: 5px; } th { background-color: #f2f2f2; } h1, p { margin: 0; padding: 0; } p { margin-bottom: 2px; } .info-block { margin-bottom: 20px; }</style></head><body><h1>TCP Connections</h1><br><div class='info-block'><p><strong>Date/Time:</strong> $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')</p><p><strong>Total Connections:</strong> $($NetMonTCPList.Items.Count)</p></div><table><tr><th>Local Address</th><th>Local Port</th><th>Remote Address</th><th>Remote Port</th><th>Process Name</th></tr>" $NetMonTCPList.Items | ForEach-Object { $htmlContent += "<tr><td>$($_.LocalAddress)</td><td>$($_.LocalPort)</td><td>$($_.RemoteAddress)</td><td>$($_.RemotePort)</td><td>$($_.ProcessName)</td></tr>" } $htmlContent += "</table></body></html>" [System.IO.File]::WriteAllText($path, $htmlContent) Show-Popup2 -Message "Export to HTML completed!" -Title "Export:" } catch { Show-Popup2 -Message "Error during export: $_" -Title "ERROR:" } } }) $NetMonExportToCSV.Add_Click({ if ($NetMonTCPList.Items.Count -eq 0) { Show-Popup2 -Message "No data to export!" -Title "Warning:"; return } $saveFileDialog = New-Object System.Windows.Forms.SaveFileDialog $saveFileDialog.Filter = "CSV files (*.csv)|*.csv|All files (*.*)|*.*" $saveFileDialog.FileName = "TCP_Connections" if ($saveFileDialog.ShowDialog() -eq "OK") { $path = $saveFileDialog.FileName try { $csvHeader = "Local Address,Local Port,Remote Address,Remote Port,Process Name" $csvContent = $NetMonTCPList.Items | ForEach-Object { "`r`n$($_.LocalAddress.Replace(',','')),$($_.LocalPort),$($_.RemoteAddress.Replace(',','')),$($_.RemotePort),$($_.ProcessName.Replace(',',''))" } [System.IO.File]::WriteAllLines($path, ($csvHeader + $csvContent)) Show-Popup2 -Message "Export to CSV completed!" -Title "Export:" } catch { Show-Popup2 -Message "Error during export: $_" -Title "ERROR:" } } }) $NetMonExportToText.Add_Click({ if ($NetMonTCPList.Items.Count -eq 0) { Show-Popup2 -Message "No data to export!" -Title "Warning:"; return } $saveFileDialog = New-Object System.Windows.Forms.SaveFileDialog $saveFileDialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*" $saveFileDialog.FileName = "TCP_Connections" if ($saveFileDialog.ShowDialog() -eq "OK") { $path = $saveFileDialog.FileName try { $textContent = "TCP CONNECTIONS`n`nDATE/TIME: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')`nTOTAL CONNECTIONS: $($NetMonTCPList.Items.Count)`n`n--------------------------------------`n" $textContent += $NetMonTCPList.Items | ForEach-Object { "Local Address: $($_.LocalAddress)`nLocal Port: $($_.LocalPort)`nRemote Address: $($_.RemoteAddress)`nRemote Port: $($_.RemotePort)`nProcess Name: $($_.ProcessName)`n--------------------------------------`n" } [System.IO.File]::WriteAllText($path, $textContent) Show-Popup2 -Message "Export to Text completed!" -Title "Export:" } catch { Show-Popup2 -Message "Error during export: $_" -Title "ERROR:" } } }) # Bring window to foreground $Main.Dispatcher.Invoke([action]{ $Main.Activate() }, [Windows.Threading.DispatcherPriority]::Background) }) # Center main window $screen = [System.Windows.SystemParameters]::WorkArea $windowLeft = ($screen.Width - $Main.Width) / 2 $windowTop = ($screen.Height - $Main.Height) / 2 $Main.Left = $windowLeft $Main.Top = $windowTop $btnMinimize.Add_Click({ $Main.WindowState = [System.Windows.WindowState]::Minimized }) $btnMinimize.Add_MouseEnter({ $btnMinimize.Background='#BBBBBB' }) $btnMinimize.Add_MouseLeave({ $btnMinimize.Background='#DDDDDD' }) $btnClose.Add_Click({ $Main.Close() }) $btnClose.Add_MouseEnter({ $btnClose.Background='#ff0000' }) $btnClose.Add_MouseLeave({ $btnClose.Background='#DDDDDD' }) $Main.Add_MouseLeftButtonDown({ $Main.DragMove() }) $pCloseButton.Add_Click({ $PopupCanvas.Visibility = 'Hidden' }) $pCloseButton.Add_MouseEnter({ $pCloseButton.Background='#ff0000' }) $pCloseButton.Add_MouseLeave({ $pCloseButton.Background='#111111' }) $pCloseButton2.Add_Click({ $PopupCanvas2.Visibility = 'Hidden' if(-not $btnScan.IsEnabled){ $global:abortscan = $true $ProgressText.Visibility = 'Collapsed' $btnScan.Visibility = 'Visible' $ProgressBar.Visibility = 'Collapsed' $ProgressBar.Value = 0 Update-uiMain $btnScan.IsEnabled = $true $Scan.IsEnabled = $true } $global:CtrlIsDown = $false if ($global:gatewayPrefix -ne $originalGatewayPrefix) { $scanButtonText.Text = 'Custom Scan' } else { $scanButtonText.Text = 'Scan' } $scanAdminIcon.Visibility = 'Collapsed' }) $pCloseButton2.Add_MouseEnter({ $pCloseButton2.Background='#ff0000' }) $pCloseButton2.Add_MouseLeave({ $pCloseButton2.Background='#111111' }) function Show-SubnetPopup { $btnOK2.Visibility = 'Visible' $PopupTitle2.Text = 'Segment Exploration' $PopupText2.Visibility = 'Collapsed' $SubnetInput.Visibility = 'Visible' $ScanPanel.Visibility = 'Collapsed' $ResultsList.Visibility = 'Collapsed' $imgPortScan.Visibility = 'Collapsed' $subnetIcon.Visibility = 'Visible' $PopupCanvas2.SetValue([System.Windows.Controls.Canvas]::LeftProperty, [System.Windows.Controls.Canvas]::GetLeft($listView) + 10) $PopupCanvas2.SetValue([System.Windows.Controls.Canvas]::TopProperty, [System.Windows.Controls.Canvas]::GetTop($listView) + 10) $PopupCanvas2.Visibility = 'Visible' } function Show-PortScanPopup { $btnOK2.Visibility = 'Collapsed' $PopupTitle2.Text = "$global:target" $SubnetInput.Visibility = 'Collapsed' $ScanPanel.Visibility = 'Visible' $ResultsList.Visibility = 'Visible' $imgPortScan.Visibility = 'Visible' $subnetIcon.Visibility = 'Collapsed' $PopupCanvas2.SetValue([System.Windows.Controls.Canvas]::LeftProperty, [System.Windows.Controls.Canvas]::GetLeft($listView) + 10) $PopupCanvas2.SetValue([System.Windows.Controls.Canvas]::TopProperty, [System.Windows.Controls.Canvas]::GetTop($listView) + 10) $PopupCanvas2.Visibility = 'Visible' } function Show-Popup2 { param ( [string]$Message, [string]$Title = 'Info', [bool]$IsSubnetPopup = $false ) $SubnetInput.Visibility = 'Collapsed' $ScanPanel.Visibility = 'Collapsed' $ResultsList.Visibility = 'Collapsed' $PopupText2.Visibility = 'Visible' $btnOK2.Visibility = 'Visible' $PopupTitle2.Text = $Title $PopupText2.Text = $Message $centerX = ($Main.ActualWidth - $PopupBorder2.ActualWidth) / 2 $centerY = ($Main.ActualHeight - $PopupBorder2.ActualHeight) / 2 $PopupCanvas2.SetValue([System.Windows.Controls.Canvas]::LeftProperty, [System.Windows.Controls.Canvas]::GetLeft($listView) + 10) $PopupCanvas2.SetValue([System.Windows.Controls.Canvas]::TopProperty, [System.Windows.Controls.Canvas]::GetTop($listView) + 10) $PopupCanvas2.Visibility = 'Visible' } $btnPortScan.Add_Click({ $global:target = $pIP.Text -replace 'IP: ' # Set multi-popup for portscan Show-PortScanPopup $PopupText2.Visibility = 'Collapsed' $SubnetInput.Visibility = 'Collapsed' # Show port scanning elements $btnScan.Visibility = 'Visible' $btnScanText.Text = 'Scan Ports' $ProgressBar.Visibility = 'Collapsed' $ProgressText.Visibility = 'Visible' $ProgressText.Text = '' $cmbPortRange.Visibility = 'Visible' $ResultsList.Visibility = 'Visible' $ResultsList.Items.Clear() $PopupCanvas2.Visibility = 'Visible' $btnOK2.Content = 'OK' $ButtonStackPanel2.Visibility = 'Visible' # Initialize combobox if not already done if ($cmbPortRange.Items.Count -eq 0) { for ($start = 1; $start -le 65535; $start += 4000) { $end = [Math]::Min($start + 3999, 65535) $range = "$start-$end" $cmbPortRange.Items.Add($range) | Out-Null } $cmbPortRange.SelectedIndex = 0 } }) $btnScan.Add_Click({ $btnScan.IsEnabled = $false $Scan.IsEnabled = $false # Check if anything is selected in the ComboBox if ($cmbPortRange.SelectedIndex -ge 0) { $selectedRange = $cmbPortRange.SelectedItem.ToString() $portRange = $selectedRange -split '-' | ForEach-Object {[int]$_} $startPort, $endPort = $portRange $totalPorts = $endPort - $startPort + 1 if($ResultsList.Items){ $ResultsList.Items.Clear() } $openPorts = @() $ProgressText.Text = 'Scanning Ports' $btnScan.Visibility = 'Collapsed' $ProgressBar.Visibility = 'Visible' $ProgressText.Visibility = 'Visible' Update-uiMain for ($port = $startPort; $port -le $endPort; $port++) { $result = Test-Port -computer $global:target -port $port if ($result) { $openPorts += $result $ResultsList.Items.Add($result) } $progress = (($port - $startPort + 1) / $totalPorts) * 100 $ProgressBar.Value = $progress Update-uiMain if($abortscan){ $ResultsList.Items.Clear() Update-uiMain $global:abortscan = $false break } } if ($openPorts.Count -eq 0) { $ResultsList.Items.Add("No open ports found in the specified range.") } $ProgressText.Visibility = 'Collapsed' $btnScan.Visibility = 'Visible' $ProgressBar.Visibility = 'Collapsed' $ProgressBar.Value = 0 Update-uiMain } else { $ResultsList.Items.Add("Please select a port range.") } $btnScan.IsEnabled = $true $Scan.IsEnabled = $true }) # Window Icon $windowIcon = [System.IconExtractor]::Extract('C:\Windows\System32\shell32.dll', 18, $true) if ($windowIcon) { $bitmapSource = [System.IconExtractor]::IconToBitmapSource($windowIcon) $Main.Icon = $bitmapSource $Main.TaskbarItemInfo.Overlay = $bitmapSource $Main.TaskbarItemInfo.Description = $AppId ($Main.FindName('WindowIconImage')).Source = $bitmapSource ($Main.FindName('WindowIconImage')).SetValue([System.Windows.Media.RenderOptions]::BitmapScalingModeProperty, [System.Windows.Media.BitmapScalingMode]::HighQuality) } $ChangeSubnet.Add_Click({ $parts = $global:gatewayPrefix -split '\.' if ($parts.Length -ge 3) { $subnetOctet1.SelectedItem = [int]$parts[0] $subnetOctet2.SelectedItem = [int]$parts[1] $subnetOctet3.SelectedItem = [int]$parts[2] } else { $subnetOctet1.SelectedItem = 192 $subnetOctet2.SelectedItem = 168 $subnetOctet3.SelectedItem = 1 } Show-SubnetPopup }) $btnReset.Add_Click({ if ($originalGatewayPrefix) { $parts = $originalGatewayPrefix -split '\.' if ($parts.Length -ge 3) { $subnetOctet1.SelectedItem = [int]$parts[0] $subnetOctet2.SelectedItem = [int]$parts[1] $subnetOctet3.SelectedItem = [int]$parts[2] $global:gatewayPrefix = $originalGatewayPrefix } } }) $btnOK2.Add_Click({ if ($SubnetInput.Visibility -eq 'Visible') { $global:gatewayPrefix = "{0}.{1}.{2}." -f $subnetOctet1.SelectedItem, $subnetOctet2.SelectedItem, $subnetOctet3.SelectedItem } $global:CtrlIsDown = $false if ($global:gatewayPrefix -ne $originalGatewayPrefix) { $scanButtonText.Text = 'Custom Scan' } else { $scanButtonText.Text = 'Scan' } $scanAdminIcon.Visibility = 'Collapsed' $PopupCanvas2.Visibility = 'Hidden' }) $btnOK2.Add_MouseEnter({ $btnOK2.Foreground='#000000' $btnOK2.Background='#CCCCCC' }) $btnOK2.Add_MouseLeave({ $btnOK2.Foreground='#EEEEEE' $btnOK2.Background='#111111' }) $btnRDP.Add_Click({ &mstsc /v:$tryToConnect }) $btnWebInterface.Add_Click({ # Priority order: HTTP/HTTPS if($script:httpAvailable -eq 1){ Start-Process "`"http://$tryToConnect`"" } else { Start-Process "`"https://$tryToConnect`"" } }) $btnShare.Add_Click({ &explorer "`"\\$tryToConnect`"" }) # Button Animation Triggers $btnRDP.Add_MouseEnter({ $btnRDP.FindResource("mouseEnterAnimation").Begin($btnRDP) }) $btnRDP.Add_MouseLeave({ $btnRDP.FindResource("mouseLeaveAnimation").Begin($btnRDP) }) $btnReset.Add_MouseEnter({ $btnReset.FindResource("mouseEnterAnimation").Begin($btnReset) }) $btnReset.Add_MouseLeave({ $btnReset.FindResource("mouseLeaveAnimation").Begin($btnReset) }) $btnWebInterface.Add_MouseEnter({ $btnWebInterface.FindResource("mouseEnterAnimation").Begin($btnWebInterface) }) $btnWebInterface.Add_MouseLeave({ $btnWebInterface.FindResource("mouseLeaveAnimation").Begin($btnWebInterface) }) $btnShare.Add_MouseEnter({ $btnShare.FindResource("mouseEnterAnimation").Begin($btnShare) }) $btnShare.Add_MouseLeave({ $btnShare.FindResource("mouseLeaveAnimation").Begin($btnShare) }) $btnNone.Add_MouseEnter({ $btnNone.FindResource("mouseEnterAnimation").Begin($btnNone) }) $btnNone.Add_MouseLeave({ $btnNone.FindResource("mouseLeaveAnimation").Begin($btnNone) }) $btnPortScan.Add_MouseEnter({ $btnPortScan.FindResource("mouseEnterAnimation").Begin($btnPortScan) }) $btnPortScan.Add_MouseLeave({ $btnPortScan.FindResource("mouseLeaveAnimation").Begin($btnPortScan) }) # Export List in HTML format $ExportToHTML.Add_Click({ $saveFileDialog = New-Object System.Windows.Forms.SaveFileDialog $saveFileDialog.Filter = "HTML files (*.html)|*.html|All files (*.*)|*.*" $saveFileDialog.FileName = "Network_Scan_Results" if ($saveFileDialog.ShowDialog() -eq "OK") { $path = $saveFileDialog.FileName try { # Create HTML content with header $htmlContent = @" <!DOCTYPE html> <html> <head> <title>Network Scan Results</title> <style> table, th, td { border: 1px solid black; border-collapse: collapse; padding: 5px; } th { background-color: #f2f2f2; } h1, p { margin: 0; padding: 0; } p { margin-bottom: 2px; } .info-block { margin-bottom: 20px; } </style> </head> <body> <h1>Network Scan Results</h1><br> <div class="info-block"> <p><strong>External IP:</strong> $global:externalIP</p> <p><strong>Domain:</strong> $global:domain</p> <p><strong>Date/Time:</strong> $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")</p> <p><strong>Total Devices:</strong> $global:totalCount</p> </div> <table> <tr> <th>MAC Address</th> <th>Vendor</th> <th>IP Address</th> <th>Host Name</th> </tr> "@ $listView.Items | ForEach-Object { $htmlContent += @" <tr> <td>$($_.MACaddress)</td> <td>$($_.Vendor)</td> <td>$($_.IPaddress)</td> <td>$($_.HostName.Replace(' (This Device)',''))</td> </tr> "@ } $htmlContent += @" </table> </body> </html> "@ # Write HTML to file [System.IO.File]::WriteAllText($path, $htmlContent) Show-Popup2 -Message 'Export to HTML completed successfully!' -Title 'Export:' } catch { Show-Popup2 -Message "Error during export: $_" -Title 'ERROR:' } } }) # Export List in CSV format $ExportToCSV.Add_Click({ $saveFileDialog = New-Object System.Windows.Forms.SaveFileDialog $saveFileDialog.Filter = "CSV files (*.csv)|*.csv|All files (*.*)|*.*" $saveFileDialog.FileName = "Network_Scan_Results" if ($saveFileDialog.ShowDialog() -eq "OK") { $path = $saveFileDialog.FileName try { # CSV header $csvHeader = "MAC Address,Vendor,IP Address,Hostname" $csvContent = $listView.Items | ForEach-Object { "`r`n$($_.MACaddress.Replace(',','')),$($_.Vendor.Replace(',','')),$($_.IPaddress.Replace(',','')),$($_.HostName.Replace(' (This Device)','').Replace(',',''))" } [System.IO.File]::WriteAllLines($path, ($csvHeader + $csvContent)) Show-Popup2 -Message 'Export to CSV completed successfully!' -Title 'Export:' } catch { Show-Popup2 -Message "Error during export: $_" -Title 'ERROR:' } } }) # Export List in TXT format $ExportToText.Add_Click({ $saveFileDialog = New-Object System.Windows.Forms.SaveFileDialog $saveFileDialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*" $saveFileDialog.FileName = "Network_Scan_Results" if ($saveFileDialog.ShowDialog() -eq "OK") { $path = $saveFileDialog.FileName try { # TXT header $textContent = @" NETWORK SCAN RESULTS EXTERNAL IP : $global:externalIP DOMAIN : $global:domain DATE/TIME : $(Get-Date -Format "yyyy-MM-dd HH:mm:ss") TOTAL DEVICES : $global:totalCount -------------------------------------- "@ $textContent += $listView.Items | ForEach-Object { @" MAC : $($_.MACaddress) Vendor : $($_.Vendor) IP : $($_.IPaddress) Hostname : $($_.HostName.Replace(' (This Device)','')) -------------------------------------- "@ } [System.IO.File]::WriteAllText($path, $textContent) Show-Popup2 -Message 'Export to Text completed successfully!' -Title 'Export:' } catch { Show-Popup2 -Message "Error during export: $_" -Title 'ERROR:' } } }) # Add listView column header click capture $ListView.AddHandler( [System.Windows.Controls.GridViewColumnHeader]::ClickEvent, [System.Windows.RoutedEventHandler]$listViewSortColumn ) # Find and assign Hostname column from listView to control width when scrollbar is present $hostNameColumn = ($listView.View.Columns | Where-Object {$_.Header -eq "Host Name"}) $listView.Add_MouseDoubleClick({ if($listView.SelectedItems.Count -gt 0){ CheckConnectivity -selectedhost $listView.SelectedItems.IPaddress $selectedItem = $listView.SelectedItems[0] $pMAC.Text = "MAC: " + $selectedItem.MACaddress $pVendor.Text = "Vendor: " + $selectedItem.Vendor $pIP.Text = "IP: " + $selectedItem.IPaddress $pHost.Text = "Host: " + $selectedItem.HostName.Replace(' (This Device)','') $PopupCanvas.SetValue([System.Windows.Controls.Canvas]::LeftProperty, [System.Windows.Controls.Canvas]::GetLeft($listView) + 10) $PopupCanvas.SetValue([System.Windows.Controls.Canvas]::TopProperty, [System.Windows.Controls.Canvas]::GetTop($listView) + 10) $PopupCanvas.Visibility = 'Visible' } }) $listView.Add_MouseLeftButtonDown({ $listView.SelectedItems.Clear() }) # Single item pop-up context menu, IP Address to clipboard $PopupContextCopyIP_Click = { if ($PopupCanvas.Visibility -eq 'Visible') { $ipText = $pIP.Text -replace 'IP: ' Set-Clipboard -Value $ipText Show-Popup2 -Message 'IP Address copied to clipboard!' -Title 'Info:' } else { Show-Popup2 -Message 'No item available to copy IP Address from!' -Title 'Warning:' } } $PopupContextCopyIP.Add_Click($PopupContextCopyIP_Click) # Single item pop-up context menu, Hostname to clipboard $PopupContextCopyHostname_Click = { if ($PopupCanvas.Visibility -eq 'Visible') { $hostText = $pHost.Text -replace 'Host: ' Set-Clipboard -Value $hostText Show-Popup2 -Message 'Hostname copied to clipboard!' -Title 'Info:' } else { Show-Popup2 -Message 'No item available to copy Hostname from!' -Title 'Warning:' } } $PopupContextCopyHostname.Add_Click($PopupContextCopyHostname_Click) # Single item pop-up context menu, MAC Address to clipboard $PopupContextCopyMAC_Click = { if ($PopupCanvas.Visibility -eq 'Visible') { $macText = $pMAC.Text -replace 'MAC: ' Set-Clipboard -Value $macText Show-Popup2 -Message 'MAC Address copied to clipboard!' -Title 'Info:' } else { Show-Popup2 -Message 'No item available to copy MAC Address from!' -Title 'Warning:' } } $PopupContextCopyMAC.Add_Click($PopupContextCopyMAC_Click) # Single item pop-up context menu, Vendor to clipboard $PopupContextCopyVendor_Click = { if ($PopupCanvas.Visibility -eq 'Visible') { $vendorText = $pVendor.Text -replace 'Vendor: ' Set-Clipboard -Value $vendorText Show-Popup2 -Message 'Vendor copied to clipboard!' -Title 'Info:' } else { Show-Popup2 -Message 'No item available to copy Vendor from!' -Title 'Warning:' } } $PopupContextCopyVendor.Add_Click($PopupContextCopyVendor_Click) # Single item pop-up context menu, All details to clipboard $PopupContextCopyAll_Click = { if ($PopupCanvas.Visibility -eq 'Visible') { $hostText = $pHost.Text -replace 'Host: ' $ipText = $pIP.Text -replace 'IP: ' $macText = $pMAC.Text -replace 'MAC: ' $vendorText = $pVendor.Text -replace 'Vendor: ' $details = "Host: $hostText`nIP: $ipText`nMAC: $macText`nVendor: $vendorText" Set-Clipboard -Value $details Show-Popup2 -Message 'All details copied to clipboard!' -Title 'Info:' } else { Show-Popup2 -Message 'No item available to copy details from!' -Title 'Warning:' } } $PopupContextCopyAll.Add_Click($PopupContextCopyAll_Click) # Clear CTRL key value $global:CtrlIsDown = $false # KeyDown event handler $Main.Add_KeyDown({ if ($_.Key -eq 'LeftCtrl' -or $_.Key -eq 'RightCtrl') { $global:CtrlIsDown = $true if($Scan.IsEnabled){ $scanButtonText.Text = 'Clear ARP cache' $scanAdminIcon.Visibility = 'Visible' } } }) # KeyUp event handler $Main.Add_KeyUp({ if ($_.Key -eq 'LeftCtrl' -or $_.Key -eq 'RightCtrl') { $global:CtrlIsDown = $false if($Scan.IsEnabled){ if ($global:gatewayPrefix -ne $originalGatewayPrefix) { $scanButtonText.Text = 'Custom Scan' } else { $scanButtonText.Text = 'Scan' } $scanAdminIcon.Visibility = 'Collapsed' } } }) # Wait for background jobs to finish with progress tracking function TrackProgress { $totalItems = $listView.Items.Count $completedItems = 0 # Initialize to a value that will always differ from $completedItems on first check $previousCompletedItems = -1 do { # Count items with both HostName and Vendor resolved $completedItems = ($listView.Items | Where-Object { $_.HostName -ne "Resolving..." -and $_.Vendor -ne "Identifying..." }).Count # Check if the number of completed items has changed if ($completedItems -ne $previousCompletedItems) { # Update UI with the new progress $completedPercentage = if ($totalItems -gt 0) { ($completedItems / $totalItems) * 100 } else { 0 } Update-Progress ([math]::Min(100, $completedPercentage)) 'Identifying Devices' # Refresh ListView to show changes $listView.Items.Refresh() Update-uiMain # Update the previous count for the next iteration $previousCompletedItems = $completedItems } else { # If no change, update the UI occasionally to show that the process is ongoing if ($completedItems -lt $totalItems) { Update-Progress ([math]::Min(100, $completedPercentage)) 'Identifying Devices' } } # Short sleep to not overload the system Start-Sleep -Milliseconds 5 } while ($completedItems -lt $totalItems) } # Ensure clean ListView if($listview.Items){ $listview.Items.Clear() } $ExportContext.IsEnabled = $false # Define Scan Button Actions $btnScan.Add_MouseEnter({ $btnScan.Background = '#EEEEEE' }) $btnScan.Add_MouseLeave({ $btnScan.Background = '#777777' }) $Scan.Add_MouseEnter({ $Scan.Background = '#EEEEEE' }) $Scan.Add_MouseLeave({ $Scan.Background = '#777777' }) $Scan.Add_Click({ if($PopupCanvas.Visibility -eq 'Visible') { $PopupCanvas.Visibility = 'Hidden' } if($PopupCanvas2.Visibility -eq 'Visible') { $PopupCanvas2.Visibility = 'Hidden' } # If CTRL key is held while clicking the Scan button, offer to clear ARP cache as Admin prior to Scan process if ($global:CtrlIsDown) { $Scan.IsEnabled = $false $osInfo = Get-CimInstance Win32_OperatingSystem if ($osInfo.Caption -match "Server") { Show-Popup2 -Message 'This option is not available for Windows Servers. Please clear your ARP Cache manually.' -Title 'Restricted Feature:' } else { try{ Start-Process -Verb RunAs powershell -WindowStyle Minimized -ArgumentList '-Command "& {Remove-NetNeighbor -InterfaceAlias * -Confirm:$false}"' $listView.Items.Clear() $TotalListed.Text = '' Show-Popup2 -Message 'Cached peer list cleared...' -Title 'List Cleared:' }catch{ Show-Popup2 -Message 'No action was taken...' -Title 'Process Aborted:' } } if ($global:gatewayPrefix -ne $originalGatewayPrefix) { $scanButtonText.Text = 'Custom Scan' } else { $scanButtonText.Text = 'Scan' } $scanAdminIcon.Visibility = 'Collapsed' $Scan.IsEnabled = $true $global:CtrlIsDown = $false } else { $Scan.IsEnabled = $false # Make ProgressBar visible, hide Button $Scan.Visibility = 'Collapsed' $Progress.Visibility = 'Visible' $Progress.Value = 0 $BarText.Text = 'Initializing' $listView.Items.Clear() $TotalListed.Text = '' $global:totalCount = 0 $ExportContext.IsEnabled = $false $hostNameColumn.Width = 284 Update-uiMain Get-HostInfo -gateway $global:gateway -gatewayPrefix $global:gatewayPrefix -originalGatewayPrefix $originalGatewayPrefix $externalIPt.Text = "`- `[ External IP: $externalIP `]" $domainName.Text = "`- `[ Domain: $domain `]" Update-uiMain Scan-Subnet List-Machines processVendors processHostnames TrackProgress # Hide ProgressBar, show button $Progress.Visibility = 'Collapsed' $Scan.Visibility = 'Visible' $BarText.Text = '' $Scan.IsEnabled = $true $Progress.Value = 0 if ($listView.Items.Count -eq 0) { $ExportContext.IsEnabled = $false } else { $ExportContext.IsEnabled = $true } Update-uiMain $global:CtrlIsDown = $false } }) # Show Window $Main.ShowDialog() | out-null |