--- title: "Automation Examples" slug: "automation-examples" updated: 2026-04-17T07:58:43Z published: 2026-04-17T07:58:43Z canonical: "documentation.lakesidesoftware.com/automation-examples" --- > ## Documentation Index > Fetch the complete documentation index at: https://documentation.lakesidesoftware.com/llms.txt > Use this file to discover all available pages before exploring further. # Automation Examples # Automation Examples ## Return Code Script This sample script demonstrates how to add a return code to an automation. It is provided for example purposes only and is not part of a released automation. ### ReturnCodeSample.ps1 ```powershell <# .SYNOPSIS    ExampleAutomationReturnCode.ps1 .DESCRIPTION    This script is used for Advanced Disk Clean that contains multiple user profiles. .INPUTS    None .OUTPUTS    All output is written into a log file in the same location from which the script is run. .NOTES    Version:            1.10.4    Author:             Lakeside Software, carsten.giese@lakesidesoftware.com    Requirements:       This script assumed to be run by the SysTrack agent (local SYSTEM account). The                        folder deletion action requires local administrator permissions.    Changes:            1.0.0 - Initial Release                        1.1.0 - Stability improvements, unique error codes, dynamic path discovery                        1.2.0 - WMI-based profile deletion, safe junction handling                        1.2.1 - Removed dangerous fallback for profiles directory discovery                        1.2.2 - Refactored temp cleanup to use array-based approach                        1.3.0 - Dynamic drive detection from profiles path using .NET DriveInfo                        1.4.0 - Enhanced logging for all deletion operations                        1.5.0 - Added diagnostic logging for profile evaluation and skip conditions                        1.6.0 - Added check for missing timestamp data to identify orphaned profiles                        1.6.1 - Replaced hardcoded orphaned age with boolean flag, improved profile logging                        1.6.2 - Changed internal units to MB with explicit variable naming                        1.7.0 - Refactored freed space thresholds into configurable hashtable                        1.8.0 - Added dynamic unit formatting for freed space display                        1.9.0 - Added protected system profile names to prevent deletion                        1.9.1 - Fixed logic to allow temp cleanup for all profiles, preserve temp folder structure                        1.9.2 - Optimized flow to cleanup first then check deletion, reduced error spam                        1.10.0 - Added comprehensive temp cleanup logging for visibility                        1.10.1 - Improved variable naming for clarity and safety                        1.10.2 - Two-pass bottom-up deletion for better locked-file handling                        1.10.3 - Added threshold sorting for robust return code determination                        1.10.4 - Further improved variable naming for code clarity                                        Copyright 2020 LAKESIDE SOFTWARE, INC. .LINK    http://www.lakesidesoftware.com #> # Clean the output screen and reset all cached variables cls Remove-Variable * -ea 0 # Set the default for what we want to happen if an unexpected error occurs # https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_preference_variables?view=powershell-7.3#erroractionpreference $ErrorActionPreference = "Stop" # Initialize script-level variables $script:resetLog = $true $scriptPath = $null $logfile = $null # Logging function with error-safe file operations function log($text) {    $line = ''    if ($text) {        $time = [datetime]::Now.ToUniversalTime().tostring('s')        $line = [string]::Join(' - ', $time, $text)    }        # Console output if available    if ($psISE -or -not [Console]::IsOutputRedirected) {        Write-Output $line    }        # File output with error suppression to prevent logging failures from crashing script    try {        if ($script:resetLog) {            $line | Out-File $logfile -Encoding utf8 -Force -ErrorAction Stop            $script:resetLog = $false        } else {            $line | Out-File $logfile -Encoding utf8 -Append -ErrorAction Stop        }    }    catch {        # Silently continue if logging fails - don't crash the script    } } # Format disk size from MB to appropriate unit for display function Format-DiskSize($sizeInMB) {    if ($sizeInMB -ge 1024) {        return "$([math]::Round($sizeInMB/1024, 2))GB"    } elseif ($sizeInMB -ge 1) {        return "$([math]::Round($sizeInMB, 2))MB"    } elseif ($sizeInMB -ge 0.001) {        return "$([math]::Round($sizeInMB * 1024, 2))KB"    } else {        return "$([math]::Round($sizeInMB * 1024 * 1024, 2))bytes"    } } # Main script body $scriptExitCode = 0 $profileDeletionAgeThresholdInDays = 60 $skipNonADProfiles = $true # Define system profile names to protect from deletion $protectedProfileNames = @(    "WsiAccount",    "DefaultAccount",    "WDAGUtilityAccount",    "Administrator",    "Guest",    "Public",    "Default" ) # Define profile subdirectories to clean for all profiles $profileSubfoldersToClean = @(    "AppData\Local\Temp",    "AppData\Local\Temporary Internet Files" ) # Define freed space thresholds and corresponding return codes $freedSpaceReturnCodes = @(    @{ ThresholdMB = 100; ReturnCode = 101; Description = "Less than 100MB freed" }    @{ ThresholdMB = 500; ReturnCode = 102; Description = "100MB to 500MB freed" }    @{ ThresholdMB = [int]::MaxValue; ReturnCode = 103; Description = "500MB or more freed" } ) try {    # Determine script location    if ($PSScriptRoot) {        $scriptPath = $MyInvocation.MyCommand.Path    } elseif ($psISE -and $psISE.CurrentFile) {        if ($psISE.CurrentFile.IsSaved -and $psISE.CurrentFile.FullPath) {            $scriptPath = $psISE.CurrentFile.FullPath        } else {            throw "Script is not saved in ISE"        }    } else {        throw "Unable to determine script location"    }    $logfile = $scriptPath + ".log"        # Log script initialization    log "Script starting ..."    log "Powershell Version: $($PSVersionTable.PSVersion)"    log ".NET CLR Version: $([System.Environment]::Version)"    # --- START OF VERSION CHECK ---    $requiredPSMajorVersion = 5    $currentPSMajorVersion = $PSVersionTable.PSVersion.Major    if ($currentPSMajorVersion -lt $requiredPSMajorVersion) {        log "ERROR: Minimum required PowerShell Major version is $($requiredPSMajorVersion)"        $scriptExitCode = 1        throw    }        # Log execution context    $CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent()    log "Running As: $($CurrentUser.Name)"    if (([Security.Principal.WindowsPrincipal]$CurrentUser).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {        log "Is an Administrator"    } else {        log "ERROR: Script needs to be started as admin or local System."        $scriptExitCode = 2        throw    }        # Check architecture    log "Architecture: $($Env:PROCESSOR_ARCHITECTURE)"    if ($env:PROCESSOR_ARCHITEW6432 -eq "AMD64") {        log "Running 32-bit Powershell on 64-bit Windows"    }        # Discover user profiles directory from registry    log "Discovering user profiles directory from registry"    try {        $profilesKey = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" -Name ProfilesDirectory -ErrorAction Stop        $usersPath = $profilesKey.ProfilesDirectory                if (-not $usersPath -or -not (Test-Path $usersPath)) {            throw "ProfilesDirectory registry value is invalid or path does not exist"        }                log "User profiles directory: $usersPath"    }    catch {        log "ERROR: Failed to discover user profiles directory from registry"        $scriptExitCode = 3        throw    }        # Extract drive letter from profiles path    $driveLetter = Split-Path -Qualifier $usersPath    log "Target drive: $driveLetter"        # Get initial disk information    log "Getting initial disk information"    try {        $driveInfo = [System.IO.DriveInfo]::new($driveLetter)        $freeSpace_before_MB = [math]::Round($driveInfo.AvailableFreeSpace/1MB, 2)        log "Disk Free Space before script run: $([math]::Round($freeSpace_before_MB/1024, 2))GB`n"    }    catch {        log "ERROR: Failed to get initial disk information"        $scriptExitCode = 4        throw    }        # Enumerate WMI user profiles    log "Enumerating WMI user profiles"    try {        $wmiProfiles = Get-WMIObject -class Win32_UserProfile -ErrorAction Stop        log "Found $($wmiProfiles.Count) WMI user profiles"    }    catch {        log "ERROR: Failed to enumerate WMI user profiles"        $scriptExitCode = 5        throw    }        # Enumerate registry profile entries    log "Enumerating registry ProfileList entries"    try {        $profileListKey = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\*"        $registryProfiles = Get-ItemProperty $profileListKey -ErrorAction Stop        log "Found $($registryProfiles.Count) registry profile entries`n"    }    catch {        log "ERROR: Failed to enumerate registry ProfileList entries"        $scriptExitCode = 6        throw    }        # Process each registry profile entry    $currentDateTime = [datetime]::Now    $profilesProcessed = 0    $profilesSkipped = 0        foreach ($profileRegistry in $registryProfiles) {        $profileSID = $profileRegistry.PSChildName        $profilePath = $profileRegistry.ProfileImagePath                # Log profile identification with path if available, otherwise SID        if ($profilePath) {            log "Evaluating profile: $profilePath ($profileSID)"        } else {            log "Evaluating profile SID: $profileSID (no ProfileImagePath)"        }                # Get corresponding WMI profile object        $wmiProfile = $wmiProfiles | Where-Object {$_.SID -eq $profileSID}                # Perform temp cleanup for ALL profiles first        if ($profilePath -and (Test-Path $profilePath -PathType Container -ea 0)) {            foreach ($profileSubfolder in $profileSubfoldersToClean) {                $subfolderPath = Join-Path $profilePath $profileSubfolder                if (Test-Path $subfolderPath -PathType Container) {                    log "Attempting to clean folder: $profileSubfolder"                    $successCount = 0                    $failureCount = 0                                        try {                        # Get all files in subfolder                        $filesToDelete = Get-ChildItem -Path $subfolderPath -Recurse -Force -File -ErrorAction SilentlyContinue                                                # Delete all files first                        foreach ($file in $filesToDelete) {                            try {                                [System.IO.File]::Delete($file.FullName)                                $successCount++                            }                            catch {                                $failureCount++                            }                        }                                                # Get all directories and sort by path length (deepest first)                        $directoriesToDelete = Get-ChildItem -Path $subfolderPath -Recurse -Force -Directory -ErrorAction SilentlyContinue                        $directoriesSorted = $directoriesToDelete | Sort-Object { $_.FullName.Length } -Descending                                                # Delete folders deepest-first                        foreach ($directory in $directoriesSorted) {                            try {                                [System.IO.Directory]::Delete($directory.FullName, $false)                                $successCount++                            }                            catch {                                $failureCount++                            }                        }                                                log "Cleaned $successCount items, $failureCount items could not be deleted (in use by other processes)"                    }                    catch {                        log "Failed to access subfolder: ..\$profileSubfolder"                    }                } else {                    log "Subfolder does not exist: ..\$profileSubfolder"                }            }        }                # Now check deletion criteria        # Skip special profiles from deletion        if ($wmiProfile.Special) {            log "Special profile - skipping deletion`n"            $profilesSkipped++            continue        }                # Skip non-AD profiles from deletion if configured        if ($skipNonADProfiles -and !$profileSID.StartsWith('S-1-5-21')) {            log "Non-AD profile - skipping deletion`n"            $profilesSkipped++            continue        }                # Skip protected system profiles from deletion        if ($profilePath) {            $profileFolderName = Split-Path -Leaf $profilePath            if ($protectedProfileNames -contains $profileFolderName) {                log "Protected system profile: $profileFolderName - skipping deletion`n"                $profilesSkipped++                continue            }        }                # Calculate age and check for orphaned status (only now after filters pass)        $isOrphaned = $false        $profileAgeInDays = 0                if ($profileRegistry.State -eq $null) {            # Orphaned profile with no state            $isOrphaned = $true            log "Orphaned profile detected (no State value)"        } elseif ($null -eq $profileRegistry.PSObject.Properties['LocalProfileLoadTimeHigh']) {            # Orphaned profile with missing timestamp data            $isOrphaned = $true            log "Orphaned profile detected (missing load timestamp)"        } else {            # Calculate age from LocalProfileLoadTime            $high = [uint64]$profileRegistry.LocalProfileLoadTimeHigh            $low = [uint64]$profileRegistry.LocalProfileLoadTimeLow            $lastLoadTime = [datetime]::FromFileTime($high -shl 32 -bor $low)            $profileAgeInDays = ($currentDateTime - $lastLoadTime).TotalDays        }                # Skip profiles with unexpected age values from deletion        if (!$isOrphaned -and (!$profileAgeInDays -or $profileAgeInDays -gt 5000)) {            log "Profile has invalid age ($profileAgeInDays days) - skipping deletion`n"            $profilesSkipped++            continue        }                $profilesProcessed++                # Check if profile should be deleted based on age or orphaned status        if ($isOrphaned -or $profileAgeInDays -gt $profileDeletionAgeThresholdInDays) {            # Delete old or orphaned profile            if ($isOrphaned) {                log "Profile marked for deletion (orphaned)"            } else {                log "Profile marked for deletion - Age: $([math]::Round($profileAgeInDays, 2)) days - Exceeds threshold"            }                        if (Test-Path $profilePath -PathType Container) {                log "Attempting to remove profile folder and data"                try {                    # Using .NET Directory.Delete() to safely handle junctions without following them into different locations                    [System.IO.Directory]::Delete($profilePath, $true)                    log "Successfully deleted profile folder: $profilePath"                }                catch {                    log "Failed to delete profile folder: $profilePath"                }            } else {                log "Profile folder does not exist, will remove WMI object only"            }                        # If folder was successfully deleted or didn't exist, remove WMI profile object            if (-not (Test-Path $profilePath -PathType Container)) {                log "Attempting to remove WMI profile object"                try {                    $wmiProfile | Remove-WmiObject -ErrorAction Stop                    log "Successfully removed WMI profile object`n"                }                catch {                    log "Failed to remove WMI profile object"                    log $_.Exception.Message                }            } else {                log "Skipping WMI removal - profile folder still exists`n"            }        }        else {            # Profile is below age threshold            log "Active profile - Age: $([math]::Round($profileAgeInDays, 2)) days - Below threshold`n"        }    }        log "Profile processing summary: $profilesProcessed processed, $profilesSkipped skipped`n"        # Get final disk information    log "Getting final disk information"    try {        $driveInfo = [System.IO.DriveInfo]::new($driveLetter)        $freeSpace_after_MB = [math]::Round($driveInfo.AvailableFreeSpace/1MB, 2)    }    catch {        log "ERROR: Failed to get final disk information"        $scriptExitCode = 7        throw    }        $FreedSpace_MB = [math]::Max(0, $freeSpace_after_MB - $freeSpace_before_MB)    log "Disk Free Space after script run: $([math]::Round($freeSpace_after_MB/1024, 2))GB"    log "Total freed space: $(Format-DiskSize $FreedSpace_MB)"        # Determine return code based on freed space thresholds    $sortedThresholds = $freedSpaceReturnCodes | Sort-Object { $_.ThresholdMB }    foreach ($threshold in $sortedThresholds) {        if ($FreedSpace_MB -lt $threshold.ThresholdMB) {            $scriptExitCode = $threshold.ReturnCode            break        }    } } catch {    # General exception handler    if ($scriptExitCode -eq 0) {        log "ERROR: Unexpected exception occurred during script execution"        log $error[0].FullyQualifiedErrorId        log $error[0].Exception.ToString()        log $error[0].ScriptStackTrace        $scriptExitCode = 6    } } finally {    log "Script complete returning ($scriptExitCode)"    Exit $scriptExitCode } ``` ### **ReturnCodeSample.bat** ```plaintext @ECHO OFF PUSHD %~dps0 SET "SCRIPTFILE=ReturnCodeSample.ps1" IF NOT EXIST "%SCRIPTFILE%" SET "SCRIPTFILE=%~n0.ps1" :: Execute the PowerShell script: SET "SYS32=System32" IF "%PROCESSOR_ARCHITECTURE%" == "x86" SET "SYS32=SysNative" SET "POWERSHELL=%WINDIR%\%SYS32%\WindowsPowerShell\v1.0\powershell.exe" "%POWERSHELL%" -NOPROFILE -EXECUTIONPOLICY BYPASS -FILE "%SCRIPTFILE%" %* > "%~nx0.log" 2>&1 SET "EXITCODE=%ERRORLEVEL%" POPD EXIT /B %EXITCODE% ``` ### **Script Output** ![](https://cdn.document360.io/87d11426-6b1f-4b19-b593-b71e55a81af3/Images/Documentation/return_code_output.png) ## **Sample Hello World Script** This is an automation example. The **HelloWorldLogs.bat** script is not maintained and is not guaranteed to work. Use at your own risk. ```powershell @echo off PowerShell -ExecutionPolicy Bypass -File "HelloWorldLogs.ps1" EXIT /B %ERRORLEVEL% HelloWorldLogs.ps1 <# .SYNOPSIS    HelloWorld.PS1 .DESCRIPTION    This script will pop up a Hello World Window .INPUTS    None .OUTPUTS    When enabled, a log file will be created in the same location from which the script is run. .NOTES    Version:            1.0    Author:             Lakeside Software    Requirements:       This script is assumed to be run by the SysTrack agent (local SYSTEM account).                        This script is NOT maintained and is not guaranteed to work and is meant as an example                                                USE AT YOUR OWN RISK                        Copyright 2023 LAKESIDE SOFTWARE, INC. .LINK    http://www.lakesidesoftware.com #> ##### # Begin Functions #####    #####    # Function: LogWrite (Logging)    #####    function LogWrite([string]$info)    {              if($script:log -eq $true)        {              # Write to logfile date - message            "$(get-date -format "yyyy-MM-dd HH:mm:ss") -  $info" >> $logfile            # Any logged Start or Exit statements also write to host            If ( ($info.contains("Starting Script")) -or ($info.contains("Exiting Script")) ) {                Write-Host $info            }            # Any logged Warning or Error statements also write to host            If ( ($info.contains("Error:")) -or ($info.contains("Warning"))) {                Write-Host "  " $info  "(See Log For Details)"            }        }        else  {            Write-Host $info        }    }                  #####    # Function: NewFile (Logging, Location)    #####    function NewFile($data, $loc)    {          If (test-path $loc) {Remove-Item $loc}        "$data" >> $loc          LogWrite "Data saved to $loc"    }          #####    # Function: ExitScript    #####    function ExitScript($msg, $ExitCode)    {        ### Cleanup        If ($Silent) {            Write-Progress -Activity "Working..." `            -Completed -Status $msg        }                ### Log Exit        LogWrite "$msg ($ExitCode)"        LogWrite "Exiting Script..."        Logwrite ""        #Exit        Exit($ExitCode)    }   ##### # End Functions ##### ##### # Advanced Variables #####          #logging    If (!$Logging) {$Logging = $true}    $ErrorActionPreference = "Stop"    $debug = $false    $retain = $false # new log on each run        $ScriptName = & { $myInvocation.ScriptName }    $ScriptPath = Split-Path -parent $ScriptName    $ScriptName = Split-Path $ScriptName -Leaf    $ScriptName = $ScriptName.Replace(".PS1","")        $logfile = "$ScriptPath\$ScriptName" + "Log.txt"    $script:log = $Logging    $Dev = "False"     ##### # Start Script #####    cls        ### Delete existing log files > 1mb    If (test-path $logfile) {        If ($retain -eq $true) {            If ((Get-Item $logfile).length -gt 1mb) {                Remove-Item $logfile            }        }        Else {            Remove-Item $logfile        }    }     ##### # Start Script #####    ### Start Script    LogWrite ""    LogWrite "Starting Script..."        $WhoAmI = [Environment]::UserName    $Is64Bit = [Environment]::Is64BitProcess        LogWrite "Running As:  $WhoAmI"    LogWrite "64bit Process:  $Is64Bit"        #LogWrite "About to try writing hello world to a file..."    try{        LogWrite "Start Hello World! Invoking Forms."        Add-Type -AssemblyName System.Windows.Forms        LogWrite "Hello World!!"    }    catch{        LogWrite "Unable to popup Hello World prompt due"        LogWrite $error[0].FullyQualifiedErrorId        LogWrite $error[0].Exception.ToString()        LogWrite $error[0].ScriptStackTrace        ExitScript -msg "Script Failed" -code 1    } ##### # Exit Script #####        ExitScript -msg "Script Completed" -code 0 ```