Entrinsec.Powershell.SETUP.psm1

#Requires -Version 7.0

<#
.SYNOPSIS
    SETUP module for Entrinsec PowerShell framework and module management.
 
.DESCRIPTION
    Provides setup, configuration, and module management functions for Entrinsec PowerShell modules.
    Includes functions for managing NuGet sources, importing Entrinsec modules, and displaying module information.
 
.NOTES
    Author : Entrinsec
    Identity : Entrinsec
    Created : 2026-01-22
    Updated : 2026-01-22 19:14
    Version : 1.15.56
    License : MIT
 
.EXAMPLE
    Import-Module Entrinsec.Powershell.SETUP
    Use SETUP module functions
#>


$SetupVersion = '1.15.78'

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Set-SetupVersion {
    param (
        [string]$SetupVersion
    )

    # Check if the user is an administrator
    if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
        Write-Host "You need to run this as an administrator." -ForegroundColor Red
        return
    }
    
    $registryPath = "HKLM:\SOFTWARE\Entrinsec\SETUP"
    $name = "Version"

    try {
        # Check if registry path exists, create if not
        if (-not (Test-Path $registryPath)) {
            New-Item -Path $registryPath -Force | Out-Null
        }

        # Set the registry value
        Set-ItemProperty -Path $registryPath -Name $name -Value $SetupVersion -Type String -Force
        Write-Host "Successfully set $name to $SetupVersion in $registryPath" -ForegroundColor Green
    } catch {
        Write-Host "Failed to set $name to $SetupVersion in $registryPath. Error: $_" -ForegroundColor Red
    }
}

Set-SetupVersion $SetupVersion

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Test-EntrinsecNugetSource {
    try {
        # Check if Entrinsec source exists and remove it if it does
        $sourceName = "Entrinsec"
        $existingSource = nuget sources list | Select-String -Pattern $sourceName

        if ($existingSource) {
            Write-Host "Checking Entrinsec NuGet source..." -ForegroundColor Cyan
            nuget sources list
            Write-Host "Entrinsec NuGet source found." -ForegroundColor Green
            return
        }

        nuget sources add -name $sourceName -source "https://nuget.entrinsec.com/api/packages/Entrinsec/nuget/index.json"

        # List all nuget sources
        nuget sources list
    } catch {
        Write-Host "Failed to add Entrinsec NuGet source. Error: $_" -ForegroundColor Red
    }
}

Test-EntrinsecNugetSource

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Show-EntrinsecSETUPInfo {

    # Get the name of the current module (the module this function is part of)
    $PackageName = $MyInvocation.MyCommand.ModuleName

    # Get the currently installed module version
    $installedVersion = (Get-Module -Name $PackageName -ListAvailable).Version
    Write-Host ""
    Write-Host "$PackageName $installedVersion imported." -ForegroundColor Blue
    Write-Host "All official MIT licensed Powershell modules can be found at https://www.entrinsec.com" -ForegroundColor Blue
    Write-Host ""
}

# Show-EntrinsecINFO

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Show-EntrinsecLicenseInfoSETUP {
    $message = @(
        "Entrinsec modules and the functions contained in them are licensed under the MIT License.",
        "For more information, please visit:",
        "https://docs.entrinsec.com/BaGet/Entrinsec-License/"
    )

    $maxLength = ($message | Measure-Object -Maximum Length).Maximum
    $border = "*" * ($maxLength + 4)

    Write-Host $border -ForegroundColor White
    foreach ($line in $message) {
        if ($line -eq "https://docs.entrinsec.com/BaGet/Entrinsec-License/") {
            Write-Host "* " -ForegroundColor White -NoNewline
            Write-Host "$line" -ForegroundColor Blue -NoNewline
            Write-Host (" " * ($maxLength - $line.Length)) -NoNewline
            Write-Host " *" -ForegroundColor White
        } else {
            Write-Host "* " -ForegroundColor White -NoNewline
            Write-Host "$line" -ForegroundColor DarkCyan -NoNewline
            Write-Host (" " * ($maxLength - $line.Length)) -NoNewline
            Write-Host " *" -ForegroundColor White
        }
    }
    Write-Host $border -ForegroundColor White
    Write-Host ""
}

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Find-EntrinsecFunction {
    param(
        [Parameter(Mandatory=$true)]
        [string]$Search
    )
    $modules = Get-Module Entrinsec.Powershell.* -ListAvailable
    $results = @()
    foreach ($mod in $modules) {
        $funcs = (Get-Command -Module $mod.Name -CommandType Function | Where-Object { $_.Name -like $Search })
        foreach ($f in $funcs) {
            $synopsis = ($f | Get-Help).Synopsis
            $results += [PSCustomObject]@{
                Module      = $mod.Name
                Function    = $f.Name
                Synopsis    = $synopsis
            }
        }
    }
    if ($results.Count -eq 0) {
        Write-Host "No matching functions found." -ForegroundColor Yellow
    } else {
        $results | Sort-Object Module, Function | Format-Table Module, Function, Synopsis -AutoSize
    }
}

# Function to install NuGet.exe
<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Get-EntrinsecSetupFunctions {
    param (
        [Parameter(Mandatory = $false)]
        [string]$ModuleName = 'Entrinsec.Powershell.SETUP'
    )
    # If a single word is provided, assume Entrinsec.Powershell.<word>
    if ($ModuleName -notmatch '^Entrinsec\.Powershell\.' -and $ModuleName -notmatch '^entrinsec\.powershell\.') {
        $ModuleName = "Entrinsec.Powershell.$ModuleName"
    }
    $module = Get-Module $ModuleName
    if (-not $module) {
        $module = Import-Module $ModuleName -PassThru -DisableNameChecking -ErrorAction SilentlyContinue
        if (-not $module) {
            Write-Host "Module '$ModuleName' could not be imported or found." -ForegroundColor Red
            return
        }
    }
    Write-Host "Module Name: $ModuleName" -ForegroundColor Cyan
    $rows = foreach ($cmd in $module.ExportedCommands.Values) {
        $help = Get-Help $cmd.Name
        [PSCustomObject]@{
            'Function Name' = $cmd.Name
            'Synopsis'      = $help.Synopsis
        }
    }
    $rows | Format-Table -AutoSize
}

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Install-Nuget {

    # Check if nuget.exe can be launched and hide the output
    try {
        $null = nuget.exe help  # This command will run nuget.exe help and discard the output
        Write-Host "nuget.exe is accessible and can be launched."
        return 0
    } catch {
        Write-Host "nuget.exe cannot be launched. Please check your PATH and the existence of nuget.exe." -ForegroundColor Red
        Write-Host "Attempting to install nuget.exe..." -ForegroundColor Yellow
    }

    # Set the installation directory
    $installDir = "C:\Program Files\Nuget"
    $nugetExePath = Join-Path -Path $installDir -ChildPath "nuget.exe"

    # Check if nuget.exe already exists in the installation directory
    if (Test-Path -Path $nugetExePath) {
        Write-Host "nuGet.exe exists at $nugetExePath"
        Write-Host "Close this Powershell session and re-launch to use the installed nuget.exe." -ForegroundColor Yellow
        return 1 # Exit the function
    }

    # Create the installation directory if it doesn't exist
    if (!(Test-Path -Path $installDir)) {
        New-Item -ItemType Directory -Path $installDir -Force
    }

    # Downloading Nuget from the official website
    Write-Host "Installing NuGet from the official source..." -ForegroundColor Green

    # Download nuget.exe from the official website
    $nugetUrl = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
    Invoke-WebRequest -Uri $nugetUrl -OutFile $nugetExePath

    # Add the installation directory to the system PATH if it's not already present
    $pathEnv = [Environment]::GetEnvironmentVariable("PATH", "Machine")
    if (-not ($pathEnv -like "*$installDir*")) {
        $newPathEnv = $installDir + ";" + $pathEnv
        [Environment]::SetEnvironmentVariable("PATH", $newPathEnv, "Machine")
    }

    Write-Host "NuGet.exe installed successfully at $nugetExePath"
    Write-Host "Close this Powershell session and re-launch to use the installed nuget.exe." -ForegroundColor Yellow
    return 1

}

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Clear-NuGetCache {
  
    # Check if dotnet is installed and accessible.
    if (Get-Command dotnet -ErrorAction SilentlyContinue) {
      # Suppress all errors from dotnet command.
      try {
        dotnet nuget locals all --clear | Out-Null
      }
      catch {
        # Ignore any errors from the dotnet command.
      }
    } 
  
    # Get the user's profile directory.
    $userProfile = [Environment]::GetFolderPath([Environment+SpecialFolder]::UserProfile)
  
    # Define the cache directories.
    $cacheDirectories = @(
      "$userProfile\AppData\Local\NuGet\v3-cache"
      "$userProfile\.nuget\packages"
      "$userProfile\AppData\Local\Temp\NuGetScratch"
      "$userProfile\AppData\Local\NuGet\plugins-cache"
    )
  
    # Clear each cache directory.
    foreach ($dir in $cacheDirectories) {
      if (Test-Path -Path $dir) {
        Write-Host "Clearing NuGet cache: $dir"
        Remove-Item -Path "$dir\*" -Recurse -Force -ErrorAction SilentlyContinue
      }
    }
  
    Write-Host "Local resources cleared."
}
  
<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Add-EntrinsecNugetSource {

    # Set the module path (you might want to make this configurable)
    $modulePath = "C:\Program Files\PowerShell\Modules" 
    Set-Location -Path "$modulePath"

    # Source name and URL
    $sourceName = "Entrinsec"
    $sourceUrl = "https://nuget.entrinsec.com/api/packages/Entrinsec/nuget/index.json"

    # Check if the source already exists and remove it
    $existingSource = nuget sources list | Select-String -Pattern $sourceName
    if ($existingSource) {
        nuget sources remove -Name $sourceName
    }

    # Add the Entrinsec NuGet source
    nuget sources add -Name $sourceName -Source $sourceUrl

    # List all NuGet sources
    nuget sources list
}

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Install-EntrinsecCORE {
    [CmdletBinding()]
    param(
        [switch]$Silent = $false 
    )

    # Function to write output only if $Silent is not true
    function Write-Output {
        param(
            [string]$Message,
            [System.ConsoleColor]$ForegroundColor = 'White'
        )
        if (-not $Silent) {
            Write-Host $Message -ForegroundColor $ForegroundColor
        }
    }

    # $command = "nuget locals all -clear"
    # Write-Output "Clearing all NuGet caches..." -ForegroundColor Yellow
    # Invoke-Expression $command
    # Write-Output "NuGet caches cleared." -ForegroundColor Green

    Write-Output ""

    try {
        if (-not (Get-Module -ListAvailable -Name BurntToast)) {
            Install-Module -Name BurntToast -Repository PSGallery -AllowClobber -Force -ErrorAction Stop -Scope AllUsers
        }
        Write-Output "BurntToast module is available." -ForegroundColor Green
    }
    catch {
        Write-Host "BurntToast module could not be installed." -ForegroundColor Red
        Write-Host "Cannot continue installing Entrinsec modules without BurntToast." -ForegroundColor Red
        exit
    }
    
    # Set the output directory for the modules
    $outputDir = "C:\Program Files\PowerShell\Modules"

    $modules = @(
        "Entrinsec.Powershell.Common"
    )
    
    # Define the output directory
    $outputDir = "C:\Program Files\PowerShell\Modules"

    # Install and import each module
    foreach ($module in $modules) {
        Write-Output ""
        Write-Output "Installing module $module..." -ForegroundColor Cyan
        if (-not $Silent) {
            # Execute nuget.exe with output
            & "C:\Program Files\Nuget\nuget.exe" install $module -Source "Entrinsec" -OutputDirectory $outputDir -ExcludeVersion
        } else {
            # Execute nuget.exe silently
            & "C:\Program Files\Nuget\nuget.exe" install $module -Source "Entrinsec" -OutputDirectory $outputDir -ExcludeVersion *> $null
        }
    
        # Push current location onto the stack
        Push-Location
    
        # Change to the module directory
        Set-Location $outputDir\$module
    
        Write-Output "Importing module $module..." -ForegroundColor White
        try {
            Import-Module $module -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -DisableNameChecking # Use relative path
          }
          catch {
            try {
              Write-Warning "Failed to import module using relative path. Trying with './'."
              Import-Module .\$module -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -DisableNameChecking # Use explicit relative path
            }
            catch {
              Write-Error "Failed to import module '$module' using both relative paths."
            }
          }
        Write-Output ""
    
        # Pop the original location from the stack
        Pop-Location 
    }

    try {
        Write-Output ""
        Write-Output "Installing Entrinsec.Powershell.SETUP module from PSGallery..." -ForegroundColor Green
        Install-Module -Name Entrinsec.Powershell.SETUP -Repository PSGallery -AllowClobber -Force -ErrorAction SilentlyContinue -Scope AllUsers *>$null
        Import-Module Entrinsec.Powershell.SETUP -Force -DisableNameChecking -ErrorAction SilentlyContinue *>$null
        Write-Output ""
    }
    catch {
    }
    
    # Enumerate the modules folder and import any module starting with Entrinsec.Powershell
    Get-ChildItem -Path $outputDir -Directory | ForEach-Object {
        if ($_.Name -like "Entrinsec.Powershell*") {
            Import-Module $_.FullName -DisableNameChecking
        }
    }

    # Run a test with Show-ToastNotification
    # Show-ToastNotification -Title "Entrinsec Powershell" -Information "You have successfully installed the Core Entrinsec Powershell modules!"
}

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Update-EntrinsecEVERYTHING {
    Install-EntrinsecEVERYTHING
}

function Update-EntrinsecCORE {
    Install-EntrinsecCORE
}

function Update-EntrinsecENTERPRISE {
    Install-EntrinsecENTERPRISE
}

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Install-EntrinsecEVERYTHING {
    [CmdletBinding()]
    param(
        [switch]$Silent = $false
    )

    # Function to write output only if $Silent is not true
    function Write-Output {
        param(
            [string]$Message,
            [System.ConsoleColor]$ForegroundColor = 'White'
        )
        if (-not $Silent) {
            Write-Host $Message -ForegroundColor $ForegroundColor
        }
    }

    # $command = "nuget locals all -clear"
    # Write-Output "Clearing all NuGet caches..." -ForegroundColor Yellow
    # Invoke-Expression $command
    # Write-Output "NuGet caches cleared." -ForegroundColor Green
    
    Write-Output ""

    try {
        if (-not (Get-Module -ListAvailable -Name BurntToast)) {
            Install-Module -Name BurntToast -Repository PSGallery -AllowClobber -Force -ErrorAction Stop -Scope AllUsers
        }
        Write-Output "BurntToast module is available." -ForegroundColor Green
    }
    catch {
        Write-Host "BurntToast module could not be installed." -ForegroundColor Red
        Write-Host "Cannot continue installing Entrinsec modules without BurntToast." -ForegroundColor Red
        exit
    }

    # Set the output directory for the modules
    $outputDir = "C:\Program Files\PowerShell\Modules"

    # Define the list of modules
    $modules = @(
        "Entrinsec.Powershell.ADO",
        "Entrinsec.Powershell.Common",
        "Entrinsec.Powershell.Containers",
        "Entrinsec.Powershell.Data",
        "Entrinsec.Powershell.Directories",
        "Entrinsec.Powershell.Email",
        "Entrinsec.Powershell.Endpoint",
        "Entrinsec.Powershell.Forensics",
        "Entrinsec.Powershell.Gaming",
        "Entrinsec.Powershell.Geography",
        "Entrinsec.Powershell.GIT",
        "Entrinsec.Powershell.Identity",
        "Entrinsec.Powershell.Networking",
        "Entrinsec.Powershell.Software",
        "Entrinsec.Powershell.SCCM",
        "Entrinsec.Powershell.Scheduling",
        "Entrinsec.Powershell.SQL"
    )

    # Define the output directory
    $outputDir = "C:\Program Files\PowerShell\Modules"

    # Install and import each module
    foreach ($module in $modules) {
        Write-Output ""
        Write-Output "Installing module $module..." -ForegroundColor Cyan
        if (-not $Silent) {
            # Execute nuget.exe with output
            & "C:\Program Files\Nuget\nuget.exe" install $module -Source "Entrinsec" -OutputDirectory $outputDir -ExcludeVersion
        } else {
            # Execute nuget.exe silently
            & "C:\Program Files\Nuget\nuget.exe" install $module -Source "Entrinsec" -OutputDirectory $outputDir -ExcludeVersion *> $null
        }
    
        # Push current location onto the stack
        Push-Location
    
        # Change to the module directory
        Set-Location $outputDir\$module
    
        Write-Output "Importing module $module..." -ForegroundColor White
        try {
            Import-Module $module -Force -DisableNameChecking -ErrorAction SilentlyContinue -WarningAction SilentlyContinue # Use relative path
          }
          catch {
            try {
              Write-Warning "Failed to import module using relative path. Trying with './'."
              Import-Module .\$module -Force -DisableNameChecking -ErrorAction SilentlyContinue -WarningAction SilentlyContinue # Use explicit relative path
            }
            catch {
              Write-Error "Failed to import module '$module' using both relative paths."
            }
          }
        Write-Output ""
    
        # Pop the original location from the stack
        Pop-Location 
    }

    try {
        Write-Output ""
        Write-Output "Installing Entrinsec.Powershell.SETUP module from PSGallery..." -ForegroundColor Green
        Install-Module -Name Entrinsec.Powershell.SETUP -Repository PSGallery -AllowClobber -Force -ErrorAction SilentlyContinue -Scope AllUsers *>$null
        Import-Module Entrinsec.Powershell.SETUP -Force -DisableNameChecking -ErrorAction SilentlyContinue *>$null         
        Write-Output ""
    }
    catch {
    }

    # Enumerate the modules folder and import any module starting with Entrinsec.Powershell
    Get-ChildItem -Path $outputDir -Directory | ForEach-Object {
        if ($_.Name -like "Entrinsec.Powershell*") {
            Import-Module $_.FullName -DisableNameChecking
        }
    }

    # Run a test with Show-ToastNotification
    # Show-ToastNotification -Title "Entrinsec Powershell" -Information "You have successfully installed all currently available Entrinsec Powershell modules!"
}

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Initialize-EntrinsecNuget {

    param (
        [switch]$CORE = $false,
        [switch]$ENTERPRISE = $false,
        [switch]$EVERYTHING = $false
    )

    # Check if the user is an administrator
    if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
        Write-Host "You need to run this as an administrator." -ForegroundColor Red
        return
    }

    # Ensure 'C:\Program Files\PowerShell\Modules' is at the start of the System PSModulePath
    try {
        $requiredPath = 'C:\Program Files\PowerShell\Modules'
        $sysPSModulePath = [Environment]::GetEnvironmentVariable('PSModulePath', 'Machine')
        if ($sysPSModulePath) {
            $paths = $sysPSModulePath -split ';'
            if ($paths[0] -ne $requiredPath) {
                $paths = $paths | Where-Object { $_ -ne $requiredPath -and $_ -ne '' }
                $newValue = ($requiredPath + ';' + ($paths -join ';')).TrimEnd(';')
                [Environment]::SetEnvironmentVariable('PSModulePath', $newValue, 'Machine')
                Write-Host "Prepended $requiredPath to System PSModulePath." -ForegroundColor Green
            } else {
                Write-Host "$requiredPath is already at the start of System PSModulePath." -ForegroundColor Green
            }
        } else {
            [Environment]::SetEnvironmentVariable('PSModulePath', $requiredPath, 'Machine')
            Write-Host "System PSModulePath was empty. Set to $requiredPath." -ForegroundColor Yellow
        }
    } catch {
        Write-Host "Failed to update System PSModulePath. Error: $_" -ForegroundColor Red
    }

    Write-Host "Setting up the Entrinsec PowerShell environment..." -ForegroundColor Cyan
    Write-Host "(Setup version : $SetupVersion)" -ForegroundColor Cyan
    if ($CORE) {
        Write-Host "Installing CORE Entrinsec modules..." -ForegroundColor Cyan
    } elseif ($ENTERPRISE) {
        Write-Host "Installing ENTERPRISE Entrinsec modules..." -ForegroundColor Cyan
    } elseif ($EVERYTHING) {
        Write-Host "Installing ALL Entrinsec modules..." -ForegroundColor Cyan
    } else {
        Write-Host "Installing CORE Entrinsec modules..." -ForegroundColor Cyan
    }
    Write-Host ""

    Show-EntrinsecLicenseInfoSETUP

    $NugetTest = Install-Nuget
    if ($NugetTest -ne 0) {
        Write-Host "NuGet installed. Need to exit this session and re-launch." -ForegroundColor Yellow
        pause
        exit
    }

    Write-Host ""

    # Adding the Entrinsec NuGet source
    Write-Host "Adding the Entrinsec NuGet source..." -ForegroundColor Green
    Add-EntrinsecNugetSource

    Write-Host ""

    # Cleaning up previous Entrinsec modules
    Remove-EntrinsecModules

    # Installing core Entrinsec modules as an example and a starting point
    if ($CORE) {
        Write-Host ""
        Write-Host "Installing core Entrinsec modules..." -ForegroundColor Green
        Install-EntrinsecCORE
        Write-Host ""
    } elseif ($ENTERPRISE) {
        Write-Host ""
        Write-Host "Installing Enterprise Entrinsec modules..." -ForegroundColor Green
        Install-EntrinsecENTERPRISE
        Write-Host ""
    } elseif ($EVERYTHING) {
        Write-Host ""
        Write-Host "Installing all Entrinsec modules..." -ForegroundColor Green
        Install-EntrinsecEVERYTHING
        Write-Host ""
    } else {
        Write-Host ""
        Write-Host "Installing core Entrinsec modules..." -ForegroundColor Green
        Install-EntrinsecCORE
        Write-Host ""
    }

    Write-Host ""
    Write-Host "Entrinsec PowerShell environment setup completed." -ForegroundColor Green
    Write-Host "It is recommended that you close any existing Powershell sessions to apply changes." -ForegroundColor Green
    Write-Host ""
}

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Remove-EntrinsecModules {
    param (
        [switch]$Test
    )

    Set-SetupVersion '0.0.0'

    Write-Host "Cleanup of Entrinsec modules, folders, and references..." -ForegroundColor Green
    Write-Host "Removing all Entrinsec modules, folders, and references from the local machine..." -ForegroundColor Yellow

    # Get all installed modules
    $modules = Get-Module -ListAvailable | Where-Object { $_.Name -like "Entrinsec.Powershell.*" }

    # Uninstall each module or perform a WhatIf
    foreach ($module in $modules) {
        if ($Test) {
            Uninstall-Module -Name $module.Name -Force -AllVersions -WhatIf -ErrorAction SilentlyContinue
        } else {
            Write-Host "Uninstalling $($module.Name)..." -ForegroundColor Yellow
            Uninstall-Module -Name $module.Name -Force -AllVersions -ErrorAction SilentlyContinue
        }
    }

    # Remove cached and memory-resident modules
    $loadedModules = Get-Module | Where-Object { $_.Name -like "Entrinsec.Powershell.*" }
    foreach ($loadedModule in $loadedModules | Where-Object { $_.Name -ne "Entrinsec.Powershell.SETUP" }) {
        if ($Test) {
            Write-Host "Would remove loaded module $($loadedModule.Name)" -ForegroundColor Yellow
        } else {
            Write-Host "Removing loaded module $($loadedModule.Name)..." -ForegroundColor Yellow
            Remove-Module -Name $loadedModule.Name -Force -ErrorAction SilentlyContinue
        }
    }

    # Define paths to check
    $paths = @(
        "C:\Program Files\PowerShell\Modules",
        "C:\Program Files\PowerShell\7\Modules",
        "C:\Program Files\PowerShell\Modules",
        "$env:USERPROFILE\Documents\WindowsPowerShell\Modules",
        "$env:ProgramFiles\WindowsPowerShell\Modules",
        "$env:ProgramFiles(x86)\WindowsPowerShell\Modules"
    )

    # Remove corresponding folders or perform a WhatIf
    foreach ($path in $paths) {
        if (Test-Path -Path $path) {
            if ($Test) {
                Get-ChildItem -Path $path -Directory |
                Where-Object { $_.Name -like "Entrinsec.Powershell.*" } |
                Remove-Item -Recurse -Force -WhatIf -ErrorAction SilentlyContinue
            } else {
                Write-Host "Removing all Entrinsec modules from folder $($path)..." -ForegroundColor Yellow
                Get-ChildItem -Path $path -Directory |
                Where-Object { $_.Name -like "Entrinsec.Powershell.*" } |
                Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
            }
        }
    }

    Write-Host "All Entrinsec.Powershell.* modules, folders, and references have been processed on the local machine." -ForegroundColor Yellow
    Write-Host "Clearing NuGet cache." -ForegroundColor Yellow
    Clear-NuGetCache -erroraction SilentlyContinue -warningaction SilentlyContinue | out-null
}

<#
.SYNOPSIS
Copies Entrinsec PowerShell modules from the local machine to a remote machine.
 
.DESCRIPTION
Copies BurntToast and Entrinsec.Powershell.* modules from a local source folder to a target folder on the specified remote machine using PowerShell remoting.
 
.PARAMETER MachineName
Target machine name or address for the remote session.
 
.PARAMETER SourcePowerShellFolder
Local folder path that contains the modules to copy.
 
.PARAMETER TargetPowerShellFolder
Destination folder path on the remote machine.
#>

function Copy-EntrinsecToRemoteMachine {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)]
        [string]$MachineName,

        [Parameter(Mandatory=$true)]
        [string]$SourcePowerShellFolder,

        [Parameter(Mandatory=$true)]
        [string]$TargetPowerShellFolder
    )

    if (-not (Test-Path -Path $SourcePowerShellFolder)) {
        throw "Source path not found: $SourcePowerShellFolder"
    }

    $modulePatterns = @("BurntToast", "BurtToast", "Entrinsec.Powershell.*")
    $session = $null

    try {
        $session = New-PSSession -ComputerName $MachineName -ErrorAction Stop

        Invoke-Command -Session $session -ScriptBlock {
            param($Target)
            if (-not (Test-Path -Path $Target)) {
                New-Item -ItemType Directory -Path $Target -Force | Out-Null
            }
        } -ArgumentList $TargetPowerShellFolder

        foreach ($pattern in $modulePatterns) {
            $modulesToCopy = Get-ChildItem -Path $SourcePowerShellFolder -Directory -ErrorAction SilentlyContinue |
                Where-Object { $_.Name -like $pattern }

            foreach ($module in $modulesToCopy) {
                Copy-Item -Path $module.FullName -Destination $TargetPowerShellFolder -Recurse -Force -ToSession $session
                Write-Host "Copied $($module.Name) to ${MachineName}:${TargetPowerShellFolder}" -ForegroundColor Green
            }
        }
    }
    catch {
        Write-Error "Failed to copy modules to $MachineName. $_"
    }
    finally {
        if ($session) {
            Remove-PSSession -Session $session
        }
    }
}

<#
.SYNOPSIS
Copies Entrinsec PowerShell modules from a remote machine to the local machine.
 
.DESCRIPTION
Copies BurntToast and Entrinsec.Powershell.* modules from a remote source folder to a local target folder using PowerShell remoting.
 
.PARAMETER MachineName
Target machine name or address for the remote session.
 
.PARAMETER SourcePowerShellFolder
Remote folder path that contains the modules to copy.
 
.PARAMETER TargetPowerShellFolder
Local destination folder path.
#>

function Copy-EntrinsecFromRemoteMachine {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)]
        [string]$MachineName,

        [Parameter(Mandatory=$true)]
        [string]$SourcePowerShellFolder,

        [Parameter(Mandatory=$true)]
        [string]$TargetPowerShellFolder
    )

    if (-not (Test-Path -Path $TargetPowerShellFolder)) {
        New-Item -ItemType Directory -Path $TargetPowerShellFolder -Force | Out-Null
    }

    $modulePatterns = @("BurntToast", "BurtToast", "Entrinsec.Powershell.*")
    $session = $null

    try {
        $session = New-PSSession -ComputerName $MachineName -ErrorAction Stop

        $modulesToCopy = Invoke-Command -Session $session -ScriptBlock {
            param($Source, $Patterns)
            if (-not (Test-Path -Path $Source)) {
                return @()
            }

            $collected = @()
            foreach ($pattern in $Patterns) {
                $collected += Get-ChildItem -Path $Source -Directory -ErrorAction SilentlyContinue |
                    Where-Object { $_.Name -like $pattern }
            }
            return $collected
        } -ArgumentList $SourcePowerShellFolder, $modulePatterns

        foreach ($module in $modulesToCopy) {
            Copy-Item -Path $module.FullName -Destination $TargetPowerShellFolder -Recurse -Force -FromSession $session
            Write-Host "Copied $($module.Name) from ${MachineName} to ${TargetPowerShellFolder}" -ForegroundColor Green
        }
    }
    catch {
        Write-Error "Failed to copy modules from $MachineName. $_"
    }
    finally {
        if ($session) {
            Remove-PSSession -Session $session
        }
    }
}

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Install-EntrinsecModule {
    param (
        [Parameter(Mandatory=$true)]
        [string]$ModuleName
    )

    # Ensure the module name starts with "Entrinsec.Powershell."
    if ($ModuleName -notmatch "^Entrinsec\.Powershell\." -and $ModuleName -notmatch "^entrinsec\.powershell\." ) {
        $ModuleName = "Entrinsec.Powershell.$ModuleName"
    }

    # Set the output directory for the modules
    $outputDir = "C:\Program Files\PowerShell\Modules"

    # Install and import the specified module
    if ($ModuleName) {

        # Ensuring CORE Entrinsec
        Write-Host "Installing CORE Entrinsec modules..." -ForegroundColor Cyan
        Write-Host "(Setup version : $SetupVersion)" -ForegroundColor Cyan

        Install-EntrinsecCORE -Silent
        Write-Host "CORE Entrinsec modules installed successfully." -ForegroundColor Green
        Write-Host ""

        Write-Host "Installing module $ModuleName..." -ForegroundColor Cyan
        & "C:\Program Files\Nuget\nuget.exe" install $ModuleName -Source "Entrinsec" -OutputDirectory $outputDir -ExcludeVersion
        Import-Module "$outputDir\$ModuleName" -Force -DisableNameChecking

        Write-Host ""
        Write-Host "Functions and aliases that are available in $ModuleName..." -ForegroundColor Green
        # List both functions and aliases in the module
        (Get-Command -Module $ModuleName -CommandType Function, Alias).Name | Sort-Object
        Write-Host ""
    }
    else {
        Write-Host "No module name provided." -ForegroundColor Red
    }

    # Run a test with Show-ToastNotification
    # Show-ToastNotification -Title "Entrinsec Powershell" -Information "You have successfully installed the specified Entrinsec Powershell module!"
}

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Install-EntrinsecENTERPRISE {
    [CmdletBinding()]
    param(
        [switch]$Silent = $false 
    )

    # Function to write output only if $Silent is not true
    function Write-Output {
        param(
            [string]$Message,
            [System.ConsoleColor]$ForegroundColor = 'White'
        )
        if (-not $Silent) {
            Write-Host $Message -ForegroundColor $ForegroundColor
        }
    }

    # $command = "nuget locals all -clear"
    # Write-Output "Clearing all NuGet caches..." -ForegroundColor Yellow
    # Invoke-Expression $command
    # Write-Output "NuGet caches cleared." -ForegroundColor Green

    Write-Output ""

    try {
        if (-not (Get-Module -ListAvailable -Name BurntToast)) {
            Install-Module -Name BurntToast -Repository PSGallery -AllowClobber -Force -ErrorAction Stop -Scope AllUsers
        }
        Write-Output "BurntToast module is available." -ForegroundColor Green
    }
    catch {
        Write-Host "BurntToast module could not be installed." -ForegroundColor Red
        Write-Host "Cannot continue installing Entrinsec modules without BurntToast." -ForegroundColor Red
        exit
    }
    
    # Set the output directory for the modules
    $outputDir = "C:\Program Files\PowerShell\Modules"

    $modules = @(
        "Entrinsec.Powershell.ADO",
        "Entrinsec.Powershell.Common",
        "Entrinsec.Powershell.Containers",
        "Entrinsec.Powershell.Data",
        "Entrinsec.Powershell.Directories",
        "Entrinsec.Powershell.Email",
        "Entrinsec.Powershell.Endpoint",
        "Entrinsec.Powershell.Forensics",
        "Entrinsec.Powershell.Geography",
        "Entrinsec.Powershell.GIT",
        "Entrinsec.Powershell.Identity",
        "Entrinsec.Powershell.Networking",
        "Entrinsec.Powershell.Software",
        "Entrinsec.Powershell.SCCM",
        "Entrinsec.Powershell.Scheduling",
        "Entrinsec.Powershell.SQL"
    )
    
    # Define the output directory
    $outputDir = "C:\Program Files\PowerShell\Modules"

    # Install and import each module
    foreach ($module in $modules) {
        Write-Output ""
        Write-Output "Installing module $module..." -ForegroundColor Cyan
        if (-not $Silent) {
            # Execute nuget.exe with output
            & "C:\Program Files\Nuget\nuget.exe" install $module -Source "Entrinsec" -OutputDirectory $outputDir -ExcludeVersion
        } else {
            # Execute nuget.exe silently
            & "C:\Program Files\Nuget\nuget.exe" install $module -Source "Entrinsec" -OutputDirectory $outputDir -ExcludeVersion *> $null
        }
        Write-Output "Importing module $module..." -ForegroundColor White
        try {
            Import-Module $module -Force -DisableNameChecking -ErrorAction SilentlyContinue -WarningAction SilentlyContinue # Use relative path
          }
          catch {
            try {
              Write-Warning "Failed to import module using relative path. Trying with './'."
              Import-Module .\$module -Force -DisableNameChecking -ErrorAction SilentlyContinue -WarningAction SilentlyContinue # Use explicit relative path
            }
            catch {
              Write-Error "Failed to import module '$module' using both relative paths."
            }
          }
        Write-Output ""
    }

    try {
        Write-Output ""
        Write-Output "Installing Entrinsec.Powershell.SETUP module from PSGallery..." -ForegroundColor Green
        Install-Module -Name Entrinsec.Powershell.SETUP -Repository PSGallery -AllowClobber -Force -ErrorAction SilentlyContinue -Scope AllUsers *>$null
        Import-Module Entrinsec.Powershell.SETUP -Force -DisableNameChecking -ErrorAction SilentlyContinue *>$null
        Write-Output ""
    }
    catch {
    }
    
    # Enumerate the modules folder and import any module starting with Entrinsec.Powershell
    Get-ChildItem -Path $outputDir -Directory | ForEach-Object {
        if ($_.Name -like "Entrinsec.Powershell*") {
            Import-Module $_.FullName -DisableNameChecking
        }
    }

    # Run a test with Show-ToastNotification
    # Show-ToastNotification -Title "Entrinsec Powershell" -Information "You have successfully installed the Core Entrinsec Powershell modules!"
}

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Show-EntrinsecModulesVersionChecker {
    [CmdletBinding()]
    param(
        [switch]$UpdateCheck
    )

    Write-Host ""
    if ($UpdateCheck) {
        Write-Host "Checking for updates to Entrinsec modules..." -ForegroundColor Cyan
    } else {
        Write-Host "Checking installed versions of Entrinsec modules..." -ForegroundColor Cyan
    }

    # Array of module names to check
    $modulesToCheck = @(
        "Common",
        "ADO",
        "Containers",
        "Data",
        "Directories",
        "Email",
        "Endpoint",
        "Forensics",
        "Gaming",
        "Geography",
        "GIT",
        "Identity",
        "Networking",
        "SCCM",
        "Scheduling",
        "Software",
        "SQL",
        "SETUP"
    )

    # Loop through each module and call its update check function
    foreach ($module in $modulesToCheck) {
        $functionName = "Show-Entrinsec$module" + "Info"
        if (Get-Command $functionName -ErrorAction SilentlyContinue) {
            & $functionName -UpdateCheck
        }
    }

    Write-Host ""
    Write-Host "Update check completed." -ForegroundColor Green
    Write-Host ""

}

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Update-EntrinsecNuGetPackage {
    param (
        [Parameter(Mandatory=$true)]
        [string]$PackageName,
        [string]$OutputDirectory = "C:\Program Files\PowerShell\Modules",
        [string]$NuGetExePath = "C:\Program Files\Nuget\nuget.exe",
        [string]$SourceUrl = "https://nuget.entrinsec.com/api/packages/Entrinsec/nuget/index.json"
    )

    # Function to check if the script is run as an administrator
    function Test-IsAdmin {
        $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
        $principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
        return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
    }

    try {
        # Check for admin privileges if the OutputDirectory is "C:\Program Files\PowerShell\Modules"
        if ($OutputDirectory -eq "C:\Program Files\PowerShell\Modules" -and -not (Test-IsAdmin)) {
            throw "Please run this script with administrative privileges."
        }

        Write-Host ""
        Write-Host "Updating (re-installing) the package $PackageName..." -ForegroundColor Cyan
        Write-Host ""
        
        # Clear all NuGet caches
        & $NuGetExePath locals all -clear

        # Remove the existing package folder
        $packagePath = Join-Path -Path $OutputDirectory -ChildPath $PackageName
        if (Test-Path $packagePath) {
            Remove-Item -Recurse -Force $packagePath
        }

        # Install the latest version of the package
        & $NuGetExePath install $PackageName -Source $SourceUrl -OutputDirectory $OutputDirectory -ExcludeVersion
        
        Write-Host ""
        Write-Host "Package $PackageName updated successfully." -ForegroundColor Green
        Write-Host ""
    }
    catch {
        Write-Host "An error occurred: $_" -ForegroundColor Red
    }
}

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>


function Get-HighestModuleVersion {
    param (
        [Parameter(Mandatory=$true)]
        [string]$ModuleName
    )

    try {
        # Get all versions of the specified module
        $modules = Get-Module -Name $ModuleName -ListAvailable

        # Check if any versions are available
        if ($modules.Count -eq 0) {
            return "UNKNOWN"
        }

        # Get the highest version number
        $highestVersion = $modules | Sort-Object Version -Descending | Select-Object -First 1

        # Output the highest version number as a string
        return $highestVersion.Version.ToString()
    }
    catch {
        Write-Host "An error occurred: $_" -ForegroundColor Red
        return "UNKNOWN"
    }
}

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Show-EntrinsecINFO {
    # $MyModuleVersion = Get-HighestModuleVersion -ModuleName Entrinsec.Powershell.SETUP
    Write-Host ""
    Write-Host 'ENTRINSEC (https://www.entrinsec.com)' -ForegroundColor Blue
    Write-Host 'MIT Licensed (https://docs.entrinsec.com/BaGet/Entrinsec-License)' -ForegroundColor Blue
    Show-EntrinsecSETUPInfo
    Write-Host "Module Version: $($MyModuleVersion)" -ForegroundColor Blue
    Write-Host ""
    Write-Host "SETUP (As admin)" -ForegroundColor DarkCyan
    Write-Host ""
    Write-Host ' Install SETUP' -ForegroundColor Cyan -NoNewline
    Write-Host ' : Install-Module -Name Entrinsec.Powershell.SETUP -Repository "PSGallery" -Force -Scope AllUsers'  -ForegroundColor White
    Write-Host ' Import SETUP' -ForegroundColor Cyan -NoNewline
    Write-Host ' : Import-Module -Name Entrinsec.Powershell.SETUP -Force -Global'  -ForegroundColor White
    Write-Host ""
    Write-Host ""
    Write-Host "INITIALIZATION (As admin)" -ForegroundColor DarkCyan
    Write-Host ""
    Write-Host ' Initialize as CORE' -ForegroundColor Cyan -NoNewline
    Write-Host ' : Initialize-EntrinsecNuget -CORE' -ForegroundColor White
    Write-Host ""
    Write-Host " or"
    Write-Host ""
    Write-Host ' Initialize as ENTERPRISE' -ForegroundColor Cyan -NoNewline
    Write-Host ' : Initialize-EntrinsecNuget -ENTERPRISE' -ForegroundColor White
    Write-Host ""
    Write-Host " or"
    Write-Host ""
    Write-Host ' Initialize as EVERYTHING' -ForegroundColor Cyan -NoNewline
    Write-Host ' : Initialize-EntrinsecNuget -EVERYTHING' -ForegroundColor White
    Write-Host ""
    Write-Host ""
    Write-Host "Import Entrinsec Modules" -ForegroundColor DarkCyan
    Write-Host ""
    Write-Host ' Perform an Import-Module on all Entrinsec.Powershell modules that are currently installed.' -ForegroundColor Cyan
    Write-Host ' This is useful at the start of any PS1 script that uses Entrinsec.Powershell modules.' -ForegroundColor Cyan 
    Write-Host ' Entrinsec modules import (Optional switches -Forced -VerboseOuput)' -ForegroundColor Cyan -NoNewline
    Write-Host ' : Import-EntrinsecModules -Forced -VerboseOutput' -ForegroundColor White
    Write-Host ""
    # Import-EntrinsecModulesForce
    Write-Host ""
    Write-Host "VERSION CHECKS" -ForegroundColor DarkCyan
    Write-Host ""
    Write-Host ' Check Installed Version' -ForegroundColor Cyan -NoNewline
    Write-Host ' : Show-EntrinsecModulesVersionChecker' -ForegroundColor White
    Write-Host ""
    Write-Host ""
    Write-Host "UPDATING (As admin)" -ForegroundColor DarkCyan
    Write-Host ""
    Write-Host ' Update an Entrinsec Powershell module' -ForegroundColor Cyan -NoNewline
    Write-Host ' : Update-EntrinsecNuGetPackage -PackageName <entrinsec.powershell.xxxxxxx>' -ForegroundColor White
    Write-Host ' For example' -ForegroundColor Cyan -NoNewline
    Write-Host ' : Update-EntrinsecNuGetPackage -PackageName Entrinsec.Powershell.COMMON' -ForegroundColor White
    Write-Host ""
    Write-Host ""
    Write-Host "REMOVAL (As admin)" -ForegroundColor DarkCyan
    Write-Host ""
    Write-Host ' Remove ALL Entrinsec Powershell modules' -ForegroundColor Cyan -NoNewline
    Write-Host ' : Remove-EntrinsecModules' -ForegroundColor White
    Write-Host ""
    Write-Host ""
}

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Import-EntrinsecModules {
    param (
        [Parameter(Mandatory=$false)]
        [string]$modulePath = "C:\Program Files\PowerShell\Modules",

        [switch]$VerboseOutput = $false,
        [switch]$Forced = $false
    )
    
    # Check if the directory exists
    if (-Not (Test-Path -Path $modulePath)) {
        Write-Error "The specified module path '$modulePath' does not exist."
        return
    }

    # Get directories that start with "Entrinsec.Powershell."
    $modules = Get-ChildItem -Path $modulePath -Directory | Where-Object {
        $_.Name -like "Entrinsec.Powershell.*"
    }

    if ($modules.Count -eq 0) {
        if ($VerboseOutput) {
            Write-Host "No modules starting with 'Entrinsec.Powershell.' were found in '$modulePath'." -ForegroundColor Yellow
        }
        return
    }

    # Separate the SETUP module and other modules
    $setupModule = $modules | Where-Object { $_.Name -eq "Entrinsec.Powershell.SETUP" }
    $otherModules = $modules | Where-Object { $_.Name -ne "Entrinsec.Powershell.SETUP" }

    # Import the SETUP module first
    if ($setupModule) {
        try {
            if ($VerboseOutput) {
                Write-Host "Attempting to import SETUP module: $($setupModule.Name)" -ForegroundColor White
            }
            Import-Module -Name $setupModule.Name -Force:($Forced.IsPresent) -DisableNameChecking -ErrorAction Stop
            if ($VerboseOutput) {
                Write-Host "Successfully imported SETUP module: $($setupModule.Name)" -ForegroundColor Green
            }
        } catch {
            Write-Host "Failed to import SETUP module: $($setupModule.Name). Error: $_" -ForegroundColor Red
        }
    }

    # Import other modules
    foreach ($module in $otherModules) {
        try {
            if ($VerboseOutput) {
                Write-Host "Attempting to import module: $($module.Name)" -ForegroundColor White
            }
            Import-Module -Name $module.Name -Force:($Forced.IsPresent) -DisableNameChecking -ErrorAction Stop
            if ($VerboseOutput) {
                Write-Host "Successfully imported module: $($module.Name)" -ForegroundColor Green
            }
        } catch {
            Write-Host "Failed to import module: $($module.Name). Error: $_" -ForegroundColor Red
        }
    }
}

<#
.SYNOPSIS
Displays information about installed Entrinsec PowerShell modules.
 
.DESCRIPTION
Lists all installed Entrinsec PowerShell modules. Optionally filter to view detailed function information for a specific module.
 
.PARAMETER ModuleName
Optional. Specify a module name (or partial name) to view detailed functions for that module.
 
.EXAMPLE
Entrinsec
Lists all available Entrinsec modules.
 
.EXAMPLE
Entrinsec Common
Lists all functions in the Entrinsec.Powershell.Common module with their synopses.
 
.EXAMPLE
Entrinsec-Info Networking
Lists all functions in the Entrinsec.Powershell.Networking module.
 
.NOTES
This function searches the standard PowerShell module paths for modules starting with 'Entrinsec.Powershell.'.
#>

<#
.EXTERNALHELP Entrinsec.Powershell.SETUP-help.xml
#>

function Entrinsec {
    [CmdletBinding()]
    [Alias('Entrinsec-Info', 'Entrinsec-Help')]
    param(
        [string]$ModuleName
    )

    # Get all Entrinsec modules from all module paths
    $modules = @()
    $modulePaths = $env:PSModulePath -split ';'
    
    foreach ($path in $modulePaths) {
        if (Test-Path $path) {
            $modules += Get-ChildItem -Path $path -Directory -ErrorAction SilentlyContinue | 
                Where-Object { $_.Name -like "Entrinsec.Powershell.*" }
        }
    }

    if ($modules.Count -eq 0) {
        Write-Host "`nNo Entrinsec modules are currently installed.`n" -ForegroundColor Yellow
        return
    }

    # Remove duplicates (keeping the first occurrence)
    $uniqueModules = @()
    $seenNames = @{}
    foreach ($module in $modules) {
        if (-not $seenNames.ContainsKey($module.Name)) {
            $uniqueModules += $module
            $seenNames[$module.Name] = $true
        }
    }

    $uniqueModules = $uniqueModules | Sort-Object Name

    # If ModuleName parameter is provided, show detailed function list for that module
    if ($ModuleName) {
        $filteredModules = $uniqueModules | Where-Object { $_.Name -like "*$ModuleName*" }
        
        if ($filteredModules.Count -eq 0) {
            Write-Host "`nNo modules matching '$ModuleName' found.`n" -ForegroundColor Yellow
            return
        }

        # Display detailed function information for the filtered module(s)
        Write-Host "`n========================================" -ForegroundColor Cyan
        Write-Host "Entrinsec PowerShell Modules" -ForegroundColor Cyan
        Write-Host "========================================`n" -ForegroundColor Cyan

        foreach ($module in $filteredModules) {
            $commands = Get-Command -Module $module.Name -ErrorAction SilentlyContinue | Sort-Object Name
            
            # Get module version
            $version = "1.0.0"
            $manifestPath = Join-Path $module.FullName "$($module.Name).psd1"
            
            # If manifest not in module root, check for version subfolders (e.g., "1.15.70")
            if (-not (Test-Path $manifestPath)) {
                $versionedSubfolders = Get-ChildItem -Path $module.FullName -Directory -ErrorAction SilentlyContinue |
                    Where-Object { $_.Name -match '^\d+\.\d+' }  # Version number pattern
                if ($versionedSubfolders) {
                    $manifestPath = Join-Path $versionedSubfolders[0].FullName "$($module.Name).psd1"
                }
            }
            
            if (Test-Path $manifestPath) {
                try {
                    $manifest = Import-PowerShellDataFile $manifestPath
                    if ($manifest.ModuleVersion) {
                        $version = $manifest.ModuleVersion
                    }
                } catch {
                    # Silently continue if manifest read fails
                }
            }
            
            if ($commands.Count -eq 0) {
                Write-Host "$($module.Name) ($version)" -ForegroundColor Green
                Write-Host ""
                continue
            }

            Write-Host "$($module.Name) ($version)" -ForegroundColor Green

            foreach ($cmd in $commands) {
                $synopsis = ""
                try {
                    $help = Get-Help $cmd.Name -ErrorAction SilentlyContinue
                    if ($help.Synopsis) {
                        $synopsis = $help.Synopsis.Trim()
                    }
                } catch {
                    # Silently continue if help lookup fails
                }
                
                Write-Host " • $($cmd.Name)" -ForegroundColor Cyan -NoNewline
                if ($synopsis) {
                    Write-Host " - $synopsis" -ForegroundColor White
                } else {
                    Write-Host ""
                }
            }
            Write-Host ""
        }

        Write-Host "========================================" -ForegroundColor Cyan
        Write-Host "Total Modules: $($filteredModules.Count)" -ForegroundColor White
        Write-Host "========================================`n" -ForegroundColor Cyan
        return
    }

    # Display list of available modules
    Write-Host "`n========================================" -ForegroundColor Cyan
    Write-Host "Entrinsec PowerShell Modules" -ForegroundColor Cyan
    Write-Host "========================================`n" -ForegroundColor Cyan

    # Separate modules into available and draft
    $availableModules = @()
    $draftModules = @()
    
    foreach ($module in $uniqueModules) {
        # Get module version
        $version = "1.0.0"
        $manifestPath = Join-Path $module.FullName "$($module.Name).psd1"
        
        # If manifest not in module root, check for version subfolders (e.g., "1.15.70")
        if (-not (Test-Path $manifestPath)) {
            $versionedSubfolders = Get-ChildItem -Path $module.FullName -Directory -ErrorAction SilentlyContinue |
                Where-Object { $_.Name -match '^\d+\.\d+' }  # Version number pattern
            if ($versionedSubfolders) {
                $manifestPath = Join-Path $versionedSubfolders[0].FullName "$($module.Name).psd1"
            }
        }
        
        if (Test-Path $manifestPath) {
            try {
                $manifest = Import-PowerShellDataFile $manifestPath
                if ($manifest.ModuleVersion) {
                    $version = $manifest.ModuleVersion
                }
            } catch {
                # Silently continue if manifest read fails
            }
        }
        
        if ($version -eq "1.0.0") {
            $draftModules += $module
        } else {
            $availableModules += $module
        }
    }

    # Display available modules (cyan)
    if ($availableModules.Count -gt 0) {
        Write-Host "Available modules:" -ForegroundColor White
        foreach ($module in $availableModules) {
            $shortName = $module.Name -replace "Entrinsec.Powershell.", ""
            Write-Host " • $shortName" -ForegroundColor Cyan
        }
        Write-Host ""
    }

    # Display draft modules (gray)
    if ($draftModules.Count -gt 0) {
        Write-Host "Draft modules:" -ForegroundColor White
        foreach ($module in $draftModules) {
            $shortName = $module.Name -replace "Entrinsec.Powershell.", ""
            Write-Host " • $shortName" -ForegroundColor DarkGray
        }
        Write-Host ""
    }

    Write-Host "To view functions for a specific module, use:" -ForegroundColor White
    Write-Host " Entrinsec <ModuleName>" -ForegroundColor Gray
    Write-Host ""
    Write-Host "Examples:" -ForegroundColor White
    $exampleCount = [Math]::Min(3, $availableModules.Count)
    for ($i = 0; $i -lt $exampleCount; $i++) {
        $shortName = $availableModules[$i].Name -replace "Entrinsec.Powershell.", ""
        Write-Host " Entrinsec $shortName" -ForegroundColor Cyan
    }

    Write-Host ""
    Write-Host "========================================`n" -ForegroundColor Cyan
}

# Export aliases
Set-Alias -Name Initialize-Entrinsec -Value Initialize-EntrinsecNuget -Scope Global
# Optionally, export the alias for module usage
Export-ModuleMember -Function * -Alias Initialize-Entrinsec