Возврат пустых строк во внешнем интерфейсеC#

Место общения программистов C#
Ответить
Anonymous
 Возврат пустых строк во внешнем интерфейсе

Сообщение Anonymous »

У меня есть ARP-сканер с графическим интерфейсом пользователя.
Он работал нормально, пока я не реализовал отображение в реальном времени, когда хост найден.
Когда он находит активный хост сети, он добавляет строку с такой информацией, как 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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»