Public/Intune/Get-AppWorkloadPoliciesTest.ps1

<#
    .DESCRIPTION
        Stolen From: https://www.deploymentresearch.com/read-cmlogs-with-powershell-and-hello-world/
#>


function Get-AppWorkloadPoliciesTest {
    [CmdletBinding()]
    param (
        [string]
        [string]$Path = "$(Get-Location)\AppWorkload*.log",
        [switch]$Latest,
        [switch]$DetectionScript,
        [switch]$RequirementScript
    )

    Write-Host -ForegroundColor DarkGray "[$((Get-Date).ToString('HH:mm:ss'))] Searching for [AppWorkload*.log]"
    foreach ($File in $(Resolve-Path $Path)) {
        Write-Host -ForegroundColor DarkGray "[$((Get-Date).ToString('HH:mm:ss'))] Found [$File]"
    }

    # Policy Pattern
    [string]$Pattern = '<!\[LOG\[Get policies = \[(.*?)\]\]'

    # Search Log File(s) for the Pattern
    $PatternMatches = $null
    if ($Latest) {
        $PatternMatches = Select-String -Path "$($Path)" -Pattern $Pattern | Select-Object -Last 1
    }
    else {
        $PatternMatches = Select-String -Path "$($Path)" -Pattern $Pattern
    }

    # Check if the Pattern was found
    if ($PatternMatches) {
        # Start Building PSCustomObject
        [Collections.Generic.List[PSCustomObject]]$PolicyApps = @()

        foreach ($Match in $PatternMatches) {
            # Parse the Line for the Policy JSON by removing the Start and End Pattern
            $PolicyJson = $null
            $PolicyJson = $Match.Line -replace '^\<\!\[LOG\[Get policies = ', '' -replace '\]LOG\]!>.*', ''

            # Parse the Line for the Date
            $PolicyDate = Read-CMTraceLogLine -LineContent "$($Match.Line)"

            # Convert the String from JSON
            $Policy = $null
            $Policy = $PolicyJson | ConvertFrom-Json -ErrorAction Stop

            $Policy | ForEach-Object {
                # Build a PSCustomObject
                $CusObj = [PSCustomObject] @{
                    'Policy Date' = $PolicyDate.DateTime
                    'App Id'      = $_.Id
                    'App Name'    = $_.Name
                    Revision      = $_.Version
                    Intent        = switch ($_.Intent) {
                        0 { 'Not Targeted' }
                        1 { 'Available' }
                        3 { 'Required' }
                        4 { 'Uninstall' }
                        Default { $_.Intent }
                    }
                    Context       = switch ((ConvertFrom-Json $_.InstallEx).RunAs) {
                        0 { 'USER' }
                        1 { 'SYSTEM' }
                        Default { $InstallEx.RunAs }
                    }
                    TimeFormat    = $_.StartDeadlineEx.TimeFormat
                    StartTime     = if ($_.StartDeadlineEx.StartTime -eq '1/1/0001 12:00:00 AM') { 'ASAP' } else { $_.StartDeadlineEx.StartTime }
                    Deadline      = if ($_.StartDeadlineEx.Deadline -eq '1/1/0001 12:00:00 AM') { 'ASAP' } else { $_.StartDeadlineEx.Deadline }
                    DO            = switch ($_.DOPriority) {
                        0 { 'Background' }
                        1 { 'Foreground' }
                        Default { $_.DOPriority }
                    }
                    Notifications = switch ($_.AvailableAppEnforcement) {
                        0 { 'Show All' }
                        1 { 'On Restart' }
                        2 { '2' }
                        3 { 'Hide All' }
                        Default { $_.NotificationPriority }
                    }
                }

                # Add Detection Script to PSCustomObject
                if ($DetectionScript) {
                    # Check Detection is a Script
                    $DetectionScriptValue = ($_.DetectionRule | ConvertFrom-Json -ErrorAction SilentlyContinue)
                    if ($DetectionScriptValue.DetectionType -eq 3) {
                        # Extract Script Body
                        $DetectionScriptValue = (ConvertFrom-Json ($DetectionScriptValue.DetectionText) | Select-Object -ExpandProperty ScriptBody -ErrorAction SilentlyContinue)
                        # Decode Base64
                        $DetectionScriptValue = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($DetectionScriptValue))

                        $DetectionObject = [PSCustomObject]@{
                            AppName = $(Get-PowerShellVariables -ScriptContent $DetectionScriptValue -VariableName "z")
                            AppVersion = $(Get-PowerShellVariables -ScriptContent $DetectionScriptValue -VariableName "d")
                        }

                        # Add to PSCustomObject
                        $CusObj | Add-Member -MemberType NoteProperty -Name 'Detection Script' -Value $DetectionObject

                        # Check Script Signature Signer
                        if ($DetectionScriptValue -match '# SIG # Begin signature block') {
                            # Convert the detection script string to byte array for Get-AuthenticodeSignature
                            $DetectionScriptSigner = ((Get-AuthenticodeSignature -Content $([System.Text.Encoding]::UTF8.GetBytes($DetectionScriptValue)) -SourcePathOrExtension ".ps1" | Select-Object *).SignerCertificate.Subject -split ',')[0]
                            # Add to PSCustomObject
                            $CusObj | Add-Member -MemberType NoteProperty -Name 'Detection Signer' -Value ($DetectionScriptSigner)
                        }
                        else {
                            $CusObj | Add-Member -MemberType NoteProperty -Name 'Detection Signer' -Value 'Not Signed'
                        }
                    }
                    else {
                        $CusObj | Add-Member -MemberType NoteProperty -Name 'Detection Script' -Value 'Not a Script'
                        $CusObj | Add-Member -MemberType NoteProperty -Name 'Detection Signer' -Value 'Not Signed'
                    }
                }

                # Add Requirement Script to PSCustomObject
                if ($RequirementScript) {
                    # Check Requirement is a Script
                    $RequirementScriptValue = ($_.ExtendedRequirementRules | ConvertFrom-Json -ErrorAction SilentlyContinue)
                    if ($RequirementScriptValue.Type -eq 3) {
                        # Extract Script Body
                        $RequirementScriptValue = (ConvertFrom-Json ($RequirementScriptValue.RequirementText) | Select-Object -ExpandProperty ScriptBody -ErrorAction SilentlyContinue)
                        # Decode Base64
                        $RequirementScriptValue = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($RequirementScriptValue))

                        # Add to PSCustomObject
                        $CusObj | Add-Member -MemberType NoteProperty -Name 'Requirement Script' -Value ($RequirementScriptValue)

                        # Check Script Signature Signer
                        if ($RequirementScriptValue -match '# SIG # Begin signature block') {
                            # Convert the requirement script string to byte array for Get-AuthenticodeSignature
                            $RequirementScriptSigner = ((Get-AuthenticodeSignature -Content $([System.Text.Encoding]::UTF8.GetBytes($RequirementScriptValue)) -SourcePathOrExtension ".ps1" | Select-Object *).SignerCertificate.Subject -split ',')[0]
                            # Add to PSCustomObject
                            $CusObj | Add-Member -MemberType NoteProperty -Name 'Requirement Signer' -Value ($RequirementScriptSigner)
                        }
                        else {
                            $CusObj | Add-Member -MemberType NoteProperty -Name 'Requirement Signer' -Value 'Not Signed'
                        }
                    }
                    else {
                        $CusObj | Add-Member -MemberType NoteProperty -Name 'Requirement Script' -Value 'Not a Script'
                        $CusObj | Add-Member -MemberType NoteProperty -Name 'Requirement Signer' -Value 'Not Signed'
                    }
                }

                # Add PSCustomObject to List
                $PolicyApps.Add($CusObj)
            }
        }
        $PolicyApps | Sort-Object 'App Name', 'App Id' | Out-GridView -Title "AppWorkload Policies [Total Records: $($PolicyApps.Count)]" -OutputMode Single
    }
    else {
        Write-Host "No Match Found"
    }
}