Он работал нормально, пока я не реализовал отображение в реальном времени, когда хост найден.
Когда он находит активный хост сети, он добавляет строку с такой информацией, как IP-адрес и MAC-адрес, но по какой-то причине начал возвращать пустые строки. Раньше это работало, когда не возвращало данные в режиме реального времени.
Это мой внутренний код:
Код: Выделить всё
using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Text.RegularExpressions;
using System.Windows.Input;
using System.Runtime.InteropServices;
using System.Net;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.Linq;
using System.ComponentModel;
// TODO - jak navýšit čas na odpověď od stanice? Občas možná nestihne přijít odpověd, dle jiného skeneru jsou ip adresy např. dostupné
// TODO - navýšit rychlost skenování - použit více paralel tasků
// TODO - naimplementovaet log4net
namespace NetVision.Pages.NetworkTools
{
public partial class NetworkScan : Page
{
private ObservableCollection Subnets { get; set; }
private ObservableCollection ScanResults { get; set; }
// Regex pattern for subnet validation with CIDR notation
private static readonly Regex SubnetRegex = new Regex(
@"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$",
RegexOptions.Compiled);
private int _totalHosts;
private int _scannedHosts;
public NetworkScan()
{
InitializeComponent();
cmbTypeScan.SelectedIndex = 0;
Subnets = new ObservableCollection();
ScanResults = new ObservableCollection();
lstSubnets.ItemsSource = Subnets;
dgScanResults.ItemsSource = ScanResults;
}
private void UpdateScanDescription()
{
if (txtScanDescription != null)
{
switch (cmbTypeScan.SelectedIndex)
{
case 0:
txtScanDescription.Text = "ARP scan works only on broadcast domain!";
break;
case 1:
txtScanDescription.Text = "Scans TCP/UDP opened ports.";
break;
case 2:
txtScanDescription.Text = "Scans TCP opened ports.";
break;
case 3:
txtScanDescription.Text = "Scans UDP opened ports.";
break;
case 4:
txtScanDescription.Text = "Uses ICMP echo requests to detect hosts.";
break;
default:
txtScanDescription.Text = "";
break;
}
}
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
UpdateScanDescription();
}
private void txtSubnet_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
AddSubnet();
e.Handled = true; // Prevents the ding sound
}
}
private void btnAddSubnet_Click(object sender, RoutedEventArgs e)
{
AddSubnet();
}
private void AddSubnet()
{
string subnet = txtSubnet.Text.Trim();
if (!string.IsNullOrWhiteSpace(subnet))
{
if (SubnetRegex.IsMatch(subnet))
{
Subnets.Add(subnet);
txtSubnet.Clear();
HideError();
}
else
{
ShowError("Invalid subnet format. Please use CIDR notation (e.g., 192.168.1.0/24 or 10.0.0.0/8).");
}
}
}
private void HideError()
{
txtErrorMessage.Text = string.Empty;
txtErrorMessage.Visibility = Visibility.Collapsed;
}
private void ShowError(string message)
{
txtErrorMessage.Text = message;
txtErrorMessage.Visibility = Visibility.Visible;
}
private void btnDeleteSubnet_Click(object sender, RoutedEventArgs e)
{
if (sender is Button button && button.DataContext is string subnet)
{
Subnets.Remove(subnet);
}
}
private async void btnStartScan_ClickAsync(object sender, RoutedEventArgs e)
{
if (Subnets.Count > 0)
{
btnStartScan.IsEnabled = false;
btnStopScan.IsEnabled = true;
ScanResults.Clear();
// Reset progress
_scannedHosts = 0;
_totalHosts = 0;
progressGrid.Visibility = Visibility.Collapsed;
if (cmbTypeScan.Text == "ARP Scan")
{
await PerformArpScan();
}
btnStartScan.IsEnabled = true;
btnStopScan.IsEnabled = false;
}
else
{
txtErrorMessage.Text = "You need to add at least one subnet to scan.";
txtErrorMessage.Visibility = Visibility.Visible;
}
}
[DllImport("iphlpapi.dll", ExactSpelling = true)]
private static extern int SendARP(int DestIP, int SrcIP, byte[] pMacAddr, ref uint PhyAddrLen);
private static uint macAddrLen = (uint)new byte[6].Length;
private async Task PerformArpScan()
{
var allHosts = new ConcurrentBag();
foreach (var subnet in Subnets)
{
var hosts = GenerateIPRange(subnet);
foreach (var host in hosts)
{
allHosts.Add(host);
}
}
var results = new ConcurrentBag();
_totalHosts = allHosts.Count;
_scannedHosts = 0;
await Dispatcher.InvokeAsync(() =>
{
progressGrid.Visibility = Visibility.Visible;
scanProgressBar.Value = 0;
scanProgressBar.Maximum = _totalHosts;
UpdateProgressText();
ScanResults.Clear();
});
await Task.Run(() =>
{
Parallel.ForEach(allHosts, new ParallelOptions { MaxDegreeOfParallelism = 50 }, ip =>
{
var result = SendArpRequest(ip);
if (result != null)
{
Application.Current.Dispatcher.Invoke(() =>
{
ScanResults.Add(result);
});
}
Interlocked.Increment(ref _scannedHosts);
Application.Current.Dispatcher.Invoke(() =>
{
scanProgressBar.Value = _scannedHosts;
UpdateProgressText();
});
});
});
await Dispatcher.InvokeAsync(() =>
{
progressGrid.Visibility = Visibility.Collapsed;
});
}
private void UpdateProgressText()
{
progressText.Text = $"Scanning: {_scannedHosts}/{_totalHosts} hosts";
}
public static IEnumerable GenerateIPRange(string cidrNotation)
{
string[] parts = cidrNotation.Split('/');
if (parts.Length != 2)
{
throw new ArgumentException("Invalid CIDR notation");
}
if (!IPAddress.TryParse(parts[0], out IPAddress ipAddress))
{
throw new ArgumentException("Invalid IP address");
}
if (!int.TryParse(parts[1], out int subnetBits) || subnetBits < 0 || subnetBits > 32)
{
throw new ArgumentException("Invalid subnet mask");
}
uint ipCount = (uint)(1 16),
(byte)(currentIP >> 8),
(byte)currentIP
};
yield return new IPAddress(currentIPBytes);
}
}
private ScanResult SendArpRequest(IPAddress ipAddress)
{
byte[] macAddr = new byte[6];
uint macAddrLen = (uint)macAddr.Length;
try
{
// Convert IP address to bytes in the correct order
byte[] ipBytes = ipAddress.GetAddressBytes();
int ipInteger = BitConverter.ToInt32(ipBytes, 0);
int result = SendARP(ipInteger, 0, macAddr, ref macAddrLen);
if (result == 0)
{
// Create MAC address string
string macAddressString = BitConverter.ToString(macAddr, 0, (int)macAddrLen).Replace("-", ":");
// Create and return result immediately
var scanResult = new ScanResult
{
IpAddress = ipAddress.ToString(),
MacAddress = macAddressString,
Status = "Online",
OpenPorts = "N/A"
};
// Debug print to verify data
Console.WriteLine($"Found device - IP: {ipAddress}, MAC: {macAddressString}");
return scanResult;
}
}
catch (Exception ex)
{
Console.WriteLine($"Error scanning {ipAddress}: {ex.Message}");
}
return null;
}
private void cmbTypeScan_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
UpdateScanDescription();
}
private void btnStopScan_Click(object sender, RoutedEventArgs e)
{
//TODO - implement logic to stop scan
btnStartScan.IsEnabled = true;
btnStopScan.IsEnabled = false;
progressGrid.Visibility = Visibility.Collapsed;
}
}
public class ScanResult : INotifyPropertyChanged
{
private string _ipAddress;
private string _macAddress;
private string _status;
private string _openPorts;
public string IpAddress
{
get => _ipAddress;
set
{
_ipAddress = value;
OnPropertyChanged(nameof(IpAddress));
}
}
public string MacAddress
{
get => _macAddress;
set
{
_macAddress = value;
OnPropertyChanged(nameof(MacAddress));
}
}
public string Status
{
get => _status;
set
{
_status = value;
OnPropertyChanged(nameof(Status));
}
}
public string OpenPorts
{
get => _openPorts;
set
{
_openPorts = value;
OnPropertyChanged(nameof(OpenPorts));
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Код: Выделить всё

Подробнее здесь: https://stackoverflow.com/questions/791 ... n-frontend
Мобильная версия