Public/computer_perf_report.ps1

# Computer Performance Report Script
# This script generates a comprehensive system performance report

# Parameter block must be at the top
param(
    [string]$ConnectionType = "Auto"
)

# Global variables initialization
$script:activityOutput = @{
    success = $false
    out     = @{}
    data    = @{}
}

# Default connection type - can be overridden by parameter
$script:connection = $ConnectionType

function GetDebugDetails() {
    try {
        $details = Get-WmiObject Win32_OperatingSystem | Select PSComputerName, Caption, OSArchitecture, Version, BuildNumber
        Write-Host "Debug Details: "
        Write-Host "OS: $($details.Caption)"
        Write-Host "OS Architecture: $($details.OSArchitecture)"
        Write-Host "Computer Name: $($details.PSComputerName)"
        Write-Host "Version: $($details.Version)"
        Write-Host "Build Number: $($details.BuildNumber)"
        return $details
    }
    catch {
        Write-Host "Error getting debug details: $($_.Exception.Message)"
        return $null
    }
}

function GetUserDetails() {
    try {
        ## --- Get Current Users ---
        $Active = Get-WmiObject Win32_LoggedOnUser | Select Antecedent -Unique | Where-Object {
            $_.Antecedent.ToString().Split('"')[1] -ne $($env:COMPUTERNAME) -and
            $_.Antecedent.ToString().Split('"')[1] -ne "Window Manager" -and
            $_.Antecedent.ToString().Split('"')[3] -notmatch $env:COMPUTERNAME
        } | % {
            "{0}\{1}" -f $_.Antecedent.ToString().Split('"')[1], $_.Antecedent.ToString().Split('"')[3]
        } | Where {
            $_ -notlike "NT AUTHORITY*" -and $_ -notlike "*\UMFD-*" -and $_ -notlike "*\DWM-*" -and
            $_ -notlike "*\LOCAL SERVICE*" -and $_ -notlike "*\NETWORK SERVICE*" -and $_ -notlike "*\*-*-*-*-*"
        }

        $Inactive = Get-WmiObject Win32_LoggedOnUser | Select Antecedent -Unique | % {
            "{0}\{1}" -f $_.Antecedent.ToString().Split('"')[1], $_.Antecedent.ToString().Split('"')[3]
        } | Where {
            $_ -notlike "NT AUTHORITY*" -and $_ -notlike "*\UMFD-*" -and $_ -notlike "*\DWM-*" -and
            $_ -notlike "*\LOCAL SERVICE*" -and $_ -notlike "*\NETWORK SERVICE*" -and $_ -notlike "*\*-*-*-*-*" -and $_ -ne $Active
        }

        [string]$LoggedIn = $null
        foreach ($user in $Active) {
            $LoggedIn += "$user - Active`n"
        }
        foreach ($user in $Inactive) {
            $LoggedIn += "$user - Disc`n"
        }

        $script:activityOutput.out.UserInfo = $LoggedIn
        return $LoggedIn
    }
    catch {
        Write-Host "Error getting user details: $($_.Exception.Message)"
        return $null
    }
}

function GetLargestFiles() {
    try {
        #-----Check for large files----
        Write-host "checking large files"
        $files = $null
        $filepath = ""

        foreach ($disk in (Get-WmiObject Win32_LogicalDisk)) {
            if ($disk.DriveType -ne 5 -and $disk.DriveType -ne 2 -and $disk.DriveType -ne 4) {
                $files = Get-ChildItem -Path "$($disk.Name)" -Recurse -ErrorAction SilentlyContinue |
                Select FullName, Length |
                sort -Descending -Property length |
                select -First 5 |
                select fullname, @{Name = 'Gigabytes'; Expression = { [math]::round($_.length / 1GB, 2) } }
                write-host "Done Scanning $($disk.Name)"
                write-host $files
            }
        }

        if ($files) {
            foreach ($file in $files) {
                $filepath += "$($file.Gigabytes)GB - $($file.fullname)`r`n"
            }
        }

        $script:activityOutput.out.largestFiles = $filepath
        return $filepath
    }
    catch {
        Write-Host "Error getting largest files: $($_.Exception.Message)"
        return $null
    }
}

function GetMachineDetails() {
    try {
        #-----Check for hung processes-----
        Write-host "checking hung processes"
        $allUnresponsiveProcesses = get-process * | where { $_.responding -eq $false }
        $script:activityOutput.out.unresponsiveProcesses = "None"

        $unresponsive = @()

        foreach ($unProc in $allUnresponsiveProcesses) {
            $suspendedProcess = $false
            foreach ($thread in $unProc.threads) {
                if ($thread.waitReason -eq "Suspended") {
                    $suspendedProcess = $true
                    break
                }
            }
            if ($suspendedProcess -eq $false) {
                $unresponsive += "$($unProc.name)<br />"
            }
        }

        if ($unresponsive.Count -gt 0) {
            $script:activityOutput.out.unresponsiveProcesses = $unresponsive -join ""
        }

        #-----Check Network-----
        Write-host "checking network"
        $adpaterName = ""
        $gateway = $null

        # Auto-detect connection type if not specified
        if ($script:connection -eq "Auto") {
            try {
                $wlanService = Get-Service -Name 'WlanSvc' -ErrorAction SilentlyContinue
                if ($wlanService -and $wlanService.Status -eq "Running") {
                    $SSID = $((netsh wlan show interfaces) -Match '^\s+SSID' -Replace '^\s+SSID\s+:\s+', '')
                    if ($SSID -and $SSID.Length -gt 0) {
                        $script:connection = "Wireless"
                    }
                    else {
                        $script:connection = "Ethernet"
                    }
                }
                else {
                    $script:connection = "Ethernet"
                }
            }
            catch {
                $script:connection = "Ethernet"
            }
        }

        if ($script:connection -eq "Wireless") {
            $adpaterName = (netsh wlan show interfaces) -Match '^\s+Name' -Replace '^\s+Name\s+:\s+', ''
        }
        else {
            if ((get-service dot3svc).status -ne "Running") {
                Start-Service dot3svc -ea SilentlyContinue -wa SilentlyContinue
                start-sleep -seconds 5
            }
            $adpaterName = (netsh lan show interfaces) -Match '^\s+Name' -Replace '^\s+Name\s+:\s+', ''
        }

        Write-Host $adpaterName
        if (![string]::IsNullOrEmpty($adpaterName)) {
            $gateway = (Get-NetIPConfiguration).ipv4defaultGateway.nexthop
        }

        $reachedGateway = $false
        try {
            if ($gateway -and (Test-Connection $gateway -count 3 -ea Stop)) {
                $reachedGateway = $true
            }
        }
        catch {
            Write-Host "Gateway test failed: $($_.Exception.Message)"
        }

        $netConnected = $false
        try {
            if (Test-Connection 8.8.8.8 -ea Stop) {
                $netConnected = $true
            }
        }
        catch {
            Write-Host "Internet connectivity test failed: $($_.Exception.Message)"
        }

        #-----Check for Temp files----
        Write-host "checking temp files"
        $Tempfolders = @()
        $TempFolders += "C:\Windows\Temp\*"
        $TempFolders += "C:\Windows\Prefetch\*"

        $Tempfiles = get-childitem -path $tempfolders -ErrorAction SilentlyContinue

        $UserPaths = Get-ChildItem -Path "C:\Users\*" -ErrorAction SilentlyContinue
        foreach ($user in $UserPaths) {
            if (Test-Path (Join-Path $user.FullName '\AppData\Local\Temp')) {
                $Tempfiles += Get-ChildItem -Path (Join-Path $user.FullName '\AppData\Local\Temp') -Recurse -ErrorAction SilentlyContinue
            }
        }

        $Size = $Tempfiles | measure Length -Sum
        $Filesize = [math]::Round($Size.Sum / 1MB, 2)

        $script:activityOutput.out.TempCount = $Tempfiles.Count
        $script:activityOutput.out.TempSize = $Filesize

        [Array]$objNetworkInfo = [pscustomobject]@()

        Import-Module NetTCPIP -Force | Out-Null

        $ip_var = $(Get-NetIPConfiguration | Where-Object { $_.IPv4DefaultGateway -ne $null -and $_.NetAdapter.Status -ne "Disconnected" }).IPv4Address.IPAddress

        [Array]$NetworkIPInfo = [pscustomobject]@()
        $NetworkIPInfo += [pscustomobject]@{ IP = "IPv4 Address: $ip_var"; }

        $objNetworkInfo += [pscustomobject]@{
            IPAddress      = "IP Address: $ip_var";
            Gateway        = "Gateway: $gateway";
            ReachedGateway = "Reached Gateway: $($reachedGateway.ToString())";
            NetConnected   = "Net Connected: $($netConnected.ToString())";
        }

        #---Get Computer Type (Desktop/Remote)------
        Write-host "getting computer type"
        $sessionType = $env:SessionName

        [Array]$NetworkTypeInfo = [pscustomobject]@()

        if ($sessionType -eq $null -or $sessionType -eq "" -or $sessionType.ToLower() -eq "console") {
            $script:activityOutput.out.sessionType = "local"
            $sessionType = "local"
        }
        else {
            $script:activityOutput.out.sessionType = "remote"
            $sessionType = "remote"
        }

        #----Check if on Wireless or Ethernet-----
        Write-host "getting network type"
        if ($sessionType -eq "local") {
            $connType = $null
            try {
                $service = Get-Service -Name 'WlanSvc' -ErrorAction Stop
                if ($service) {
                    if ((Get-service WlanSvc).Status -eq "Running") {
                        $SSID = $((netsh wlan show interfaces) -Match '^\s+SSID' -Replace '^\s+SSID\s+:\s+', '')

                        if ($SSID -eq $null -or $SSID.Length -eq 0) {
                            $connType = "Ethernet"
                            $NetworkTypeInfo += [pscustomobject]@{ ConnType = "Connection Type: Ethernet"; SSID = "SSID: N/A"; SignalStrength = "Signal Strength: N/A"; }
                        }
                        else {
                            $connType = "Wireless"
                            $signalStrength = (netsh wlan show interfaces) -Match '^\s+Signal' -Replace '^\s+Signal\s+:\s+', ''
                            $NetworkTypeInfo += [pscustomobject]@{ ConnType = "Connection Type: Wireless"; SSID = "SSID: $SSID"; SignalStrength = "Signal Strength: $signalStrength"; }
                        }
                    }
                    else {
                        $connType = "Ethernet"
                        $NetworkTypeInfo += [pscustomobject]@{ ConnType = "Connection Type: Ethernet"; SSID = "SSID: N/A"; SignalStrength = "Signal Strength: N/A"; }
                    }
                }
                else {
                    Write-Host "WlanSvc Not found from else"
                }
            }
            catch [Microsoft.PowerShell.Commands.ServiceCommandException] {
                Write-Host "WlanSvc Not found from catch"
            }
        }
        else {
            $connType = "Ethernet"
            $NetworkTypeInfo += [pscustomobject]@{ ConnType = "Connection Type: Ethernet"; SSID = "SSID: N/A"; SignalStrength = "Signal Strength: N/A"; }
        }

        #----Last Time machine turned on-------
        Write-host "getting uptime"
        $lastBootTime = (Get-CimInstance Win32_OperatingSystem | select LastBootUpTime).LastBootupTime
        $LastBootTimeAus = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId(($lastBootTime), 'AUS Eastern Standard Time').toString('dd/MM/yyyy h:mm tt')
        $script:activityOutput.out.lastBootTime = $lastBootTimeAus

        [Array]$GeneralSystemInfo = [pscustomobject]@()
        $GeneralSystemInfo += [pscustomobject]@{
            LastBootTime = "Last Boot Time: $lastBootTimeAus";
            Unresponsive = $unresponsive;
            TempCount    = $Tempfiles.Count;
            TempSize     = $Filesize
        }

        #----Get Build Information-----
        Write-Host "getting General Computer Information"

        $wmiOSInfo = Get-WmiObject Win32_OperatingSystem

        $BuildNo = $($wmiOSInfo.BuildNumber)
        [string]$Win10Ver = switch ($BuildNo) {
            "10240" { "1507" }
            "10586" { "1511" }
            "14393" { "1607" }
            "15063" { "1703" }
            "16299" { "1709" }
            "17134" { "1803" }
            "17763" { "1809" }
            "18362" { "1903" }
            "18363" { "1909" }
            "19041" { "2004" }
            "19042" { "20H2" }
            "19043" { "21H1" }
            "19044" { "21H2" }
            "22621" { "22H2" }
        }
        [string]$Release = switch ($BuildNo) {
            "10240" { "(Released Jul 2015)" }
            "10586" { "(Released Nov 2015)" }
            "14393" { "(Released Aug 2016)" }
            "15063" { "(Released Apr 2017)" }
            "16299" { "(Released Oct 2017)" }
            "17134" { "(Released Apr 2018)" }
            "17763" { "(Released Nov 2018)" }
            "18362" { "(Released May 2019)" }
            "18363" { "(Released Nov 2019)" }
            "19041" { "(Released May 2020)" }
            "19042" { "(Released Oct 2020)" }
            "19043" { "(Released May 2021)" }
            "19044" { "TBA" }
            "22621" { "(Released Sep 2021)" }
        }

        Write-Host "Build: $BuildNo"

        if ([string]::IsNullOrEmpty($Win10Ver)) {
            $Win10Ver = "Unable to find OS Version"
            Write-Host "Version: $Win10Ver"
        }
        else {
            Write-Host "Version: $Win10Ver"
        }

        $is64bit = [System.Environment]::Is64BitOperatingSystem
        if ($is64bit) {
            [string]$OSBitType = "64-Bit"
        }
        else {
            [string]$OSBitType = "32-Bit"
        }

        $PCInfo = Get-WmiObject Win32_ComputerSystem
        $PCInfo2 = Get-WmiObject win32_ComputerSystemProduct
        $wmiCPUInfo = Get-WmiObject -Class Win32_Processor

        $wmiRAMInfo = Get-WmiObject win32_Physicalmemory
        $DriveInfo = Get-WmiObject -Class MSFT_PhysicalDisk -Namespace root\Microsoft\Windows\Storage -ErrorAction SilentlyContinue

        $Enclosure = (Get-WmiObject Win32_SystemEnclosure).ChassisTypes

        [string]$DeviceType = switch ($Enclosure) {
            "1" { "Other" }
            "2" { "Unknown" }
            "3" { "Desktop" }
            "4" { "Low Profile Desktop" }
            "5" { "Pizza Box" }
            "6" { "Mini Tower" }
            "7" { "Tower" }
            "8" { "Portable" }
            "9" { "Laptop" }
            "10" { "Notebook" }
            "11" { "Hand Held" }
            "12" { "Docking Station" }
            "13" { "All in One" }
            "14" { "Sub Notebook" }
            "15" { "Space-Saving" }
            "16" { "Lunch Box" }
            "17" { "Main System Chassis" }
            "18" { "Expansion Chassis" }
            "19" { "SubChassis" }
            "20" { "Bus Expansion Chassis" }
            "21" { "Peripheral Chassis" }
            "22" { "Storage Chassis" }
            "23" { "Rack Mount Chassis" }
            "24" { "Sealed-Case PC" }
            "30" { "Tablet" }
            "31" { "Convertible" }
            "32" { "Detachable" }
        }

        [Array]$CPUInfo = [pscustomobject]@()
        $CPUInfo += [pscustomobject]@{Type = "CPU Type: $DeviceType"; Name = "CPU Name: $($wmiCPUInfo.Name)" }

        [Array]$OSInfo = [pscustomobject]@()
        $OSInfo += [pscustomobject]@{Edition = "Edition: $($wmiOSInfo.Caption) $OSBitType"; Version = "Version: $Win10Ver $Release"; Domain = "Domain: $($PCInfo.Domain)" }

        [Array]$RAMHardwareInfo = [pscustomobject]@()
        $i = 0
        foreach ($item in $wmiRAMInfo) {
            $i++
            $RAMHardwareInfo += [pscustomobject]@{ Count = $i; Manufacturer = "Manufacturer: $($item.Manufacturer)"; PartNumber = $("Part Number: $($item.PartNumber)").Trim(); Capacity = "Capacity: $($($item.Capacity)/1GB)GB"; }
        }
        if ($wmiRAMInfo -eq $null -and $(Get-WmiObject Win32_BaseBoard).Product -eq "Virtualbox") {
            $RAMHardwareInfo += [pscustomobject]@{ Count = 1; Manufacturer = "Manufacturer: Virtualbox"; PartNumber = "Part Number: None"; Capacity = "Capacity: Unknown"; }
        }

        $i = 0
        [Array]$DriveHardwareInfo = [pscustomobject]@()
        if ($DriveInfo) {
            foreach ($item in $DriveInfo) {
                $i++
                $DriveHardwareInfo += [pscustomobject]@{ Count = $i; Manufacturer = "Manufacturer: $($item.FriendlyName)"; Type = "Type: $(switch($($item.MediaType)){ '3' {'HDD'}; '4' {'SSD'}; '0' {'Virtual'};})" }
            }
        }

        [Array]$VendorInfo = [pscustomobject]@()
        $modelno = $($PCInfo2.Version)

        if ([string]::IsNullOrEmpty($modelno) -or $modelno -eq " ") {
            $modelno = "Not found."
        }

        $VendorInfo += [pscustomobject]@{Model = "Model: $($PCInfo2.Name)"; ModelNo = "Model No: $modelno"; Vendor = "Vendor: $($PCInfo2.Vendor)"; SerialNo = "Serial No: $($PCInfo2.IdentifyingNumber)" }

        #----Most Recent Patch------
        Write-host "getting patches"
        $hotfix = "$((Get-HotFix | Sort-Object InstalledOn -ErrorAction SilentlyContinue -Descending)[0].HotFixID) - Installed $(((Get-HotFix | Sort-Object InstalledOn -ErrorAction SilentlyContinue -Descending)[0].InstalledOn).toString('dd/MM/yyyy'))"
        $hotfix.Replace("`n", "<br />")
        $script:activityOutput.out.hotFix = $hotfix

        Write-host "getting powerplan"
        $powerplan = "N/A"
        if ($sessionType -eq "local") {
            try {
                $powerplan = (powercfg -GETACTIVESCHEME)
                $powerplan = $powerplan.Substring(0, $powerplan.Length - 1)
                $powerplan = $powerplan.Split('(')[-1]

                $battery = Get-WmiObject -Class Win32_Battery | Select-Object -First 1
                $noAC = $battery -ne $null -and $battery.BatteryStatus -eq 1

                if ($noAC) {
                    $powerplan += " - On Battery"
                }
                else {
                    $powerplan += " - On Mains"
                }
            }
            catch {
                $powerplan = "Unable to retrieve power plan"
            }
        }

        $script:activityOutput.out.powerProfile = $powerplan
        [Array]$PowerInfo = [pscustomobject]@()
        $PowerInfo += [pscustomobject]@{ PowerPlan = $powerplan; }
        [Array]$CPULoad = [pscustomobject]@()

        #---Get CPU Load---
        Write-host "getting CPU"
        $cpuLoadPercentage = (Get-WmiObject -Class win32_Processor -ErrorAction Stop | Select-Object LoadPercentage).LoadPercentage
        $script:activityOutput.out.CPUload = $cpuLoadPercentage
        $CPULoad += [pscustomobject]@{ Load = "CPU Load: $cpuLoadPercentage%"; }

        #top 10 processes
        $CpuCores = (Get-WMIObject Win32_ComputerSystem).NumberOfLogicalProcessors
        $CPUProcesses = (Get-Counter "\Process(*)\% Processor Time" -SampleInterval 1 -MaxSamples 30 -ErrorAction SilentlyContinue).CounterSamples |
        Where-Object { $_.instancename -NotLike "_total" -and $_.instancename -NotLike "idle" } |
        Group-Object -Property Instancename |
        Select Name, @{Name = "Min"; Expression = { [Decimal]::Round((($_.group | Measure-Object CookedValue -Minimum).minimum / $CpuCores), 2) } },
        @{Name = "Avg"; Expression = { [Decimal]::Round((($_.group | Measure-Object CookedValue -average).average / $CpuCores), 2) } },
        @{Name = "Max"; Expression = { [Decimal]::Round((($_.group | Measure-Object CookedValue -maximum).maximum / $CpuCores), 2) } } |
        Sort-Object -Property Avg -Descending |
        Select-Object -First 10

        [string]$CPUResultString = $null
        foreach ($item in $CPUProcesses) {
            $CPUResultString += "Min:$($item.Min) Avg:$($item.Avg) Max:$($item.Max) - $($item.Name)<br />"
        }

        #------Get Machine memory------
        Write-host "getting Memory"
        $maxMemory = ((Get-WmiObject Win32_physicalMemory) | Measure-Object Capacity -Sum).sum / 1GB
        $consumedMemory = 0

        foreach ($WS in (get-process | select-object Name, @{Name = 'WorkingSet'; Expression = { ($_.WorkingSet64) } })) {
            $consumedMemory += $WS.WorkingSet
        }
        $consumedMemory = [math]::Round($consumedMemory / 1GB, 2)

        #top 10 RAM uses
        $RAMArray = @()
        $timer = 0
        While ($Timer -lt 10) {
            $RAMArray += $RAMTest = Get-Process | Group-Object -Property ProcessName | Select Name, @{Name = 'Memory_usage'; Expression = { [math]::Round((($_.Group | Measure-Object WorkingSet64 -Sum).Sum / 1MB), 2) } }
            Start-Sleep -seconds 1
            $timer ++
        }
        $RAMResult = $RAMArray | Group-Object -Property Name | Select Name, @{Name = 'Memory_usage'; Expression = { [math]::Round((($_.Group | Measure-Object "Memory_usage" -Average).Average), 2) } } | Sort-Object -Property 'Memory_usage' -Descending | select -first 10

        [string]$RAMResultString = $null
        foreach ($item in $RAMResult) {
            $RAMResultString += "$($item.Memory_usage)MB - $($item.Name)<br />"
        }

        $script:activityOutput.out.ProcessMemory = $RAMResultString
        $script:activityOutput.out.maxMemory = $maxMemory
        $script:activityOutput.out.consumedMemory = $consumedMemory

        #----Get Capacity and remaining space for disks----
        $allDisks = @()
        $diskCount = 0

        $Drives = Get-WmiObject Win32_Volume -ErrorAction SilentlyContinue | Where-Object { $_.DriveLetter -NotLike $Null -and $_.DriveType -eq "3" } | Select DriveLetter, @{Name = "Capacity"; Expression = { [math]::Round($_.capacity / 1GB, 2) } }, @{Name = "FreeSpace"; Expression = { [math]::Round($_.FreeSpace / 1GB, 2) } } | Sort-Object -Property FreeSpace -Descending

        [string]$DriveResultString = $null
        foreach ($item in $Drives) {
            $DriveResultString += "Drive: $($item.DriveLetter) - Capacity: $($item.Capacity)GB - Used: $($item.Capacity - $item.FreeSpace)GB - Free: $($item.FreeSpace)GB<br />"
        }

        $data = @{
            OSInfo            = $OSInfo;
            CPUInfo           = $CPUInfo;
            CPULoad           = $CPULoad;
            RAMHardwareInfo   = $RAMHardwareInfo;
            DriveHardwareInfo = $DriveHardwareInfo;
            DriveResultString = $DriveResultString;
            VendorInfo        = $VendorInfo;
            GeneralSystemInfo = $GeneralSystemInfo;
            PowerInfo         = $PowerInfo;
            NetworkTypeInfo   = $NetworkTypeInfo;
            ConsumedMemory    = $consumedMemory;
            NetworkInfo       = $objNetworkInfo;
            CPUProcesses      = $CPUResultString;
            RAMResult         = $RAMResultString;
            Hotfixes          = $hotfix;
        }

        Write-Host $(ConvertTo-Json $data -Depth 10)

        $script:activityOutput.out.data = $data

        [string]$OtherInfo = $null
        $OtherInfo += "Last Boot: $lastBootTimeAus`n"
        $OtherInfo += "Power Plan: $powerplan`n"

        $script:activityOutput.out.OtherInfo = $OtherInfo

        return $data
    }
    catch {
        Write-Host "Error in GetMachineDetails: $($_.Exception.Message)"
        return $null
    }
}

function MainActivity() {
    try {
        Write-Host "Starting Computer Performance Report..."
        Write-Host "GetDebugDetails"
        GetDebugDetails
        Write-Host "GetUserDetails"
        $captureReturn3 = GetUserDetails
        Write-Host "GetMachineDetails"
        $captureReturn4 = GetMachineDetails

        # Add to the log
        $script:activityOutput.success = $true
        return $script:activityOutput
    }
    catch {
        Write-Host "Error in MainActivity: $($_.Exception.Message)"
        $script:activityOutput.success = $false
        return $script:activityOutput
    }
}

Function ExecuteActivity() {
    $exec = MainActivity
    return $script:activityOutput
}

# Main execution - only run if script is called directly
if ($MyInvocation.InvocationName -eq $MyInvocation.MyCommand.Name) {
    Write-Host "Computer Performance Report"
    Write-Host "=========================="

    $result = ExecuteActivity

    if ($result.success) {
        Write-Host "`nReport completed successfully!"
        Write-Host "Data available in: `$result.out.data"
    }
    else {
        Write-Host "`nReport completed with errors."
    }

    return $result
}

function ComputerPerformanceReport {
    # Main execution - only run if script is called directly
    if ($MyInvocation.InvocationName -eq $MyInvocation.MyCommand.Name) {
        Write-Host "Computer Performance Report"
        Write-Host "=========================="

        $result = ExecuteActivity

        if ($result.success) {
            Write-Host "`nReport completed successfully!"
            Write-Host "Data available in: `$result.out.data"
        }
        else {
            Write-Host "`nReport completed with errors."
        }
        return $result
    }
}