mqsft.networklocal.psm1

# ==============================================================================
# mqsft.networklocal.psm1 - AUTO-GENERATED by Create_Module_0_0_5.ps1 v0.0.5
# ------------------------------------------------------------------------------
# Module Version : 1.0.4
# Script Version : 0.0.5
# Built : 2026-02-24 17:12:41
# Source : C:\Modules\functions\mqsft.networklocal
#
# DO NOT EDIT THIS FILE DIRECTLY.
# Edit source files in C:\Modules\functions\mqsft.networklocal and re-run Create_Module_0_0_5.ps1.
# ==============================================================================

Set-StrictMode -Version Latest

# --- Source: Get-SubnetUsage.ps1 -----------------------------------------
function Get-SubnetUsage {

    param(

        [Parameter(ParameterSetName = "List")]

        [string[]]$IPList,



        [Parameter(ParameterSetName = "Range")]

        [string]$StartIP,



        [Parameter(ParameterSetName = "Range")]

        [string]$EndIP,



        [int]$CIDR = 24,

        [int]$TimeoutMs = 1000,

        [string]$ExportCSV

    )



    # ---- Internal: Subnet validation ----

    function _Test-SameSubnet {

        param([string]$IP1, [string]$IP2, [int]$CIDR)

        $addr1 = [System.Net.IPAddress]::Parse($IP1).GetAddressBytes()

        $addr2 = [System.Net.IPAddress]::Parse($IP2).GetAddressBytes()

        $mask = [uint32]0

        for ($i = 0; $i -lt $CIDR; $i++) { $mask = $mask -bor (1 -shl (31 - $i)) }

        $maskBytes = [BitConverter]::GetBytes([uint32]$mask)

        if ([BitConverter]::IsLittleEndian) { [Array]::Reverse($maskBytes) }

        $net1 = [byte[]]::new(4)

        $net2 = [byte[]]::new(4)

        for ($i = 0; $i -lt 4; $i++) {

            $net1[$i] = $addr1[$i] -band $maskBytes[$i]

            $net2[$i] = $addr2[$i] -band $maskBytes[$i]

        }

        return ($net1 -join '.') -eq ($net2 -join '.')

    }



    # ---- Internal: Ping a single IP ----

    function _Test-IPResponse {

        param([string]$IPAddress)

        try { return Test-Connection -ComputerName $IPAddress -Count 1 -Quiet -ErrorAction Stop }

        catch { return $false }

    }



    # ---- Internal: Scan and print a list of IPs ----

    function _Invoke-Scan {

        param([string[]]$IPs)

        $results = @()

        $online = 0; $offline = 0

        foreach ($ip in $IPs) {

            Write-Host "Scanning $ip... " -NoNewline

            if (_Test-IPResponse -IPAddress $ip) {

                Write-Host "ONLINE" -ForegroundColor Green

                $online++; $status = "Online"

            } else {

                Write-Host "OFFLINE" -ForegroundColor Red

                $offline++; $status = "Offline"

            }

            $results += [PSCustomObject]@{

                IPAddress = $ip

                Status    = $status

                Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"

            }

        }

        Write-Host "`n--- Summary ---"      -ForegroundColor Cyan

        Write-Host "Online: $online"       -ForegroundColor Green

        Write-Host "Offline: $offline"      -ForegroundColor Red

        return $results

    }



    # ---- Main logic ----

    switch ($PSCmdlet.ParameterSetName) {



        "List" {

            Write-Host "`n=== Scanning IP List ($($IPList.Count) hosts) ===" -ForegroundColor Cyan

            $results = _Invoke-Scan -IPs $IPList

        }



        "Range" {

            if (-not (_Test-SameSubnet -IP1 $StartIP -IP2 $EndIP -CIDR $CIDR)) {

                Write-Error "Start and End IPs must be in the same /$CIDR network."

                return

            }

            $octets  = $StartIP.Split('.')

            $network = $octets[0..2] -join '.'

            $start   = [int]$octets[3]

            $end     = [int]$EndIP.Split('.')[3]

            $ips     = $start..$end | ForEach-Object { "$network.$_" }



            Write-Host "`n=== Scanning Range $StartIP – $EndIP ($($ips.Count) hosts) ===" -ForegroundColor Cyan

            $results = _Invoke-Scan -IPs $ips

        }

    }



    # ---- Optional CSV export ----

    if ($ExportCSV) {

        $results | Export-Csv -Path $ExportCSV -NoTypeInformation

        Write-Host "`nResults exported to $ExportCSV" -ForegroundColor Yellow

    }



    return $results

}