Entrinsec.Powershell.SETUP.psm1

#Requires -Version 7.0

$SetupVersion = '1.6.4'

# Function to install NuGet.exe
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-Output "nuget.exe is accessible and can be launched."
    } catch {
        Write-Output "nuget.exe cannot be launched. Please check your PATH and the existence of nuget.exe."
    }

    # 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"
        return  # 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"
}
function Clear-NuGetCache {
    # Clears the NuGet cache.
  
    # Use the dotnet CLI to clear the cache.
    dotnet nuget locals all --clear
  
    # Write a message to the console indicating that the cache has been cleared.
    Write-Host "NuGet cache cleared."
}

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/v3/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
}
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.Alerting",
        "Entrinsec.Powershell.Common",
        "Entrinsec.Powershell.Identity",
        "Entrinsec.Powershell.Logging"
    )
    
    # 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
        Import-Module "$outputDir\$module" -Force
        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 -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
        }
    }

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

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 ""

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

    # Define the list of modules
    $modules = @(
        "Entrinsec.Powershell.ADO",
        "Entrinsec.Powershell.Alerting",
        "Entrinsec.Powershell.Common",
        "Entrinsec.Powershell.Containers",
        "Entrinsec.Powershell.Dialogs",
        "Entrinsec.Powershell.Data",
        "Entrinsec.Powershell.Directories",
        "Entrinsec.Powershell.Email",
        "Entrinsec.Powershell.Endpoint.Diagnostics",
        "Entrinsec.Powershell.Endpoint.Management",
        "Entrinsec.Powershell.FileSystem",
        "Entrinsec.Powershell.Forensics",
        "Entrinsec.Powershell.Gaming",
        "Entrinsec.Powershell.Geography",
        "Entrinsec.Powershell.GIT",
        "Entrinsec.Powershell.Identity",
        "Entrinsec.Powershell.Logging",
        "Entrinsec.Powershell.Networking",
        "Entrinsec.Powershell.Registry",
        "Entrinsec.Powershell.SCCM",
        "Entrinsec.Powershell.Scheduling",
        "Entrinsec.Powershell.Software.Management",
        "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
        Import-Module "$outputDir\$module" -Force
        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 -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
        }
    }

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

function Initialize-EntrinsecNuget {
    
    <#
    .SYNOPSIS
        Sets up the Entrinsec PowerShell environment by installing NuGet,
        adding the Entrinsec NuGet source, and installing Entrinsec modules.
 
    .DESCRIPTION
        This function performs the following steps:
            1. Installs NuGet.exe if it's not already present.
            2. Adds the Entrinsec NuGet source.
            3. Installs core Entrinsec modules.
 
    .PARAMETER CORE
        Indicates whether to install core Entrinsec modules. Default is $true.
 
    .PARAMETER EVERYTHING
        Indicates whether to install all Entrinsec modules. Default is $false.
 
    .EXAMPLE
        PS> Initialize-EntrinsecNuget -CORE $true -EVERYTHING $false
 
    .NOTES
        Author: Entrinsec
        Date: 2024-11-19
        Version: 1.0
        Run as an administrator.
    #>


    param (
        [switch]$CORE = $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 script as an administrator." -ForegroundColor Red
        return
    }

    Clear-Host

    Write-Host "Setting up the Entrinsec PowerShell environment..." -ForegroundColor Cyan
    Write-Host "(Setup version : $SetupVersion)" -ForegroundColor Cyan
    Write-Host ""

    Install-Nuget

    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 ($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 ""
}

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

    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\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
    dotnet nuget locals all --clear
}

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) {

        Clear-Host

        # 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

        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!"
}