Analyth.PowerShell.psm1

# Module: Analyth.PowerShell
# Description: this module contains functions to manage Windows Servers and Windows Clients.

#Requires -RunAsAdministrator

$moduleName = "Analyth.PowerShell"

function Test-IsAdmin {
    # Test if you run the shell as admin
    ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
}

if ((Test-IsAdmin) -ne $true) {
    Write-Output "Please run this script with admin privileges."
    Read-Host
    Break
}

function Clear-Logs {
    <#
    .SYNOPSIS
        Clear Windows Logs.
    .DESCRIPTION
        It clears all the logs (Event Viewer Logs) on your current computer. It uses the cmdlet "Get-WinEvent" to realize the cleaning.
        Some logs cannot be cleaned up because they are linked to the system or locked for other reasons.
    .EXAMPLE
        Clear-Logs
    .NOTES
        It must be run as admin to allow to delete logs.
    #>


    [CmdletBinding()]
    Param()
    
    # Run as admin
    Test-IsAdmin | Out-Null
    
    # Clear all the event logs on your computer.
    Write-Output "Clearing logs in progress... Please be patient!"
    Get-WinEvent -ListLog * -Force | Where-Object { Wevtutil.exe Clear-Log $_.LogName } | Out-Null
    Write-Output "Clearing logs done. Thanks for your patience."
}

# Run the application "Disk Cleanup" (also known as cleanmgr) in auto-mode with all options selected.
function Invoke-CleanMgr {
    <#
    .SYNOPSIS
        Start "Disk Cleanup" (cleanmgr.exe) with all options enable.
    .DESCRIPTION
        Clean Manager allows to clean up your computer. This function starts the application "Disk Cleanup" (cleanmgr.exe) in auto-mode.
        It automatically tick all options in the application and start a cleaning.
        Options ticked: Microsoft Defender Antivirus, Windows upgrade log files, Downloaded Program Files, Temporary Internet Files, DirectX Shader Cache, Delivery Optimization Files, Device driver packages, Language Resource Files, Recyle Bin, Temporary files, Thumbnails, User file history.
    .EXAMPLE
        Invoke-CleanMgr
    .NOTES
        The application "Disk Cleanup" opens 2 Windows during the cleaning. It has no possibility to hide the 2 Windows during the process.
    #>


    [CmdletBinding()]
    Param()

    # Run as admin
    Test-IsAdmin | Out-Null
        
    $FreespaceBefore = (Get-CimInstance -ClassName Win32_Logicaldisk -Filter "DeviceID='C:'" | 
        Select-Object @{Name = "FreeSpace (GB)"; Expression = { [math]::Round($_.Freespace / 1GB, 2) } })

    function Set-SageRun {
        param (
            [int]$StateFlags
        )

        $Number = $StateFlags
        try {
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Active Setup Temp Folders' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\BranchCache' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\D3D Shader Cache' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Delivery Optimization Files' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Diagnostic Data Viewer database files' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Downloaded Program Files' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Internet Cache Files' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Language Pack' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Old ChkDsk Files' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Recycle Bin' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\RetailDemo Offline Content' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Service Pack Cleanup' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Setup Log Files' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\System error memory dump files' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\System error minidump files' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Temporary Files' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Temporary Sync Files' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Thumbnail Cache' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Update Cleanup' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\User file versions' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Windows Defender' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Windows Error Reporting Files' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Temporary Setup Files' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
            New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Previous Installations' -PropertyType 'DWORD' -Force -Name "StateFlags$Number" -Value 0x2
        }
        catch {
            "An error occured"
        }
    }

    $flag = 1234
    Set-SageRun -StateFlags $flag
    Start-Process -FilePath CleanMgr.exe -ArgumentList "/sagerun:$flag" -NoNewWindow -PassThru

    do {
        Clear-Host
        "Waiting for cleanmgr to complete."
        Start-Sleep -Seconds 1
        Clear-Host
        "Waiting for cleanmgr to complete.."
        Start-Sleep -Seconds 1
        Clear-Host
        "Waiting for cleanmgr to complete..."
        Start-Sleep -Seconds 1
    } while ((Get-Process | Where-Object { $_.Name -eq 'cleanmgr' }).Count -gt 0)

    $FreespaceAfter = (Get-CimInstance -ClassName Win32_Logicaldisk -Filter "DeviceID='C:'" | 
        Select-Object @{Name = "FreeSpace (GB)"; Expression = { [math]::Round($_.Freespace / 1GB, 2) } })

    "Free Space Before: {0}" -f $FreespaceBefore
    "Free Space After: {0}" -f $FreespaceAfter

    "The cleaning is complete!"
}


function Update-PowerShell {
    # Update PowerShell with the latest version
    Invoke-Expression "& { $(Invoke-RestMethod https://aka.ms/install-powershell.ps1) } -UseMSI"
}

function Start-WindowsUpdate {
    # Windows Update by using the module PSWindowsUpdate
    $moduleName = "PSWindowsUpdate"

    if (Get-Module -ListAvailable -Name $moduleName) {
        Import-Module $moduleName
        Write-Output "Module $moduleName exists."
        $currentDate = Get-Date -Format "yyyy-MM-dd"
        $desktopPath = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::Desktop)
        $outputFilePath = "$desktopPath\$currentDate-WindowsUpdate_Patches_Installed.txt"
        Write-Output "Installing Windows Updates... Please be patient!"
        Install-WindowsUpdate -MicrosoftUpdate -UpdateType Software -AcceptAll | Out-File $outputFilePath -force
        Write-Output "All patches have been installed. Thanks for your patience."
    } 
    else {
        Write-Output "Module $moduleName does not exist."
        try {
            Install-Module -Name $moduleName -Force
            Write-Output "Module $moduleName has been installed."
        }
        catch {
            Write-Error $_.ErrorDetails
        }
    }
}

function Start-MicrosoftStoreUpdate {
    # Same as click on the button "Get Updates" of the Microsoft Store.
    Get-CimInstance -Namespace "Root\cimv2\mdm\dmmap" -ClassName "MDM_EnterpriseModernAppManagement_AppManagement01" | 
    Invoke-CimMethod -MethodName UpdateScanMethod
}

function Install-VirtualBoxGuestAdditions {
    # Install the latest version of VirtualBox Guest Additions

    # Run as admin
    Test-IsAdmin | Out-Null

    Write-Output "Installation of VirtualBox Guest Additions for Windows - Beginning"

    # Get the latest VirtualBox version number
    $getLatestVersion = Invoke-WebRequest -URI "https://download.virtualbox.org/virtualbox/LATEST.TXT" -UseBasicParsing
    $getLatestVersion.Content.TrimEnd() | Out-Null
    $version = ($getLatestVersion).Content.ToString()
    
    # Parse the folder containing the latest version to get the name of the "VirtualBox Guest Additions"
    $url = ("https://download.virtualbox.org/virtualbox/$version").TrimEnd()
    $fileNameToDownload = (Invoke-WebRequest -Uri $url -UseBasicParsing | ForEach-Object { $_.Links } | Where-Object { $_.href -like "VBoxGuestAdditions*.iso" } | Select-Object -Property href)
    $fileName = $fileNameToDownload.href
    $finalUrl = "$url\$fileName"

    # Save iso file locally
    $pathToSaveFile = "$env:TEMP\VBoxGuestAdditions.iso"

    if (Test-Path -Path $pathToSaveFile) {
        Remove-Item -Path $pathToSaveFile -Force
        Write-Output "The old version of the file has been deleted."
    }

    if (-not (Test-Path -Path $pathToSaveFile)) {
        Write-Output "Download in progress... Please be patient!"
        Invoke-WebRequest -Uri "$url\$fileName" -OutFile $pathToSaveFile -UseBasicParsing
        Write-Output "The file has been downloaded."
    }

    # Mount ISO and run the exe in silent mode
    $isoDrive = Mount-DiskImage -ImagePath $pathToSaveFile -PassThru
    $isoLetter = ($isoDrive | Get-Volume).DriveLetter
    $exePath = ($isoLetter + ":\" + "VBoxWindowsAdditions.exe")

    # Install VBoxGuestAdditions silently
    Start-Process -FilePath $exePath -ArgumentList @("/S") -Wait
    Write-Output "VBoxGuestAdditions has been installed"

    # Dismount ISO
    Dismount-DiskImage -ImagePath $pathToSaveFile | Out-Null
    Dismount-DiskImage -ImagePath $pathToSaveFile | Out-Null
    Write-Output "Installation of VirtualBox Guest Additions for Windows - End"

    Write-Host "Do you want to restart your computer right now to complete the installation?"
    Write-Host "[Y]es or [N]o, default is No."
    
    $answer = Read-Host
    if ($answer -eq "Y" -or $answer -eq "Yes") {
        Write-Output "You said Yes"
        Restart-Computer
    }
    elseif ($answer -eq "N" -or $answer -eq "No") {
        Write-Output "You said No"
        Write-Output "Have a nice day!"
    }
    else {
        Write-Output "Your answer is confused, so your computer will not restart."
        Write-Output "Have a nice day!"
    }
}

function Uninstall-AllChocolateyPackages {
    # List all packages installed and then uninstall them (-x = manage dependencies)
    choco list -l | foreach-object { $_.Split(" ")[0] } | foreach-object { choco uninstall $_ -x }
}

# This command is automatically executed when the module is loaded to create aliases with prefix "ana" for all the functions
Get-Command -Module $moduleName | 
Where-Object { ($_.CommandType -eq "function" -and $_.Name -ne "Test-IsAdmin") } | 
ForEach-Object { $name = $_.Name ; Set-Alias "ana-$name" $name }