Public/Invoke-IntunePlatformScriptTest.ps1

function Invoke-IntunePlatformScriptTest {
    <#
    .EXTERNALHELP IntuneScriptLab-Help.xml
    .SYNOPSIS
        Runs a platform (device) script the way Intune does and reports its run state.
    #>

    [CmdletBinding()]
    [OutputType('IntuneScriptLab.PlatformScriptResult')]
    param(
        [Parameter(Mandatory, Position = 0)]
        [string]$Path,

        [ValidateSet('x86', 'x64', 'arm64')]
        [string]$Architecture = 'x86',

        [ValidateSet('User', 'System')]
        [string]$Context = 'User',

        # Run as this account instead of the current user (with -Context User): a scheduled task in
        # the account's own session, the way the agent runs user-context scripts as the signed-in
        # user; needs an elevated session
        [System.Management.Automation.PSCredential]
        [System.Management.Automation.Credential()]
        $Credential,

        [ValidateRange(1, 86400)]
        [int]$TimeoutSeconds = 300
    )
    Write-Verbose "Starting $($MyInvocation.MyCommand.Name) for $($PSBoundParameters.Keys -join ', ')"

    $scriptRunSplat = @{
        Path           = $Path
        Architecture   = $Architecture
        Context        = $Context
        Phase          = 'script'
        TimeoutSeconds = $TimeoutSeconds
    }
    if ($Credential) {
        if ($Context -eq 'System') {
            throw '-Credential applies to -Context User; System runs as NT AUTHORITY\SYSTEM'
        }
        $scriptRunSplat.Credential = $Credential
    }
    $run = Invoke-IslScriptRun @scriptRunSplat
    $runState = if ($run.TimedOut) { 'TimedOut' } elseif ($run.ExitCode -eq 0) { 'Success' } else { 'Failed' }

    # What happens next under Intune, from the PS-FAIL experiments: a failed script is fetched and
    # run again at the agent's next script policy fetch, which happens at a service start or
    # restart and otherwise every 8 hours (the hourly Win32 check-ins fetch no script policy),
    # three runs in all, then never again
    $warnings = [System.Collections.Generic.List[string]]::new()
    if ($runState -ne 'Success') {
        $warnings.Add(('Intune runs a failed platform script again at its next script policy fetch (an agent ' +
                'start or restart, otherwise every 8 hours), three runs in total (initial plus two retries), ' +
                'then reports Failed for good'))
    }

    Write-Verbose "Completed $($MyInvocation.MyCommand.Name)"
    [pscustomobject]@{
        PSTypeName    = 'IntuneScriptLab.PlatformScriptResult'
        RunState      = $runState
        ExitCode      = $run.ExitCode
        ResultMessage = ($run.StdOut + $run.StdErr).TrimEnd("`r", "`n")
        StdOut        = $run.StdOut
        StdErr        = $run.StdErr
        TimedOut      = $run.TimedOut
        Duration      = $run.Duration
        Warnings      = $warnings.ToArray()
        Architecture  = $Architecture
        Context       = $Context
        RunAs         = $run.RunAs
        Host          = $run.Host
        ScriptPath    = $run.ScriptPath
    }
}