mqsft.dnsexternal.psm1

# ==============================================================================
# mqsft.dnsexternal.psm1 - AUTO-GENERATED by Create_Module_0_0_7.ps1 v0.0.7
# ------------------------------------------------------------------------------
# Module Version : 1.0.4
# Script Version : 0.0.7
# Built : 2026-02-24 17:31:11
# Source : C:\Modules\functions\mqsft.dnsexternal
#
# DO NOT EDIT THIS FILE DIRECTLY.
# Edit source files in C:\Modules\functions\mqsft.dnsexternal and re-run Create_Module_0_0_7.ps1.
# ==============================================================================

Set-StrictMode -Version Latest

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

    <#

    .SYNOPSIS

        Analyzes complete mail infrastructure for domains - both inbound (MX) and outbound (SPF/DKIM/DMARC).

    

    .DESCRIPTION

        By default, performs comprehensive analysis of both inbound and outbound mail configuration:

        - INBOUND: MX records, mail servers, provider identification

        - OUTBOUND: SPF, DKIM, DMARC records and policies

        

        Use -InboundOnly or -OutboundOnly to focus on specific areas.

    

    .PARAMETER Domains

        Array of domain names to analyze. Supports subdomains.

    

    .PARAMETER InboundOnly

        Only check inbound mail configuration (MX records)

    

    .PARAMETER OutboundOnly

        Only check outbound mail configuration (SPF, DKIM, DMARC)

    

    .PARAMETER ExportPath

        Optional: Directory path to export reports (auto-generates filenames with timestamp)

    

    .PARAMETER IncludeIPInfo

        Resolve IP addresses for mail servers (slower but more detailed)

    

    .EXAMPLE

        Get-MailDomainInfrastructure -Domains "example.com","subdomain.example.com"

        Checks both inbound and outbound configuration

    

    .EXAMPLE

        Get-MailDomainInfrastructure -Domains "example.com" -InboundOnly

        Only checks MX records

    

    .EXAMPLE

        Get-MailDomainInfrastructure -Domains $domains -ExportPath "C:\Reports"

        Full analysis with exported reports

    

    .EXAMPLE

        Get-Content domains.txt | Get-MailDomainInfrastructure -OutboundOnly

        Only checks SPF, DKIM, and DMARC from file

    #>


    

    [CmdletBinding()]

    param(

        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]

        [string[]]$Domains,

        

        [switch]$InboundOnly,

        [switch]$OutboundOnly,

        [string]$ExportPath,

        [switch]$IncludeIPInfo

    )

    

    begin {

        # Determine what to check

        $CheckInbound = -not $OutboundOnly

        $CheckOutbound = -not $InboundOnly

        

        # Mail provider patterns

        $ProviderPatterns = @{

            'Microsoft 365' = @("*.mail.protection.outlook.com", "*.outlook.com", "*.office365.com")

            'Google Workspace' = @("*.google.com", "*.googlemail.com", "aspmx.l.google.com")

            'Proofpoint' = @("*.pphosted.com", "*.proofpoint.com")

            'Mimecast' = @("*.mimecast.com", "*.mimecast-offshore.com")

            'Barracuda' = @("*.barracudanetworks.com", "*.cuda-inc.com")

            'Cloudflare' = @("*.cloudflare.net")

            'Zoho Mail' = @("*.zoho.com", "*.zohomail.com")

            'Amazon SES' = @("*.amazonaws.com", "inbound-smtp.*.amazonaws.com")

            'GoDaddy' = @("*.secureserver.net", "*.godaddy.com")

            'Mailgun' = @("*.mailgun.org")

            'SendGrid' = @("*.sendgrid.net")

        }

        

        $AllResults = @()

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

        $FileTimestamp = Get-Date -Format "yyyyMMdd_HHmmss"

    }

    

    process {

        foreach ($Domain in $Domains) {

            Write-Host "`n[$Timestamp] Analyzing: $Domain" -ForegroundColor Cyan

            Write-Host ("=" * 80) -ForegroundColor DarkGray

            

            $DomainResult = [PSCustomObject]@{

                Timestamp = $Timestamp

                Domain = $Domain

                # Inbound

                MXRecords = @()

                MXCount = 0

                PrimaryProvider = "Unknown"

                AllProviders = @()

                # Outbound

                SPF = @{

                    Configured = $false

                    Record = ""

                    Analysis = ""

                }

                DKIM = @{

                    Configured = $false

                    Selectors = @()

                }

                DMARC = @{

                    Configured = $false

                    Policy = ""

                    Record = ""

                }

                # Status

                InboundStatus = "Not Checked"

                OutboundStatus = "Not Checked"

                Errors = @()

            }

            

            # ============================================

            # INBOUND MAIL CONFIGURATION (MX Records)

            # ============================================

            if ($CheckInbound) {

                Write-Host "`n INBOUND MAIL CONFIGURATION" -ForegroundColor Green

                Write-Host " " + ("-" * 50) -ForegroundColor DarkGray

                

                try {

                    $MXRecords = Resolve-DnsName -Name $Domain -Type MX -ErrorAction Stop | 

                        Where-Object { $_.Type -eq 'MX' }

                    

                    if ($MXRecords) {

                        $DomainResult.InboundStatus = "Configured"

                        $DomainResult.MXCount = $MXRecords.Count

                        $ProvidersFound = @()

                        

                        foreach ($MX in $MXRecords | Sort-Object Preference) {

                            $Provider = "Unknown/Custom"

                            

                            # Identify provider

                            foreach ($ProviderName in $ProviderPatterns.Keys) {

                                foreach ($Pattern in $ProviderPatterns[$ProviderName]) {

                                    if ($MX.NameExchange -like $Pattern) {

                                        $Provider = $ProviderName

                                        break

                                    }

                                }

                                if ($Provider -ne "Unknown/Custom") { break }

                            }

                            

                            if ($Provider -ne "Unknown/Custom" -and $Provider -notin $ProvidersFound) {

                                $ProvidersFound += $Provider

                            }

                            

                            # Get IP if requested

                            $IPAddress = $null

                            if ($IncludeIPInfo) {

                                try {

                                    $IPLookup = Resolve-DnsName -Name $MX.NameExchange -Type A -ErrorAction SilentlyContinue

                                    $IPAddress = ($IPLookup | Where-Object { $_.Type -eq 'A' } | Select-Object -First 1).IPAddress

                                }

                                catch { $IPAddress = "N/A" }

                            }

                            

                            $MXInfo = [PSCustomObject]@{

                                Priority = $MX.Preference

                                MailServer = $MX.NameExchange

                                Provider = $Provider

                                IPAddress = $IPAddress

                            }

                            

                            $DomainResult.MXRecords += $MXInfo

                            

                            $ProviderDisplay = if ($Provider -ne "Unknown/Custom") { "[$Provider]" } else { "" }

                            Write-Host " Priority $($MX.Preference): $($MX.NameExchange) $ProviderDisplay" -ForegroundColor White

                        }

                        

                        $DomainResult.PrimaryProvider = if ($ProvidersFound.Count -gt 0) { $ProvidersFound[0] } else { "Unknown/Custom" }

                        $DomainResult.AllProviders = $ProvidersFound

                        

                        Write-Host "`n āœ“ MX Records: $($MXRecords.Count) found" -ForegroundColor Green

                        Write-Host " āœ“ Primary Provider: $($DomainResult.PrimaryProvider)" -ForegroundColor Green

                    }

                    else {

                        $DomainResult.InboundStatus = "No MX Records"

                        Write-Host " āœ— No MX records found" -ForegroundColor Yellow

                    }

                }

                catch {

                    $DomainResult.InboundStatus = "Error"

                    $DomainResult.Errors += "MX: $($_.Exception.Message)"

                    Write-Host " āœ— Failed to resolve MX records: $($_.Exception.Message)" -ForegroundColor Red

                }

            }

            

            # ============================================

            # OUTBOUND MAIL CONFIGURATION

            # ============================================

            if ($CheckOutbound) {

                Write-Host "`n OUTBOUND MAIL CONFIGURATION" -ForegroundColor Magenta

                Write-Host " " + ("-" * 50) -ForegroundColor DarkGray

                

                # SPF Check

                Write-Host "`n SPF (Sender Policy Framework):" -ForegroundColor Yellow

                try {

                    $SPFRecord = Resolve-DnsName -Name $Domain -Type TXT -ErrorAction Stop | 

                        Where-Object { $_.Strings -match '^v=spf1' }

                    

                    if ($SPFRecord) {

                        $SPFString = $SPFRecord.Strings -join ""

                        $DomainResult.SPF.Configured = $true

                        $DomainResult.SPF.Record = $SPFString

                        

                        # Analyze SPF

                        $Analysis = @()

                        if ($SPFString -match '\+all') { $Analysis += "⚠ WARNING: Allows all senders (+all)" }

                        elseif ($SPFString -match '~all') { $Analysis += "āœ“ Soft fail configured (~all)" }

                        elseif ($SPFString -match '-all') { $Analysis += "āœ“ Hard fail configured (-all)" }

                        else { $Analysis += "⚠ No 'all' mechanism found" }

                        

                        $DomainResult.SPF.Analysis = $Analysis -join "; "

                        

                        Write-Host " āœ“ SPF Record Found" -ForegroundColor Green

                        Write-Host " Record: $SPFString" -ForegroundColor Gray

                        foreach ($note in $Analysis) {

                            Write-Host " $note" -ForegroundColor Gray

                        }

                    }

                    else {

                        Write-Host " āœ— No SPF record configured" -ForegroundColor Red

                        Write-Host " ⚠ Recommendation: Configure SPF to prevent email spoofing" -ForegroundColor Yellow

                    }

                }

                catch {

                    $DomainResult.Errors += "SPF: $($_.Exception.Message)"

                    Write-Host " āœ— Error checking SPF: $($_.Exception.Message)" -ForegroundColor Red

                }

                

                # DKIM Check (common selectors)

                Write-Host "`n DKIM (DomainKeys Identified Mail):" -ForegroundColor Yellow

                $CommonSelectors = @('default', 'google', 'k1', 'selector1', 'selector2', 'dkim', 'mail', 's1', 's2')

                $DKIMFound = @()

                

                foreach ($Selector in $CommonSelectors) {

                    try {

                        $DKIMDomain = "$Selector._domainkey.$Domain"

                        $DKIMRecord = Resolve-DnsName -Name $DKIMDomain -Type TXT -ErrorAction SilentlyContinue | 

                            Where-Object { $_.Strings -match 'v=DKIM1' }

                        

                        if ($DKIMRecord) {

                            $DKIMFound += $Selector

                        }

                    }

                    catch { }

                }

                

                if ($DKIMFound.Count -gt 0) {

                    $DomainResult.DKIM.Configured = $true

                    $DomainResult.DKIM.Selectors = $DKIMFound

                    Write-Host " āœ“ DKIM Records Found" -ForegroundColor Green

                    Write-Host " Selectors: $($DKIMFound -join ', ')" -ForegroundColor Gray

                }

                else {

                    Write-Host " āœ— No DKIM records found (checked common selectors)" -ForegroundColor Red

                    Write-Host " ℹ Note: DKIM may use custom selectors not checked" -ForegroundColor Gray

                }

                

                # DMARC Check

                Write-Host "`n DMARC (Domain-based Message Authentication):" -ForegroundColor Yellow

                try {

                    $DMARCDomain = "_dmarc.$Domain"

                    $DMARCRecord = Resolve-DnsName -Name $DMARCDomain -Type TXT -ErrorAction Stop | 

                        Where-Object { $_.Strings -match '^v=DMARC1' }

                    

                    if ($DMARCRecord) {

                        $DMARCString = $DMARCRecord.Strings -join ""

                        $DomainResult.DMARC.Configured = $true

                        $DomainResult.DMARC.Record = $DMARCString

                        

                        # Extract policy

                        if ($DMARCString -match 'p=(\w+)') {

                            $Policy = $matches[1]

                            $DomainResult.DMARC.Policy = $Policy

                            

                            $PolicyColor = switch ($Policy) {

                                'none' { 'Yellow' }

                                'quarantine' { 'Cyan' }

                                'reject' { 'Green' }

                                default { 'White' }

                            }

                            

                            Write-Host " āœ“ DMARC Policy Found" -ForegroundColor Green

                            Write-Host " Policy: $Policy" -ForegroundColor $PolicyColor

                            Write-Host " Record: $DMARCString" -ForegroundColor Gray

                        }

                    }

                    else {

                        Write-Host " āœ— No DMARC policy configured" -ForegroundColor Red

                        Write-Host " ⚠ Recommendation: Configure DMARC to protect against email spoofing" -ForegroundColor Yellow

                    }

                }

                catch {

                    $DomainResult.Errors += "DMARC: $($_.Exception.Message)"

                    Write-Host " āœ— Error checking DMARC: $($_.Exception.Message)" -ForegroundColor Red

                }

                

                # Overall outbound status

                $OutboundConfigured = $DomainResult.SPF.Configured -or $DomainResult.DKIM.Configured -or $DomainResult.DMARC.Configured

                $DomainResult.OutboundStatus = if ($OutboundConfigured) { "Configured" } else { "Not Configured" }

            }

            

            $AllResults += $DomainResult

        }

    }

    

    end {

        # ============================================

        # SUMMARY REPORT

        # ============================================

        Write-Host "`n`n" + ("=" * 80) -ForegroundColor Cyan

        Write-Host "MAIL DOMAIN INFRASTRUCTURE SUMMARY - $Timestamp" -ForegroundColor Cyan

        Write-Host ("=" * 80) -ForegroundColor Cyan

        

        $TotalDomains = $AllResults.Count

        

        if ($CheckInbound) {

            Write-Host "`nINBOUND CONFIGURATION:" -ForegroundColor Green

            $InboundConfigured = @($AllResults | Where-Object { $_.InboundStatus -eq "Configured" }).Count

            Write-Host " Total Domains: $TotalDomains"

            Write-Host " With MX Records: $InboundConfigured"

            Write-Host " Missing MX Records: $($TotalDomains - $InboundConfigured)"

            

            # Provider summary

            $Providers = $AllResults | Where-Object { $_.PrimaryProvider -ne "Unknown" -and $_.PrimaryProvider -ne "Unknown/Custom" } | 

                Group-Object PrimaryProvider | 

                Sort-Object Count -Descending

            

            if ($Providers) {

                Write-Host "`n Provider Distribution:"

                foreach ($Provider in $Providers) {

                    Write-Host " $($Provider.Name): $($Provider.Count) domain(s)" -ForegroundColor White

                }

            }

        }

        

        if ($CheckOutbound) {

            Write-Host "`nOUTBOUND CONFIGURATION:" -ForegroundColor Magenta

            $SPFConfigured = @($AllResults | Where-Object { $_.SPF.Configured }).Count

            $DKIMConfigured = @($AllResults | Where-Object { $_.DKIM.Configured }).Count

            $DMARCConfigured = @($AllResults | Where-Object { $_.DMARC.Configured }).Count

            

            Write-Host " Total Domains: $TotalDomains"

            Write-Host " With SPF: $SPFConfigured ($([math]::Round(($SPFConfigured/$TotalDomains)*100,1))%)"

            Write-Host " With DKIM: $DKIMConfigured ($([math]::Round(($DKIMConfigured/$TotalDomains)*100,1))%)"

            Write-Host " With DMARC: $DMARCConfigured ($([math]::Round(($DMARCConfigured/$TotalDomains)*100,1))%)"

            

            $FullyConfigured = @($AllResults | Where-Object { 

                $_.SPF.Configured -and $_.DKIM.Configured -and $_.DMARC.Configured 

            }).Count

            Write-Host "`n Fully Protected (SPF+DKIM+DMARC): $FullyConfigured ($([math]::Round(($FullyConfigured/$TotalDomains)*100,1))%)"

        }

        

        # Export if requested

        if ($ExportPath) {

            if (-not (Test-Path $ExportPath)) {

                New-Item -ItemType Directory -Path $ExportPath -Force | Out-Null

            }

            

            $DomainList = ($AllResults.Domain -join "_").Substring(0, [Math]::Min(50, ($AllResults.Domain -join "_").Length))

            $BaseFileName = "${DomainList}_${FileTimestamp}"

            

            # Export detailed results to CSV

            $CSVPath = Join-Path $ExportPath "${BaseFileName}_detailed.csv"

            $AllResults | Select-Object Timestamp, Domain, MXCount, PrimaryProvider, 

                @{N='SPF_Configured';E={$_.SPF.Configured}},

                @{N='SPF_Record';E={$_.SPF.Record}},

                @{N='DKIM_Configured';E={$_.DKIM.Configured}},

                @{N='DKIM_Selectors';E={$_.DKIM.Selectors -join ','}},

                @{N='DMARC_Configured';E={$_.DMARC.Configured}},

                @{N='DMARC_Policy';E={$_.DMARC.Policy}},

                InboundStatus, OutboundStatus |

                Export-Csv -Path $CSVPath -NoTypeInformation

            

            Write-Host "`nāœ“ Detailed report exported: $CSVPath" -ForegroundColor Green

            

            # Export MX records to separate CSV

            if ($CheckInbound) {

                $MXPath = Join-Path $ExportPath "${BaseFileName}_mx_records.csv"

                $AllResults | ForEach-Object {

                    $Domain = $_.Domain

                    $_.MXRecords | ForEach-Object {

                        [PSCustomObject]@{

                            Domain = $Domain

                            Priority = $_.Priority

                            MailServer = $_.MailServer

                            Provider = $_.Provider

                            IPAddress = $_.IPAddress

                        }

                    }

                } | Export-Csv -Path $MXPath -NoTypeInformation

                

                Write-Host "āœ“ MX records exported: $MXPath" -ForegroundColor Green

            }

        }

        

        Write-Host "`n" + ("=" * 80) -ForegroundColor Cyan

        

        # Return structured results

        return [PSCustomObject]@{

            Timestamp = $Timestamp

            Domains = $AllResults

            Summary = @{

                TotalDomains = $TotalDomains

                InboundConfigured = @($AllResults | Where-Object { $_.InboundStatus -eq "Configured" }).Count

                SPFConfigured = @($AllResults | Where-Object { $_.SPF.Configured }).Count

                DKIMConfigured = @($AllResults | Where-Object { $_.DKIM.Configured }).Count

                DMARCConfigured = @($AllResults | Where-Object { $_.DMARC.Configured }).Count

            }

        }

    }

}



# Quick usage examples:

<#

# Full analysis (default - both inbound and outbound)

Get-MailDomainInfrastructure -Domains "example.com","subdomain.example.com"



# Inbound only (MX records)

Get-MailDomainInfrastructure -Domains "example.com" -InboundOnly



# Outbound only (SPF/DKIM/DMARC)

Get-MailDomainInfrastructure -Domains "example.com" -OutboundOnly



# With exports

Get-MailDomainInfrastructure -Domains $domains -ExportPath "C:\MailReports"



# From file

Get-Content domains.txt | Get-MailDomainInfrastructure -ExportPath ".\Reports"



# Store results for further analysis

$Results = Get-MailDomainInfrastructure -Domains "example.com","test.com"

$Results.Summary

$Results.Domains | Where-Object { $_.PrimaryProvider -eq "Microsoft 365" }

#>

# --- Source: Monitor-NameServerChange.ps1 --------------------------------
function Monitor-NameServerChange {

<#

.SYNOPSIS

Monitors a domain for DNS nameserver (NS) record changes.



.DESCRIPTION

Continuously queries the specified domain for NS records and compares them

against the initial baseline set retrieved at startup.



The function will loop at a defined interval until:

- A change in nameservers is detected (returns $true), or

- The optional maximum number of checks is reached (returns $false).



Useful for:

- Tracking DNS propagation

- Monitoring domain migrations

- Validating registrar or hosting changes

- Change verification during cutovers



.PARAMETER Domain

The domain name to monitor (e.g. example.com).



This parameter is mandatory.



.PARAMETER CheckInterval

Number of seconds between DNS checks.



Default value is 10 seconds.



.PARAMETER MaxChecks

Maximum number of checks before stopping.



Default is 0, which means run indefinitely until a change is detected.



.PARAMETER ShowProgress

If specified, displays the current nameserver values during each check.



.EXAMPLE

Monitor-NameServerChange -Domain example.com



Monitors example.com every 10 seconds until a nameserver change is detected.



.EXAMPLE

Monitor-NameServerChange -Domain example.com -CheckInterval 30 -ShowProgress



Checks every 30 seconds and displays current NS records each cycle.



.EXAMPLE

Monitor-NameServerChange -Domain example.com -MaxChecks 20



Checks up to 20 times, then exits if no change is detected.



.OUTPUTS

System.Boolean



Returns:

- $true if a nameserver change is detected

- $false if maximum checks are reached or initial lookup fails



.NOTES

Author: Mike Quick

Requires: Resolve-DnsName (PowerShell 4.0+)

Intended for DNS monitoring and change validation scenarios.



#>




    [CmdletBinding()]

    param(

        [Parameter(Mandatory=$true)]

        [string]$Domain,

        

        [Parameter(Mandatory=$false)]

        [int]$CheckInterval = 10,

        

        [Parameter(Mandatory=$false)]

        [int]$MaxChecks = 0,

        

        [Parameter(Mandatory=$false)]

        [switch]$ShowProgress

    )

    

    Write-Host "Starting nameserver monitoring for: $Domain" -ForegroundColor Cyan

    Write-Host "Check interval: $CheckInterval seconds" -ForegroundColor Cyan

    Write-Host ""

    

    # Get initial nameservers

    Write-Host "Getting initial nameservers..." -ForegroundColor Yellow

    

    try {

        $nsRecords = Resolve-DnsName -Name $Domain -Type NS -ErrorAction Stop

        $baselineNS = $nsRecords | 

            Where-Object { $_.Type -eq 'NS' } | 

            Select-Object -ExpandProperty NameHost | 

            ForEach-Object { $_.TrimEnd('.').ToLower() } |

            Sort-Object -Unique

    }

    catch {

        Write-Host "ERROR: Could not retrieve initial nameservers for $Domain" -ForegroundColor Red

        Write-Host "Error: $_" -ForegroundColor Red

        return $false

    }

    

    if (-not $baselineNS) {

        Write-Host "ERROR: No nameservers found for $Domain" -ForegroundColor Red

        return $false

    }

    

    Write-Host "Baseline nameservers (watching for changes):" -ForegroundColor Yellow

    $baselineNS | ForEach-Object { Write-Host " - $_" -ForegroundColor White }

    Write-Host ""

    Write-Host "Monitoring for changes..." -ForegroundColor Cyan

    Write-Host ""

    

    $checkCount = 0

    $startTime = Get-Date

    

    # Monitoring loop

    while ($true) {

        $checkCount++

        $currentTime = Get-Date

        $elapsed = $currentTime - $startTime

        

        # Query current nameservers

        try {

            $nsRecords = Resolve-DnsName -Name $Domain -Type NS -ErrorAction Stop

            $currentNS = $nsRecords | 

                Where-Object { $_.Type -eq 'NS' } | 

                Select-Object -ExpandProperty NameHost | 

                ForEach-Object { $_.TrimEnd('.').ToLower() } |

                Sort-Object -Unique

        }

        catch {

            Write-Host "[$checkCount] $(Get-Date -Format 'HH:mm:ss') - Failed to query nameservers" -ForegroundColor Red

            $currentNS = $null

        }

        

        if ($null -eq $currentNS) {

            # Continue on error

        }

        else {

            # Compare nameservers

            $match = ($currentNS.Count -eq $baselineNS.Count) -and 

                     ($baselineNS | ForEach-Object { $_ -in $currentNS } | Where-Object { -not $_ }).Count -eq 0

            

            if (-not $match) {

                # Change detected!

                Write-Host ""

                Write-Host "SUCCESS! Nameserver change detected!" -ForegroundColor Green

                Write-Host "Domain: $Domain" -ForegroundColor Green

                Write-Host ""

                Write-Host "Original nameservers:" -ForegroundColor Yellow

                $baselineNS | ForEach-Object { Write-Host " - $_" -ForegroundColor White }

                Write-Host ""

                Write-Host "New nameservers:" -ForegroundColor Green

                $currentNS | ForEach-Object { Write-Host " - $_" -ForegroundColor White }

                Write-Host ""

                Write-Host "Total checks: $checkCount" -ForegroundColor Cyan

                Write-Host "Total time elapsed: $($elapsed.ToString('hh\:mm\:ss'))" -ForegroundColor Cyan

                Write-Host "Change detected at: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Cyan

                return $true

            }

            else {

                $status = "[$checkCount] $(Get-Date -Format 'HH:mm:ss') - No change detected"

                

                if ($ShowProgress) {

                    Write-Host $status -ForegroundColor Gray

                    Write-Host " Current: $($currentNS -join ', ')" -ForegroundColor DarkGray

                }

                else {

                    Write-Host $status -ForegroundColor Gray

                }

            }

        }

        

        # Check if max checks reached

        if ($MaxChecks -gt 0 -and $checkCount -ge $MaxChecks) {

            Write-Host ""

            Write-Host "Maximum checks ($MaxChecks) reached without detecting change" -ForegroundColor Red

            Write-Host "Total time elapsed: $($elapsed.ToString('hh\:mm\:ss'))" -ForegroundColor Cyan

            return $false

        }

        

        Start-Sleep -Seconds $CheckInterval

    }

}