Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Subscribe
Archives
April 18, 2023

Switching Things Up in PowerShell

Learning the mechanics and syntax of PowerShell is not that difficult. Anyone can read the documentation for a concept like an IF statement and understand how to use it. What isn’t always apparent is the how and why, the in-between squishy bits of PowerShell. That’s one of the reasons I started this newsletter - to teach people about the PowerShell culture.

Today, I want to discuss managing logic decisions in your PowerShell scripts and functions. Let’s begin with this demonstration script file.

#requires -version 5.1
#requires -runAsAdministrator

#menu1.ps1

$menu = {
    Clear-Host
    $options = @"

    $([char]27)[4;3;92mManagement Menu$([char]27)[0m

  1 - Get uptime
  2 - Get top 20 processes
  3 - Get temp folder size
  4 - Get memory usage
  5 - Get disk usage
  6 - Quit

"@

    Write-Host "$options"
    Read-Host "  $([char]27)[1;38;5;11mSelect a menu option$([char]27)[0m [1-6]"
}

Do {
    <#
    The scriptblocks explicitly pipe to Out-Host to force proper
    formatting. Normally, you would never need to do this.
    #>
    $r = Invoke-Command -ScriptBlock $menu
    if ($r -eq 1) {
        $os = Get-CimInstance -ClassName Win32_OperatingSystem -Property LastBootUpTime
        [PSCustomObject]@{
            LastBoot = $os.LastBootUpTime
            Uptime   = New-TimeSpan -Start $os.LastBootUpTime -End (Get-Date)
        } | Out-Host
        Pause
    }
    elseif ($r -eq 2) {
        Get-Process | Sort-Object WorkingSet64 -Descending | Select-Object -First 20 | Out-Host
        Pause
    }
    elseif ($r -eq 3) {
        $stat = Get-ChildItem -Path $ENV:TEMP -File -Recurse |
        Measure-Object -Property Length -Sum
        [PSCustomObject]@{
            Path  = $ENV:TEMP
            Files = $stat.Count
            SumMB   = $stat.sum/1MB
        } | Out-Host
        Pause
    }
    elseif ($r -eq 4) {
        $os = Get-CimInstance -ClassName Win32_OperatingSystem -Property FreePhysicalMemory,TotalVisibleMemorySize
        $pctFreeMem = [math]::Round(($os.FreePhysicalMemory / $os.TotalVisibleMemorySize) * 100, 2)
        [PSCustomObject]@{
            FreeMemoryKB = $os.FreePhysicalMemory
            PctFree   = $pctFreeMem
        } | Out-Host
        Pause
    }
    elseif ($r -eq 5) {
        #Filter out Google Drive assignments
        $disks = Get-CimInstance -ClassName Win32_LogicalDisk -filter "DriveType=3 AND FileSystem='NTFS'"
        $out = foreach ($disk in $disks) {
            [PSCustomObject]@{
                Drive = $disk.DeviceID
                SizeGB = $disk.Size/1gb -as [Int]
                FreeGB = $disk.FreeSpace/1GB
                PctFree ="{0:p2}" -f ($disk.FreeSpace/$disk.Size)
            }
        }
        $out | Out-Host
        Pause
    }
    elseif ($r -eq 6) {
        #don't do anything except exit
    }
    else {
        Write-Host 'Invalid choice. Please try again.' -ForegroundColor Red
        Pause
    }

} Until ($r -eq 6)

The script presents a menu and prompts the user.

Want to read the full issue?
GitHub Bluesky LinkedIn About Jeff
Powered by Buttondown, the easiest way to start and grow your newsletter.