EnhancedBoilerPlateAO.psm1

#Region '.\Public\Add-EnvPath.ps1' -1

function Add-EnvPath {
    <#
    .SYNOPSIS
    Adds a specified path to the environment PATH variable.
 
    .DESCRIPTION
    The Add-EnvPath function adds a specified path to the environment PATH variable. The path can be added to the session, user, or machine scope.
 
    .PARAMETER Path
    The path to be added to the environment PATH variable.
 
    .PARAMETER Container
    Specifies the scope of the environment variable. Valid values are 'Machine', 'User', or 'Session'.
 
    .EXAMPLE
    Add-EnvPath -Path 'C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Imaging and Configuration Designer\x86' -Container 'Machine'
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string] $Path,

        [ValidateSet('Machine', 'User', 'Session')]
        [string] $Container = 'Session'
    )

    begin {
        Write-EnhancedLog -Message "Starting Add-EnvPath function" -Level "INFO"
        Log-Params -Params @{
            Path = $Path
            Container = $Container
        }

        $envPathHashtable = [ordered]@{}
        $persistedPathsHashtable = [ordered]@{}
        $containerMapping = @{
            Machine = [System.EnvironmentVariableTarget]::Machine
            User    = [System.EnvironmentVariableTarget]::User
        }
    }

    process {
        try {
            # Update the PATH variable for User or Machine scope
            if ($Container -ne 'Session') {
                $containerType = $containerMapping[$Container]
                $existingPaths = [System.Environment]::GetEnvironmentVariable('Path', $containerType) -split ';'
                
                foreach ($pathItem in $existingPaths) {
                    $persistedPathsHashtable[$pathItem] = $null
                }

                if (-not $persistedPathsHashtable.Contains($Path)) {
                    Write-EnhancedLog -Message "Path not found in persisted paths, adding it." -Level "INFO"
                    $persistedPathsHashtable[$Path] = $null
                    [System.Environment]::SetEnvironmentVariable('Path', ($persistedPathsHashtable.Keys -join ';'), $containerType)
                }
            }

            # Update the PATH variable for the current session
            $existingSessionPaths = $env:Path -split ';'
            
            foreach ($sessionPathItem in $existingSessionPaths) {
                $envPathHashtable[$sessionPathItem] = $null
            }

            if (-not $envPathHashtable.Contains($Path)) {
                Write-EnhancedLog -Message "Path not found in session paths, adding it." -Level "INFO"
                $envPathHashtable[$Path] = $null
                $env:Path = $envPathHashtable.Keys -join ';'
            }
        } catch {
            Write-EnhancedLog -Message "An error occurred: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
        }
    }

    end {
        Write-EnhancedLog -Message "Exiting Add-EnvPath function" -Level "INFO"
        
        Write-Host "The permanent environment PATH variable is:"
        [System.Environment]::GetEnvironmentVariable('Path', [System.EnvironmentVariableTarget]::Machine) -split ';'

        Write-Host "The temporary environment PATH variable is:"
        $env:Path -split ';'
    }
}

# # Example usage
# $envPathParams = @{
# Path = 'C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Imaging and Configuration Designer\x86'
# Container = 'Machine'
# }

# Add-EnvPath @envPathParams
#EndRegion '.\Public\Add-EnvPath.ps1' 97
#Region '.\Public\CallingasSYSTEM.ps1' -1


# ################################################################################################################################
# ################################################ CALLING AS SYSTEM (Uncomment for debugging) ###################################
# ################################################################################################################################

# Assuming Invoke-AsSystem and Write-EnhancedLog are already defined
# Update the path to your actual location of PsExec64.exe

# Write-EnhancedLog -Message "calling Test-RunningAsSystem" -Level "INFO" -ForegroundColor ([ConsoleColor]::Green)
# if (-not (Test-RunningAsSystem)) {
# $privateFolderPath = Join-Path -Path $PSScriptRoot -ChildPath "private"

# # Check if the private folder exists, and create it if it does not
# if (-not (Test-Path -Path $privateFolderPath)) {
# New-Item -Path $privateFolderPath -ItemType Directory | Out-Null
# }
    
# $PsExec64Path = Join-Path -Path $privateFolderPath -ChildPath "PsExec64.exe"
    

# Write-EnhancedLog -Message "Current session is not running as SYSTEM. Attempting to invoke as SYSTEM..." -Level "INFO" -ForegroundColor ([ConsoleColor]::Yellow)

# $ScriptToRunAsSystem = $MyInvocation.MyCommand.Path
# Invoke-AsSystem -PsExec64Path $PsExec64Path -ScriptPath $ScriptToRunAsSystem -TargetFolder $privateFolderPath

# }
# else {
# Write-EnhancedLog -Message "Session is already running as SYSTEM." -Level "INFO" -ForegroundColor ([ConsoleColor]::Green)
# }



# ################################################################################################################################
# ################################################ END CALLING AS SYSTEM (Uncomment for debugging) ###############################
# ################################################################################################################################
#EndRegion '.\Public\CallingasSYSTEM.ps1' 36
#Region '.\Public\Check-ModuleVersionStatus.ps1' -1


function Check-ModuleVersionStatus {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string[]]$ModuleNames
    )

    #the following modules PowerShellGet and PackageManagement has to be either automatically imported or manually imported into C:\windows\System32\WindowsPowerShell\v1.0\Modules

    Import-Module -Name PowerShellGet -ErrorAction SilentlyContinue
    # Import-Module 'C:\Program Files (x86)\WindowsPowerShell\Modules\PowerShellGet\PSModule.psm1' -ErrorAction SilentlyContinue
    # Import-Module 'C:\windows\System32\WindowsPowerShell\v1.0\Modules\PowerShellGet\PSModule.psm1' -ErrorAction SilentlyContinue
    # Import-Module 'C:\Program Files (x86)\WindowsPowerShell\Modules\PackageManagement\PackageProviderFunctions.psm1' -ErrorAction SilentlyContinue
    # Import-Module 'C:\windows\System32\WindowsPowerShell\v1.0\Modules\PackageManagement\PackageProviderFunctions.psm1' -ErrorAction SilentlyContinue
    # Import-Module 'C:\Program Files (x86)\WindowsPowerShell\Modules\PackageManagement\PackageManagement.psm1' -ErrorAction SilentlyContinue

    $results = New-Object System.Collections.Generic.List[PSObject]  # Initialize a List to hold the results

    foreach ($ModuleName in $ModuleNames) {
        try {

            Write-Host 'Checking module '$ModuleName
            $installedModule = Get-Module -ListAvailable -Name $ModuleName | Sort-Object Version -Descending | Select-Object -First 1
            # $installedModule = Check-SystemWideModule -ModuleName 'Pester'
            $latestModule = Find-Module -Name $ModuleName -ErrorAction SilentlyContinue

            if ($installedModule -and $latestModule) {
                if ($installedModule.Version -lt $latestModule.Version) {
                    $results.Add([PSCustomObject]@{
                        ModuleName = $ModuleName
                        Status = "Outdated"
                        InstalledVersion = $installedModule.Version
                        LatestVersion = $latestModule.Version
                    })
                } else {
                    $results.Add([PSCustomObject]@{
                        ModuleName = $ModuleName
                        Status = "Up-to-date"
                        InstalledVersion = $installedModule.Version
                        LatestVersion = $installedModule.Version
                    })
                }
            } elseif (-not $installedModule) {
                $results.Add([PSCustomObject]@{
                    ModuleName = $ModuleName
                    Status = "Not Installed"
                    InstalledVersion = $null
                    LatestVersion = $null
                })
            } else {
                $results.Add([PSCustomObject]@{
                    ModuleName = $ModuleName
                    Status = "Not Found in Gallery"
                    InstalledVersion = $null
                    LatestVersion = $null
                })
            }
        } catch {
            Write-Error "An error occurred checking module '$ModuleName': $_"
        }
    }

    return $results
}

# Example usage:
# $versionStatuses = Check-ModuleVersionStatus -ModuleNames @('Pester', 'AzureRM', 'PowerShellGet')
# $versionStatuses | Format-Table -AutoSize # Display the results in a table format for readability


#EndRegion '.\Public\Check-ModuleVersionStatus.ps1' 72
#Region '.\Public\Convert-WindowsPathToLinuxPath.ps1' -1

function Convert-WindowsPathToLinuxPath {
    <#
.SYNOPSIS
    Converts a Windows file path to a Linux file path.
 
.DESCRIPTION
    This function takes a Windows file path as input and converts it to a Linux file path.
    It replaces backslashes with forward slashes and handles the drive letter.
 
.PARAMETER WindowsPath
    The full file path in Windows format that needs to be converted.
 
.EXAMPLE
    PS> Convert-WindowsPathToLinuxPath -WindowsPath 'C:\Code\CB\Entra\ARH\Get-EntraConnectSyncErrorsfromEntra copy.ps1'
    Returns '/mnt/c/Code/CB/Entra/ARH/Get-EntraConnectSyncErrorsfromEntra copy.ps1'
 
#>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$WindowsPath
    )

    Begin {
        Write-Host "Starting the path conversion process..."
    }

    Process {
        try {
            Write-Host "Input Windows Path: $WindowsPath"
            
            # Replace backslashes with forward slashes
            $linuxPath = $WindowsPath -replace '\\', '/'

            # Handle drive letter by converting "C:" to "/mnt/c"
            if ($linuxPath -match '^[A-Za-z]:') {
                $driveLetter = $linuxPath.Substring(0, 1).ToLower()
                $linuxPath = "/mnt/$driveLetter" + $linuxPath.Substring(2)
            }

            Write-Host "Converted Linux Path: $linuxPath"
            return $linuxPath
        }
        catch {
            Write-Host "Error during conversion: $_"
            throw
        }
    }

    End {
        Write-Host "Path conversion completed."
    }
}

# # Example usage
# $windowsPath = 'C:\Code\Unified365toolbox\Graph\graphcert.pfx'
# $linuxPath = Convert-WindowsPathToLinuxPath -WindowsPath $windowsPath
# Write-Host "Linux path: $linuxPath"
#EndRegion '.\Public\Convert-WindowsPathToLinuxPath.ps1' 59
#Region '.\Public\Ensure-LoggingFunctionExists.ps1' -1

function Ensure-LoggingFunctionExists {
    param (
        # [string]$LoggingFunctionName = "Write-EnhancedLog"
        [string]$LoggingFunctionName
    )

    if (Get-Command $LoggingFunctionName -ErrorAction SilentlyContinue) {
        Write-EnhancedLog -Message "Logging works" -Level "INFO" -ForegroundColor ([ConsoleColor]::Green)
    }
    else {
        throw "$LoggingFunctionName function not found. Terminating script."
    }
}

# Example of how to call the function with the default parameter
# Ensure-LoggingFunctionExists

# Example of how to call the function with a different logging function name
# Ensure-LoggingFunctionExists -LoggingFunctionName "Write-EnhancedLog"
#EndRegion '.\Public\Ensure-LoggingFunctionExists.ps1' 20
#Region '.\Public\Get-ModulesFolderPath.ps1' -1

function Get-ModulesFolderPath {
    param (
        [Parameter(Mandatory = $true)]
        [string]$WindowsPath,
        [Parameter(Mandatory = $true)]
        [string]$UnixPath
    )

    # Auxiliary function to detect OS and set the Modules folder path
    if ($PSVersionTable.PSVersion.Major -ge 7) {
        if ($PSVersionTable.Platform -eq 'Win32NT') {
            return $WindowsPath
        }
        elseif ($PSVersionTable.Platform -eq 'Unix') {
            return $UnixPath
        }
        else {
            throw "Unsupported operating system"
        }
    }
    else {
        $os = [System.Environment]::OSVersion.Platform
        if ($os -eq [System.PlatformID]::Win32NT) {
            return $WindowsPath
        }
        elseif ($os -eq [System.PlatformID]::Unix) {
            return $UnixPath
        }
        else {
            throw "Unsupported operating system"
        }
    }
}
#EndRegion '.\Public\Get-ModulesFolderPath.ps1' 34
#Region '.\Public\Get-ModulesScriptPathsAndVariables.ps1' -1

# function Get-ModulesScriptPathsAndVariables {
    

# <#
# .SYNOPSIS
# Dot-sources all PowerShell scripts in the 'Modules' folder relative to the script root.
    
# .DESCRIPTION
# This function finds all PowerShell (.ps1) scripts in a 'Modules' folder located in the script root directory and dot-sources them. It logs the process, including any errors encountered, with optional color coding.
    
# .EXAMPLE
# Dot-SourceModulesScripts
    
# Dot-sources all scripts in the 'Modules' folder and logs the process.
    
# .NOTES
# Ensure the Write-EnhancedLog function is defined before using this function for logging purposes.
# #>
# param (
# [string]$BaseDirectory
# )
    
# try {
# $ModulesFolderPath = Join-Path -Path $BaseDirectory -ChildPath "Modules"
            
# if (-not (Test-Path -Path $ModulesFolderPath)) {
# throw "Modules folder path does not exist: $ModulesFolderPath"
# }
    
# # Construct and return a PSCustomObject
# return [PSCustomObject]@{
# BaseDirectory = $BaseDirectory
# ModulesFolderPath = $ModulesFolderPath
# }
# }
# catch {
# Write-Host "Error in finding Modules script files: $_" -ForegroundColor Red
# # Optionally, you could return a PSCustomObject indicating an error state
# # return [PSCustomObject]@{ Error = $_.Exception.Message }
# }
# }
#EndRegion '.\Public\Get-ModulesScriptPathsAndVariables.ps1' 42
#Region '.\Public\Import-LatestModulesLocalRepository.ps1' -1

# function Import-LatestModulesLocalRepository {

# <#
# .SYNOPSIS
# Imports the latest version of all modules found in the specified Modules directory.

# .DESCRIPTION
# This function scans the Modules directory for module folders, identifies the latest version of each module,
# and attempts to import the module. If a module file is not found or if importing fails, appropriate error
# messages are logged.

# .PARAMETER None
# This function does not take any parameters.

# .NOTES
# This function assumes the presence of a custom function 'Import-ModuleWithRetry' for retrying module imports.

# .EXAMPLE
# ImportLatestModules
# This example imports the latest version of all modules found in the Modules directory.
# #>

# [CmdletBinding()]
# param (
# $ModulesFolderPath
# )

# Begin {
# # Get the path to the Modules directory
# # $modulesDir = Join-Path -Path $PSScriptRoot -ChildPath "Modules"
# # $modulesDir = "C:\code\Modules"

# # Get all module directories
# $moduleDirectories = Get-ChildItem -Path $ModulesFolderPath -Directory

# Write-Host "moduleDirectories is $moduleDirectories"

# # Log the number of discovered module directories
# Write-Host "Discovered module directories: $($moduleDirectories.Count)" -ForegroundColor ([ConsoleColor]::Cyan)
# }

# Process {
# foreach ($moduleDir in $moduleDirectories) {
# # Get the latest version directory for the current module
# $latestVersionDir = Get-ChildItem -Path $moduleDir.FullName -Directory | Sort-Object Name -Descending | Select-Object -First 1

# if ($null -eq $latestVersionDir) {
# Write-Host "No version directories found for module: $($moduleDir.Name)" -ForegroundColor ([ConsoleColor]::Red)
# continue
# }

# # Construct the path to the module file
# $modulePath = Join-Path -Path $latestVersionDir.FullName -ChildPath "$($moduleDir.Name).psm1"

# # Check if the module file exists
# if (Test-Path -Path $modulePath) {
# # Import the module with retry logic
# try {
# Import-ModuleWithRetry -ModulePath $modulePath
# # Import-Module $ModulePath -ErrorAction Stop -Verbose
# Write-Host "Successfully imported module: $($moduleDir.Name) from version: $($latestVersionDir.Name)" -ForegroundColor ([ConsoleColor]::Green)
# }
# catch {
# Write-Host "Failed to import module: $($moduleDir.Name) from version: $($latestVersionDir.Name). Error: $_" -ForegroundColor ([ConsoleColor]::Red)
# }
# }
# else {
# Write-Host "Module file not found: $modulePath" -ForegroundColor ([ConsoleColor]::Red)
# }
# }
# }

# End {
# Write-Host "Module import process completed using Import-LatestModulesLocalRepository from $moduleDirectories" -ForegroundColor ([ConsoleColor]::Cyan)
# }
# }




function Import-LatestModulesLocalRepository {
    <#
.SYNOPSIS
    Imports the latest version of all modules found in the specified Modules directory.
 
.DESCRIPTION
    This function scans the Modules directory for module folders, identifies the latest version of each module,
    and attempts to import the module. If a module file is not found or if importing fails, appropriate error
    messages are logged.
 
.PARAMETER ModulesFolderPath
    The path to the folder containing the modules.
 
.EXAMPLE
    Import-LatestModulesLocalRepository -ModulesFolderPath "C:\code\Modules"
    This example imports the latest version of all modules found in the specified Modules directory.
#>


    [CmdletBinding()]
    param (
        [string]$ModulesFolderPath,
        [string]$ScriptPath
        
    )

    Begin {
        # Get the path to the Modules directory
        $moduleDirectories = Get-ChildItem -Path $ModulesFolderPath -Directory

        Write-Host "moduleDirectories is $moduleDirectories"

        # Log the number of discovered module directories
        Write-Host "Discovered module directories: $($moduleDirectories.Count)" -ForegroundColor ([ConsoleColor]::Cyan)

        # Read the modules exclusion list from the JSON file
        $exclusionFilePath = Join-Path -Path $ScriptPath -ChildPath "modulesexclusion.json"
        if (Test-Path -Path $exclusionFilePath) {
            $excludedModules = Get-Content -Path $exclusionFilePath | ConvertFrom-Json
            Write-Host "Excluded modules: $excludedModules" -ForegroundColor ([ConsoleColor]::Cyan)
        } else {
            $excludedModules = @()
            Write-Host "No exclusion file found. Proceeding with all modules." -ForegroundColor ([ConsoleColor]::Yellow)
        }
    }

    Process {
        foreach ($moduleDir in $moduleDirectories) {
            # Skip the module if it is in the exclusion list
            if ($excludedModules -contains $moduleDir.Name) {
                Write-Host "Skipping excluded module: $($moduleDir.Name)" -ForegroundColor ([ConsoleColor]::Yellow)
                continue
            }

            # Get the latest version directory for the current module
            $latestVersionDir = Get-ChildItem -Path $moduleDir.FullName -Directory | Sort-Object Name -Descending | Select-Object -First 1

            if ($null -eq $latestVersionDir) {
                Write-Host "No version directories found for module: $($moduleDir.Name)" -ForegroundColor ([ConsoleColor]::Red)
                continue
            }

            # Construct the path to the module file
            $modulePath = Join-Path -Path $latestVersionDir.FullName -ChildPath "$($moduleDir.Name).psm1"

            # Check if the module file exists
            if (Test-Path -Path $modulePath) {
                # Import the module with retry logic
                try {
                    Import-ModuleWithRetry -ModulePath $modulePath
                    Write-Host "Successfully imported module: $($moduleDir.Name) from version: $($latestVersionDir.Name)" -ForegroundColor ([ConsoleColor]::Green)
                }
                catch {
                    Write-Host "Failed to import module: $($moduleDir.Name) from version: $($latestVersionDir.Name). Error: $_" -ForegroundColor ([ConsoleColor]::Red)
                }
            }
            else {
                Write-Host "Module file not found: $modulePath" -ForegroundColor ([ConsoleColor]::Red)
            }
        }
    }

    End {
        Write-Host "Module import process completed using Import-LatestModulesLocalRepository from $moduleDirectories" -ForegroundColor ([ConsoleColor]::Cyan)
    }
}
#EndRegion '.\Public\Import-LatestModulesLocalRepository.ps1' 166
#Region '.\Public\Import-Modules.ps1' -1

function Import-Modules {
    param (
        [Parameter(Mandatory = $true)]
        [string[]]$Modules
    )
    
    foreach ($module in $Modules) {
        if (Get-Module -ListAvailable -Name $module) {
            # Import-Module -Name $module -Force -Verbose
            Import-Module -Name $module -Force:$true -Global:$true
            Write-EnhancedLog -Message "Module '$module' imported." -Level "INFO"
        }
        else {
            Write-EnhancedLog -Message "Module '$module' not found. Cannot import." -Level "ERROR"
        }
    }
}
#EndRegion '.\Public\Import-Modules.ps1' 18
#Region '.\Public\Import-ModuleWithRetry.ps1' -1

function Import-ModuleWithRetry {
    <#
    .SYNOPSIS
    Imports a PowerShell module with retries on failure.
 
    .DESCRIPTION
    This function attempts to import a specified PowerShell module, retrying the import process up to a specified number of times upon failure. It also checks if the module path exists before attempting to import.
 
    .PARAMETER ModulePath
    The path to the PowerShell module file (.psm1) that should be imported.
 
    .PARAMETER MaxRetries
    The maximum number of retries to attempt if importing the module fails. Default is 3.
 
    .PARAMETER WaitTimeSeconds
    The number of seconds to wait between retry attempts. Default is 2 seconds.
 
    .EXAMPLE
    $modulePath = "C:\Modules\MyPowerShellModule.psm1"
    Import-ModuleWithRetry -ModulePath $modulePath
 
    Tries to import the module located at "C:\Modules\MyPowerShellModule.psm1", with up to 3 retries, waiting 2 seconds between each retry.
 
    .NOTES
    This function requires the `Write-EnhancedLog` function to be defined in the script for logging purposes.
 
    .LINK
    Write-EnhancedLog
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]$ModulePath,

        [int]$MaxRetries = 3,

        [int]$WaitTimeSeconds = 2
    )

    Begin {
        $retryCount = 0
        $isModuleLoaded = $false
        Write-Host "Starting to import module from path: $ModulePath"
        
        # Check if the module file exists before attempting to load it
        if (-not (Test-Path -Path $ModulePath -PathType Leaf)) {
            Write-Host "The module path '$ModulePath' does not exist."
            return
        }
    }

    Process {
        while (-not $isModuleLoaded -and $retryCount -lt $MaxRetries) {
            try {
                # Import-Module $ModulePath -ErrorAction Stop -Verbose -Global
                Import-Module $ModulePath -ErrorAction Stop -Global -Force:$true
                # Import-Module $ModulePath -ErrorAction Stop
                $isModuleLoaded = $true
                Write-Host "Module: $ModulePath imported successfully."
            }
            catch {
                $errorMsg = $_.Exception.Message
                Write-Host "Attempt $retryCount to load module failed: $errorMsg Waiting $WaitTimeSeconds seconds before retrying."
                Write-Host "Attempt $retryCount to load module failed with error: $errorMsg"
                Start-Sleep -Seconds $WaitTimeSeconds
            }
            finally {
                $retryCount++
            }

            if ($retryCount -eq $MaxRetries -and -not $isModuleLoaded) {
                Write-Host "Failed to import module after $MaxRetries retries."
                Write-Host "Failed to import module after $MaxRetries retries with last error: $errorMsg"
                break
            }
        }
    }

    End {
        if ($isModuleLoaded) {
            Write-Host "Module: $ModulePath loaded successfully."
        }
        else {
            Write-Host -Message "Failed to load module $ModulePath within the maximum retry limit."
        }
    }
}
#EndRegion '.\Public\Import-ModuleWithRetry.ps1' 89
#Region '.\Public\Install-Modules.ps1' -1

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

    # Check if running in PowerShell 5 or in a Windows environment
    # if ($PSVersionTable.PSVersion.Major -eq 5 -or ($PSVersionTable.Platform -eq 'Win32NT' -or [System.Environment]::OSVersion.Platform -eq [System.PlatformID]::Win32NT)) {
    # # Install the NuGet package provider if the condition is met
    # Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser
    # }

    if ($PSVersionTable.PSVersion.Major -eq 5) {
        # Install the NuGet package provider if the condition is met
        Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser
    }

    
    foreach ($module in $Modules) {
        if (-not (Get-Module -ListAvailable -Name $module)) {
            # Install-Module -Name $module -Force -Scope AllUsers
            Install-Module -Name $module -Force -Scope CurrentUser
            Write-EnhancedLog -Message "Module '$module' installed." -Level "INFO" -ForegroundColor
        }
        else {
            Write-EnhancedLog -Message "Module '$module' is already installed." -Level "INFO" -ForegroundColor
        }
    }
}
#EndRegion '.\Public\Install-Modules.ps1' 30
#Region '.\Public\Install-RequiredModules.ps1' -1

# function Install-RequiredModules {

# [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12

# # $requiredModules = @("Microsoft.Graph", "Microsoft.Graph.Authentication")
# $requiredModules = @("Microsoft.Graph.Authentication")

# foreach ($module in $requiredModules) {
# if (!(Get-Module -ListAvailable -Name $module)) {

# Write-EnhancedLog -Message "Installing module: $module" -Level "INFO" -ForegroundColor ([ConsoleColor]::Cyan)
# Install-Module -Name $module -Force
# Write-EnhancedLog -Message "Module: $module has been installed" -Level "INFO" -ForegroundColor ([ConsoleColor]::Cyan)
# }
# else {
# Write-EnhancedLog -Message "Module $module is already installed" -Level "INFO" -ForegroundColor ([ConsoleColor]::Cyan)
# }
# }


# $ImportedModules = @("Microsoft.Graph.Identity.DirectoryManagement", "Microsoft.Graph.Authentication")
    
# foreach ($Importedmodule in $ImportedModules) {
# if ((Get-Module -ListAvailable -Name $Importedmodule)) {
# Write-EnhancedLog -Message "Importing module: $Importedmodule" -Level "INFO" -ForegroundColor ([ConsoleColor]::Cyan)
# Import-Module -Name $Importedmodule
# Write-EnhancedLog -Message "Module: $Importedmodule has been Imported" -Level "INFO" -ForegroundColor ([ConsoleColor]::Cyan)
# }
# }


# }
#EndRegion '.\Public\Install-RequiredModules.ps1' 33
#Region '.\Public\InstallAndImportModulesPSGallery.ps1' -1

function InstallAndImportModulesPSGallery {

    <#
.SYNOPSIS
    Validates, installs, and imports required PowerShell modules specified in a JSON file.
 
.DESCRIPTION
    This function reads the 'modules.json' file from the script's directory, validates the existence of the required modules,
    installs any that are missing, and imports the specified modules into the current session.
 
.PARAMETER None
    This function does not take any parameters.
 
.NOTES
    This function relies on a properly formatted 'modules.json' file in the script's root directory.
    The JSON file should have 'requiredModules' and 'importedModules' arrays defined.
 
.EXAMPLE
    InstallAndImportModules
    This example reads the 'modules.json' file, installs any missing required modules, and imports the specified modules.
#>


    # Define the path to the modules.json file
    # $moduleJsonPath = "$PSScriptRoot/modules.json"

    param (
        [Parameter(Mandatory = $true)]
        [string]$moduleJsonPath
    )
    
    if (Test-Path -Path $moduleJsonPath) {
        try {
            # Read and convert JSON data from the modules.json file
            $moduleData = Get-Content -Path $moduleJsonPath | ConvertFrom-Json
            $requiredModules = $moduleData.requiredModules
            $importedModules = $moduleData.importedModules

            # Validate, Install, and Import Modules
            if ($requiredModules) {
                Install-Modules -Modules $requiredModules
            }
            if ($importedModules) {
                Import-Modules -Modules $importedModules
            }

            Write-EnhancedLog -Message "Modules installed and imported successfully." -Level "INFO" -ForegroundColor ([ConsoleColor]::Green)
        }
        catch {
            Write-EnhancedLog -Message "Error processing modules.json: $_" -Level "ERROR" -ForegroundColor ([ConsoleColor]::Red)
        }
    }
    else {
        Write-EnhancedLog -Message "modules.json file not found." -Level "ERROR" -ForegroundColor ([ConsoleColor]::Red)
    }
}
#EndRegion '.\Public\InstallAndImportModulesPSGallery.ps1' 56
#Region '.\Public\Is-ServerCore.ps1' -1

function Is-ServerCore {
    $explorerPath = "$env:SystemRoot\explorer.exe"

    if (Test-Path $explorerPath) {
        return $false
    } else {
        return $true
    }
}

Is-ServerCore
#EndRegion '.\Public\Is-ServerCore.ps1' 12
#Region '.\Public\IsAdmin.ps1' -1

function IsAdmin {
    <#
    .SYNOPSIS
    Checks if the current user is an administrator.
    #>

    [CmdletBinding()]
    param ()

    Begin {
        Write-EnhancedLog -Message "Starting Is-Admin function" -Level "INFO"
    }

    Process {
        try {
            Write-EnhancedLog -Message "Checking if the current user is an administrator" -Level "INFO"
            $identity = [Security.Principal.WindowsIdentity]::GetCurrent()
            $principal = [Security.Principal.WindowsPrincipal] $identity
            $isAdmin = $principal.IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
            
            if ($isAdmin) {
                Write-EnhancedLog -Message "Current user is an administrator" -Level "INFO"
            } else {
                Write-EnhancedLog -Message "Current user is not an administrator" -Level "WARNING"
            }
            
            return $isAdmin
        } catch {
            Write-EnhancedLog -Message "An error occurred while checking administrator status: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            return $false
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Is-Admin function" -Level "INFO"
    }
}
#EndRegion '.\Public\IsAdmin.ps1' 38