UpdatePowerShellGet_Manual.ps1

# Manual PowerShellGet/PackageManagement Update
# Bypasses Install-Module to avoid module locking issues

Write-Host "========================================================================" -ForegroundColor Cyan
Write-Host "Manual PowerShellGet/PackageManagement Update (Direct Download Method)" -ForegroundColor Cyan
Write-Host "========================================================================" -ForegroundColor Cyan
Write-Host ""

# Check if running as admin
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
    Write-Host "ERROR: This script must run with administrator privileges!" -ForegroundColor Red
    Write-Host "Press any key to exit..."
    $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
    exit 1
}

# Setup paths
$tempPath = Join-Path $env:TEMP "PSModuleUpdate"
$userModulePath = Join-Path ([Environment]::GetFolderPath("MyDocuments")) "WindowsPowerShell\Modules"
$nugetPath = Join-Path $tempPath "nuget.exe"

Write-Host "Temporary working directory: $tempPath" -ForegroundColor Yellow
Write-Host "User module installation path: $userModulePath" -ForegroundColor Yellow
Write-Host ""

# Create temp directory
if (Test-Path $tempPath) {
    Remove-Item $tempPath -Recurse -Force -ErrorAction SilentlyContinue
}
New-Item -ItemType Directory -Path $tempPath -Force | Out-Null

# Download NuGet.exe
Write-Host "Downloading NuGet.exe..." -ForegroundColor Green
try {
    $nugetUrl = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
    Invoke-WebRequest -Uri $nugetUrl -OutFile $nugetPath -UseBasicParsing
    Write-Host "SUCCESS: NuGet.exe downloaded" -ForegroundColor Green
} catch {
    Write-Host "ERROR downloading NuGet.exe: $($_.Exception.Message)" -ForegroundColor Red
    Write-Host "Press any key to exit..."
    $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
    exit 1
}
Write-Host ""

# Function to download and install a module
function Install-ModuleManually {
    param(
        [string]$ModuleName,
        [string]$NugetExe,
        [string]$TempPath,
        [string]$InstallPath
    )

    Write-Host "========================================" -ForegroundColor Cyan
    Write-Host "Processing: $ModuleName" -ForegroundColor Yellow
    Write-Host "========================================" -ForegroundColor Cyan

    # Download package using NuGet
    Write-Host "Downloading $ModuleName from PowerShell Gallery..." -ForegroundColor Green
    $downloadPath = Join-Path $TempPath $ModuleName
    New-Item -ItemType Directory -Path $downloadPath -Force | Out-Null

    Push-Location $downloadPath
    try {
        & $NugetExe install $ModuleName -Source "https://www.powershellgallery.com/api/v2" -OutputDirectory . -NonInteractive -Verbosity quiet

        # Find the downloaded package folder
        $packageFolder = Get-ChildItem -Directory | Where-Object { $_.Name -like "$ModuleName.*" } | Select-Object -First 1

        if (-not $packageFolder) {
            Write-Host "ERROR: Package folder not found after download" -ForegroundColor Red
            return $false
        }

        Write-Host "Downloaded version: $($packageFolder.Name)" -ForegroundColor Green

        # Extract version number
        $version = $packageFolder.Name -replace "^$ModuleName\.", ""

        # Setup destination
        $moduleDestination = Join-Path $InstallPath "$ModuleName\$version"

        # Remove old version in this location if exists
        if (Test-Path $moduleDestination) {
            Write-Host "Removing existing version at: $moduleDestination" -ForegroundColor Yellow
            Remove-Item $moduleDestination -Recurse -Force
        }

        # Create destination directory
        New-Item -ItemType Directory -Path $moduleDestination -Force | Out-Null

        # Copy module files to destination
        Write-Host "Installing to: $moduleDestination" -ForegroundColor Green
        Copy-Item -Path (Join-Path $packageFolder.FullName "*") -Destination $moduleDestination -Recurse -Force

        Write-Host "SUCCESS: $ModuleName $version installed!" -ForegroundColor Green
        Write-Host ""
        return $true

    } catch {
        Write-Host "ERROR installing $($ModuleName): $($_.Exception.Message)" -ForegroundColor Red
        Write-Host ""
        return $false
    } finally {
        Pop-Location
    }
}

# Install PackageManagement first
$pm = Install-ModuleManually -ModuleName "PackageManagement" -NugetExe $nugetPath -TempPath $tempPath -InstallPath $userModulePath

# Install PowerShellGet
$psg = Install-ModuleManually -ModuleName "PowerShellGet" -NugetExe $nugetPath -TempPath $tempPath -InstallPath $userModulePath

# Cleanup
Write-Host "Cleaning up temporary files..." -ForegroundColor Yellow
Remove-Item $tempPath -Recurse -Force -ErrorAction SilentlyContinue
Write-Host ""

# Show results
Write-Host "========================================================================" -ForegroundColor Cyan
Write-Host "Installation Summary" -ForegroundColor Cyan
Write-Host "========================================================================" -ForegroundColor Cyan
Write-Host "PackageManagement: $(if($pm){'SUCCESS'}else{'FAILED'})" -ForegroundColor $(if($pm){'Green'}else{'Red'})
Write-Host "PowerShellGet: $(if($psg){'SUCCESS'}else{'FAILED'})" -ForegroundColor $(if($psg){'Green'}else{'Red'})
Write-Host ""

Write-Host "All installed versions:" -ForegroundColor Yellow
Get-Module -Name PowerShellGet, PackageManagement -ListAvailable |
    Select-Object Name, Version, Path |
    Sort-Object Name, Version -Descending |
    Format-Table -AutoSize
Write-Host ""

Write-Host "========================================================================" -ForegroundColor Cyan
Write-Host "IMPORTANT: Close ALL PowerShell windows and reopen to use new versions!" -ForegroundColor Yellow
Write-Host "========================================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Press any key to exit..."
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")