Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <#
- ****************************************************************************************
- * Powershell Script GUI Network Scanner *
- * Scans user input subnet and returns all active devices' IP Address *
- * hostname, MAC Address, and OS version if applicable. *
- * User can select field and right mouse click to copy data. *
- * Version 2: WPF GUI *
- * Coded by: djl236 *
- * 2025 January 11 *
- * Version 2.0 *
- ****************************************************************************************
- #>
- #Load WPF Assembly
- Add-Type -AssemblyName PresentationFramework
- #Define the WPF XAML Layout
- $Xaml = @"
- <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Network Scanner Tool"
- Height="520" Width="750" WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto"/> <!-- Header -->
- <RowDefinition Height="Auto"/> <!-- Subnet Input -->
- <RowDefinition Height="*"/> <!-- Results -->
- <RowDefinition Height="Auto"/> <!-- Status -->
- <RowDefinition Height="Auto"/> <!-- Footer -->
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="Auto"/> <!-- Label -->
- <ColumnDefinition Width="Auto"/> <!-- Input -->
- <ColumnDefinition Width="Auto"/> <!-- Scan -->
- <ColumnDefinition Width="Auto"/> <!-- Clear -->
- <ColumnDefinition Width="Auto"/> <!-- Close -->
- <ColumnDefinition Width="*"/> <!-- Remaining space -->
- </Grid.ColumnDefinitions>
- <!-- Header -->
- <Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="6" HorizontalAlignment="Center"
- VerticalAlignment="Center" FontSize="14" FontWeight="Bold">
- <TextBlock TextAlignment="Center">
- Network Scanner Tool
- <LineBreak/>
- Right mouse click selected data to copy.
- </TextBlock>
- </Label>
- <!-- Subnet Input -->
- <Label Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Margin="0,5,5,5">Subnet:</Label>
- <TextBox x:Name="SubnetTextBox" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center"
- Margin="0,5,5,5" Text="Enter Subnet (192.168.1)" Width="200"/>
- <Button x:Name="ScanButton" Grid.Row="1" Grid.Column="2" Margin="5" Width="75">Scan</Button>
- <Button x:Name="ClearButton" Grid.Row="1" Grid.Column="3" Margin="5" Width="75">Clear</Button>
- <Button x:Name="CloseButton" Grid.Row="1" Grid.Column="4" Margin="2,5,5,5" Width="75">Close</Button>
- <!-- Results ListView -->
- <ListView x:Name="ResultsListView" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="6"
- Margin="5" BorderThickness="1" SelectionMode="Single">
- <ListView.ContextMenu>
- <ContextMenu>
- <MenuItem Header="Copy IP Address" />
- <MenuItem Header="Copy Host Name" />
- <MenuItem Header="Copy MAC Address" />
- <MenuItem Header="Copy OS Version" />
- <MenuItem Header="Copy Entire Row" />
- </ContextMenu>
- </ListView.ContextMenu>
- <ListView.View>
- <GridView>
- <GridViewColumn Header="IP Address" Width="120" DisplayMemberBinding="{Binding IPAddress}"/>
- <GridViewColumn Header="Host Name" Width="200" DisplayMemberBinding="{Binding HostName}"/>
- <GridViewColumn Header="MAC Address" Width="150" DisplayMemberBinding="{Binding MACAddress}"/>
- <GridViewColumn Header="OS Version" Width="200" DisplayMemberBinding="{Binding OSVersion}"/>
- </GridView>
- </ListView.View>
- </ListView>
- <!-- Status Label -->
- <Label x:Name="StatusTextLabel" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="6" Margin="5">
- Status: Ready
- </Label>
- <!-- Footer -->
- <Label Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="6" HorizontalAlignment="Center"
- VerticalAlignment="Center" FontSize="12" FontWeight="Bold">
- Developer POC - djl236
- </Label>
- </Grid>
- </Window>
- "@
- #Load the XAML
- [xml]$XamlObject = $Xaml
- $Reader = (New-Object System.Xml.XmlNodeReader $XamlObject)
- $Window = [Windows.Markup.XamlReader]::Load($Reader)
- #Get UI Elements
- $SubnetTextBox = $Window.FindName("SubnetTextBox")
- $ScanButton = $Window.FindName("ScanButton")
- $ClearButton = $Window.FindName("ClearButton")
- $CloseButton = $Window.FindName("CloseButton")
- $ResultsListView = $Window.FindName("ResultsListView")
- $StatusTextLabel = $Window.FindName("StatusTextLabel")
- #Functions
- Function Copy-SelectedField
- {
- Param ([string]$Field)
- If ($ResultsListView.SelectedItem)
- {
- $SelectedItem = $ResultsListView.SelectedItem
- Switch ($Field)
- {
- "IP" { [System.Windows.Clipboard]::SetText($SelectedItem.IPAddress); Write-Host "IP Address copied." }
- "HostName" { [System.Windows.Clipboard]::SetText($SelectedItem.HostName); Write-Host "Host Name copied." }
- "MAC" { [System.Windows.Clipboard]::SetText($SelectedItem.MACAddress); Write-Host "MAC Address copied." }
- "OS" { [System.Windows.Clipboard]::SetText($SelectedItem.OSVersion); Write-Host "OS Version copied." }
- "Row" {
- $RowData = "$($SelectedItem.IPAddress), $($SelectedItem.HostName), $($SelectedItem.MACAddress), $($SelectedItem.OSVersion)"
- [System.Windows.Clipboard]::SetText($RowData)
- Write-Host "Entire row copied."
- }
- }
- }
- Else
- {
- Write-Host "No item selected to copy." -ForegroundColor Yellow
- }
- }
- #Attach Context Menu Events
- $ResultsListView.ContextMenu.Items[0].Add_Click({ Copy-SelectedField -Field "IP" })
- $ResultsListView.ContextMenu.Items[1].Add_Click({ Copy-SelectedField -Field "HostName" })
- $ResultsListView.ContextMenu.Items[2].Add_Click({ Copy-SelectedField -Field "MAC" })
- $ResultsListView.ContextMenu.Items[3].Add_Click({ Copy-SelectedField -Field "OS" })
- $ResultsListView.ContextMenu.Items[4].Add_Click({ Copy-SelectedField -Field "Row" })
- Function Get-MACAddress
- {
- Param ([string]$IPAddress)
- Try
- {
- $LocalIP = (Get-NetIPAddress | Where-Object { $_.IPAddress -eq $IPAddress }).IPAddress
- If ($LocalIP)
- {
- $Adapter = Get-NetIPAddress -IPAddress $IPAddress | Get-NetAdapter
- If ($Adapter)
- {
- Return $Adapter.MacAddress
- }
- Else
- {
- Return "MAC Not Found (Local)"
- }
- }
- $ARPTable = arp -a
- $Regex = [regex]"(?<IP>\d+\.\d+\.\d+\.\d+)\s+(?<MAC>([0-9a-f]{2}-?){6})"
- $Match = $Regex.Matches($ARPTable) | Where-Object { $_.Groups["IP"].Value -eq $IPAddress }
- If ($Match)
- {
- Return $Match.Groups["MAC"].Value
- }
- Else
- {
- Return "Not Found"
- }
- }
- Catch
- {
- Return "Error"
- }
- }
- Function Get-OSVersion
- {
- Param ([string]$IPAddress)
- Try
- {
- $OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $IPAddress -ErrorAction Stop
- Return $OS.Caption
- }
- Catch
- {
- Return "Unknown or Not a Windows OS"
- }
- }
- Function Update-Status
- {
- #Forces the WPF GUI to refresh immediately
- $Frame = New-Object -TypeName System.Windows.Threading.DispatcherFrame
- [System.Windows.Threading.Dispatcher]::CurrentDispatcher.Invoke(
- [System.Action]{ $Frame.Continue = $false },
- [System.Windows.Threading.DispatcherPriority]::Background
- )
- [System.Windows.Threading.Dispatcher]::PushFrame($Frame)
- }
- Function Search-Network
- {
- Param ([string]$Subnet)
- If (-not $Subnet)
- {
- $StatusTextLabel.Content = "Error: Please enter a subnet."
- Return
- }
- $StatusTextLabel.Content = "Scanning..."
- #Force GUI refresh
- Update-Status
- $ResultsListView.Items.Clear()
- Try
- {
- $IPRange = 1..254 | ForEach-Object { "$Subnet.$_" }
- $Addresses = $IPRange -join "' or Address='"
- $Filter = "(Address='$Addresses') AND StatusCode=0"
- $Results = Get-WmiObject -Class Win32_PingStatus -Filter $Filter
- #Manual IP Sorting
- $SortedResults = $Results | Sort-Object {
- $Octets = $_.Address -split '\.' | ForEach-Object { [int]$_ }
- ($Octets[0] * 256 * 256 * 256) + ($Octets[1] * 256 * 256) + ($Octets[2] * 256) + $Octets[3]
- }
- #Add Sorted Results to the ListView
- ForEach ($Result in $SortedResults)
- {
- $IPAddress = $Result.Address
- $HostName = Try { ([System.Net.Dns]::GetHostEntry($IPAddress)).HostName } Catch { "Unable to Resolve" }
- $MACAddress = Get-MACAddress -IPAddress $IPAddress
- $OSVersion = Get-OSVersion -IPAddress $IPAddress
- If (-not $MACAddress) { $MACAddress = "Unable to Resolve" }
- $Item = [PSCustomObject]@{
- IPAddress = $IPAddress
- HostName = $HostName
- MACAddress = $MACAddress
- OSVersion = $OSVersion
- }
- $ResultsListView.Items.Add($Item)
- }
- $StatusTextLabel.Content = "Scan Complete."
- }
- Catch
- {
- $StatusTextLabel.Content = "Error occurred: $_"
- Write-Host "Error occurred: $_" -ForegroundColor Red
- }
- }
- Function Clear-Results
- {
- $ResultsListView.Items.Clear()
- $StatusTextLabel.Content = "Status: Ready"
- Write-Host "Results cleared."
- }
- #Event Handlers
- $ScanButton.Add_Click({
- #Validate Subnet Format
- $Subnet = $SubnetTextBox.Text
- $SubnetRegex = '^\d{1,3}\.\d{1,3}\.\d{1,3}$'
- If (-not [string]::IsNullOrWhiteSpace($Subnet))
- {
- If ($Subnet -match $SubnetRegex)
- {
- Search-Network -Subnet $Subnet
- }
- Else
- {
- $StatusTextLabel.Content = "Error: Invalid Subnet Format (e.g. 192.168.1)"
- Write-Host "Error: Invalid Subnet Format (e.g. 192.168.1)"
- }
- }
- Else
- {
- $StatusTextLabel.Content = "Error: Please enter a subnet."
- Write-Host "Error: Please enter a subnet."
- }
- })
- $ClearButton.Add_Click({ Clear-Results })
- $CloseButton.Add_Click({ $Window.Close() })
- #Show the Window
- $Window.ShowDialog()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement