Advertisement
djl236

IPScanner.ps1

Jan 12th, 2025
191
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PowerShell 12.17 KB | Source Code | 0 0
  1. <#
  2. ****************************************************************************************
  3. *              Powershell Script GUI Network Scanner                                   *
  4. *              Scans user input subnet and returns all active devices' IP Address      *
  5. *              hostname, MAC Address, and OS version if applicable.                    *
  6. *              User can select field and right mouse click to copy data.               *
  7. *               Version 2: WPF GUI                                                     *
  8. *                        Coded by: djl236                                              *
  9. *                        2025 January 11                                               *
  10. *                        Version 2.0                                                   *
  11. ****************************************************************************************
  12. #>
  13.  
  14. #Load WPF Assembly
  15. Add-Type -AssemblyName PresentationFramework
  16.  
  17. #Define the WPF XAML Layout
  18. $Xaml = @"
  19. <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  20.        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  21.        Title="Network Scanner Tool"
  22.        Height="520" Width="750" WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
  23.    <Grid>
  24.        <Grid.RowDefinitions>
  25.            <RowDefinition Height="Auto"/>   <!-- Header -->
  26.            <RowDefinition Height="Auto"/>   <!-- Subnet Input -->
  27.            <RowDefinition Height="*"/>     <!-- Results -->
  28.            <RowDefinition Height="Auto"/>   <!-- Status -->
  29.            <RowDefinition Height="Auto"/>   <!-- Footer -->
  30.        </Grid.RowDefinitions>
  31.        <Grid.ColumnDefinitions>
  32.            <ColumnDefinition Width="Auto"/> <!-- Label -->
  33.            <ColumnDefinition Width="Auto"/> <!-- Input -->
  34.            <ColumnDefinition Width="Auto"/> <!-- Scan -->
  35.            <ColumnDefinition Width="Auto"/> <!-- Clear -->
  36.            <ColumnDefinition Width="Auto"/> <!-- Close -->
  37.            <ColumnDefinition Width="*"/>   <!-- Remaining space -->
  38.        </Grid.ColumnDefinitions>
  39.  
  40.        <!-- Header -->
  41.        <Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="6" HorizontalAlignment="Center"
  42.               VerticalAlignment="Center" FontSize="14" FontWeight="Bold">
  43.            <TextBlock TextAlignment="Center">
  44.                Network Scanner Tool
  45.                <LineBreak/>
  46.                Right mouse click selected data to copy.
  47.            </TextBlock>
  48.        </Label>
  49.  
  50.        <!-- Subnet Input -->
  51.        <Label Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Margin="0,5,5,5">Subnet:</Label>
  52.        <TextBox x:Name="SubnetTextBox" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center"
  53.                 Margin="0,5,5,5" Text="Enter Subnet (192.168.1)" Width="200"/>
  54.        <Button x:Name="ScanButton" Grid.Row="1" Grid.Column="2" Margin="5" Width="75">Scan</Button>
  55.        <Button x:Name="ClearButton" Grid.Row="1" Grid.Column="3" Margin="5" Width="75">Clear</Button>
  56.        <Button x:Name="CloseButton" Grid.Row="1" Grid.Column="4" Margin="2,5,5,5" Width="75">Close</Button>
  57.  
  58.        <!-- Results ListView -->
  59.        <ListView x:Name="ResultsListView" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="6"
  60.                  Margin="5" BorderThickness="1" SelectionMode="Single">
  61.            <ListView.ContextMenu>
  62.                <ContextMenu>
  63.                    <MenuItem Header="Copy IP Address" />
  64.                    <MenuItem Header="Copy Host Name" />
  65.                    <MenuItem Header="Copy MAC Address" />
  66.                    <MenuItem Header="Copy OS Version" />
  67.                    <MenuItem Header="Copy Entire Row" />
  68.                </ContextMenu>
  69.            </ListView.ContextMenu>
  70.            <ListView.View>
  71.                <GridView>
  72.                    <GridViewColumn Header="IP Address" Width="120" DisplayMemberBinding="{Binding IPAddress}"/>
  73.                    <GridViewColumn Header="Host Name" Width="200" DisplayMemberBinding="{Binding HostName}"/>
  74.                    <GridViewColumn Header="MAC Address" Width="150" DisplayMemberBinding="{Binding MACAddress}"/>
  75.                    <GridViewColumn Header="OS Version" Width="200" DisplayMemberBinding="{Binding OSVersion}"/>
  76.                </GridView>
  77.            </ListView.View>
  78.        </ListView>
  79.  
  80.        <!-- Status Label -->
  81.        <Label x:Name="StatusTextLabel" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="6" Margin="5">
  82.            Status: Ready
  83.        </Label>
  84.  
  85.        <!-- Footer -->
  86.        <Label Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="6" HorizontalAlignment="Center"
  87.               VerticalAlignment="Center" FontSize="12" FontWeight="Bold">
  88.            Developer POC - djl236
  89.        </Label>
  90.    </Grid>
  91. </Window>
  92. "@
  93.  
  94. #Load the XAML
  95. [xml]$XamlObject = $Xaml
  96. $Reader = (New-Object System.Xml.XmlNodeReader $XamlObject)
  97. $Window = [Windows.Markup.XamlReader]::Load($Reader)
  98.  
  99. #Get UI Elements
  100. $SubnetTextBox = $Window.FindName("SubnetTextBox")
  101. $ScanButton = $Window.FindName("ScanButton")
  102. $ClearButton = $Window.FindName("ClearButton")
  103. $CloseButton = $Window.FindName("CloseButton")
  104. $ResultsListView = $Window.FindName("ResultsListView")
  105. $StatusTextLabel = $Window.FindName("StatusTextLabel")
  106.  
  107. #Functions
  108. Function Copy-SelectedField
  109.     {
  110.         Param ([string]$Field)
  111.         If ($ResultsListView.SelectedItem)
  112.             {
  113.                 $SelectedItem = $ResultsListView.SelectedItem
  114.                 Switch ($Field)
  115.                     {
  116.                         "IP" { [System.Windows.Clipboard]::SetText($SelectedItem.IPAddress); Write-Host "IP Address copied." }
  117.                         "HostName" { [System.Windows.Clipboard]::SetText($SelectedItem.HostName); Write-Host "Host Name copied." }
  118.                         "MAC" { [System.Windows.Clipboard]::SetText($SelectedItem.MACAddress); Write-Host "MAC Address copied." }
  119.                         "OS" { [System.Windows.Clipboard]::SetText($SelectedItem.OSVersion); Write-Host "OS Version copied." }
  120.                         "Row" {
  121.                             $RowData = "$($SelectedItem.IPAddress), $($SelectedItem.HostName), $($SelectedItem.MACAddress), $($SelectedItem.OSVersion)"
  122.                             [System.Windows.Clipboard]::SetText($RowData)
  123.                             Write-Host "Entire row copied."
  124.                         }
  125.                     }
  126.             }
  127.         Else
  128.             {
  129.                 Write-Host "No item selected to copy." -ForegroundColor Yellow
  130.             }
  131.     }
  132.  
  133. #Attach Context Menu Events
  134. $ResultsListView.ContextMenu.Items[0].Add_Click({ Copy-SelectedField -Field "IP" })
  135. $ResultsListView.ContextMenu.Items[1].Add_Click({ Copy-SelectedField -Field "HostName" })
  136. $ResultsListView.ContextMenu.Items[2].Add_Click({ Copy-SelectedField -Field "MAC" })
  137. $ResultsListView.ContextMenu.Items[3].Add_Click({ Copy-SelectedField -Field "OS" })
  138. $ResultsListView.ContextMenu.Items[4].Add_Click({ Copy-SelectedField -Field "Row" })
  139.  
  140. Function Get-MACAddress
  141.     {
  142.         Param ([string]$IPAddress)
  143.         Try
  144.             {
  145.                 $LocalIP = (Get-NetIPAddress | Where-Object { $_.IPAddress -eq $IPAddress }).IPAddress
  146.                 If ($LocalIP)
  147.                     {
  148.                         $Adapter = Get-NetIPAddress -IPAddress $IPAddress | Get-NetAdapter
  149.                         If ($Adapter)
  150.                             {
  151.                                 Return $Adapter.MacAddress
  152.                             }
  153.                         Else
  154.                             {
  155.                                 Return "MAC Not Found (Local)"
  156.                             }
  157.                     }
  158.  
  159.                 $ARPTable = arp -a
  160.                 $Regex = [regex]"(?<IP>\d+\.\d+\.\d+\.\d+)\s+(?<MAC>([0-9a-f]{2}-?){6})"
  161.                 $Match = $Regex.Matches($ARPTable) | Where-Object { $_.Groups["IP"].Value -eq $IPAddress }
  162.                 If ($Match)
  163.                     {
  164.                         Return $Match.Groups["MAC"].Value
  165.                     }
  166.                 Else
  167.                     {
  168.                         Return "Not Found"
  169.                     }
  170.             }
  171.         Catch
  172.             {
  173.                 Return "Error"
  174.             }
  175.     }
  176.  
  177. Function Get-OSVersion
  178.     {
  179.         Param ([string]$IPAddress)
  180.         Try
  181.             {
  182.                 $OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $IPAddress -ErrorAction Stop
  183.                 Return $OS.Caption
  184.             }
  185.         Catch
  186.             {
  187.                 Return "Unknown or Not a Windows OS"
  188.             }
  189.     }
  190.  
  191. Function Update-Status
  192.     {
  193.         #Forces the WPF GUI to refresh immediately
  194.         $Frame = New-Object -TypeName System.Windows.Threading.DispatcherFrame
  195.         [System.Windows.Threading.Dispatcher]::CurrentDispatcher.Invoke(
  196.             [System.Action]{ $Frame.Continue = $false },
  197.             [System.Windows.Threading.DispatcherPriority]::Background
  198.         )
  199.         [System.Windows.Threading.Dispatcher]::PushFrame($Frame)
  200.     }
  201.  
  202.     Function Search-Network
  203.     {
  204.         Param ([string]$Subnet)
  205.  
  206.         If (-not $Subnet)
  207.             {
  208.                 $StatusTextLabel.Content = "Error: Please enter a subnet."
  209.                 Return
  210.             }
  211.  
  212.         $StatusTextLabel.Content = "Scanning..."
  213.        
  214.         #Force GUI refresh
  215.         Update-Status
  216.  
  217.         $ResultsListView.Items.Clear()
  218.  
  219.         Try
  220.             {
  221.                 $IPRange = 1..254 | ForEach-Object { "$Subnet.$_" }
  222.                 $Addresses = $IPRange -join "' or Address='"
  223.                 $Filter = "(Address='$Addresses') AND StatusCode=0"
  224.                 $Results = Get-WmiObject -Class Win32_PingStatus -Filter $Filter
  225.  
  226.                 #Manual IP Sorting
  227.                 $SortedResults = $Results | Sort-Object {
  228.                     $Octets = $_.Address -split '\.' | ForEach-Object { [int]$_ }
  229.                     ($Octets[0] * 256 * 256 * 256) + ($Octets[1] * 256 * 256) + ($Octets[2] * 256) + $Octets[3]
  230.                 }
  231.  
  232.                 #Add Sorted Results to the ListView
  233.                 ForEach ($Result in $SortedResults)
  234.                     {
  235.                         $IPAddress = $Result.Address
  236.                         $HostName = Try { ([System.Net.Dns]::GetHostEntry($IPAddress)).HostName } Catch { "Unable to Resolve" }
  237.                         $MACAddress = Get-MACAddress -IPAddress $IPAddress
  238.                         $OSVersion = Get-OSVersion -IPAddress $IPAddress
  239.  
  240.                         If (-not $MACAddress) { $MACAddress = "Unable to Resolve" }
  241.  
  242.                         $Item = [PSCustomObject]@{
  243.                             IPAddress  = $IPAddress
  244.                             HostName   = $HostName
  245.                             MACAddress = $MACAddress
  246.                             OSVersion  = $OSVersion
  247.                         }
  248.                         $ResultsListView.Items.Add($Item)
  249.                     }
  250.  
  251.                 $StatusTextLabel.Content = "Scan Complete."
  252.             }
  253.         Catch
  254.             {
  255.                 $StatusTextLabel.Content = "Error occurred: $_"
  256.                 Write-Host "Error occurred: $_" -ForegroundColor Red
  257.             }
  258.     }
  259.  
  260.  
  261. Function Clear-Results
  262.     {
  263.         $ResultsListView.Items.Clear()
  264.         $StatusTextLabel.Content = "Status: Ready"
  265.         Write-Host "Results cleared."
  266.     }
  267.  
  268. #Event Handlers
  269. $ScanButton.Add_Click({
  270.     #Validate Subnet Format
  271.     $Subnet = $SubnetTextBox.Text
  272.     $SubnetRegex = '^\d{1,3}\.\d{1,3}\.\d{1,3}$'
  273.  
  274.     If (-not [string]::IsNullOrWhiteSpace($Subnet))
  275.         {
  276.             If ($Subnet -match $SubnetRegex)
  277.                 {
  278.                     Search-Network -Subnet $Subnet
  279.                 }
  280.             Else
  281.                 {
  282.                     $StatusTextLabel.Content = "Error: Invalid Subnet Format (e.g. 192.168.1)"
  283.                     Write-Host "Error: Invalid Subnet Format (e.g. 192.168.1)"
  284.                 }
  285.         }
  286.     Else
  287.         {
  288.             $StatusTextLabel.Content = "Error: Please enter a subnet."
  289.             Write-Host "Error: Please enter a subnet."
  290.         }
  291. })
  292. $ClearButton.Add_Click({ Clear-Results })
  293. $CloseButton.Add_Click({ $Window.Close() })
  294.  
  295. #Show the Window
  296. $Window.ShowDialog()
  297.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement