Private/New-IntuneDetection.ps1

<#
.Synopsis
Created on: 17/03/2024
Update on: 08/01/2025
Created by: Ben Whitmore
Filename: New-IntuneDetection.ps1
 
.Description
Function to get the local detection methods from the detection methods xml object
 
.PARAMETER LogId
The component (script name) passed as LogID to the 'Write-Log' function.
This parameter is built from the line number of the call from the function up the
 
.PARAMETER LocalSettings
The local detection method settings array to convert to JSON
 
.PARAMETER Script
The local detection method script to prepare
#>


function New-IntuneDetectionMethod {
    param (
        [Parameter(Mandatory = $false, ValuefromPipeline = $false, HelpMessage = "The component (script name) passed as LogID to the 'Write-Log' function")]
        [string]$LogId = $($MyInvocation.MyCommand).Name,
        [Parameter(Mandatory = $false, ValueFromPipeline = $false, Position = 0, HelpMessage = 'The local detection method settings array to convert to JSON', ParameterSetName = 'Methods')]
        [object]$LocalSettings,
        [Parameter(Mandatory = $false, ValueFromPipeline = $false, Position = 1, HelpMessage = 'The local detection method script to prepare', ParameterSetName = 'Methods')]
        [object]$Script
    )
    begin {

        # Helper functions to create the JSON objects
        # Function to convert empty strings to $null in JSON
        function Convert-EmptyStringToNullInJson {
            param (
                [Parameter(Mandatory = $true)]
                [string]$Json
            )
            
            # Convert the JSON to objects
            $objects = $Json | ConvertFrom-Json
            
            function Update-Object {
                param (
                    $Object
                )
                
                # Check key values for empty strings and convert to $null
                foreach ($property in $Object.PSObject.Properties) {
                    if ($property.Value -is [string] -and $property.Value -eq '') {
                        $property.Value = $null
                    }
                    elseif ($property.Value -is [PSCustomObject] -or $property.Value -is [array]) {
                        Update-Object -Object $property.Value
                    }
                }
            }
            
            # Process each object
            foreach ($obj in $objects) {
                Update-Object -Object $obj
            }
            
            # Return the new JSON
            $newJson = $objects | ConvertTo-Json -Depth 5
            return $newJson
        }
        
        # Registry detection method
        function Add-SimpleSetting {
            param(
                [string]$is64Bit,
                [string]$keyPath,
                [string]$valueName,
                [string]$operator,
                [string]$version,
                [string]$detectionType,
                [string]$detectionValue
            )
            
            # Prepare 64bit check
            if ($is64Bit -eq 'true') {
                $check32BitOn64System = [bool]$false
            }
            else {
                $check32BitOn64System = [bool]$true
            }

            # Set the detection type
            $detectionType = $detectionType.ToLower()

            # Prepare operands for the Intune detection method
            switch ($operator) {
                'Equals' {
                    $operator = 'equal'
                }
                'NotEquals' {
                    $operator = 'notEqual'
                }
                'GreaterThan' {
                    $operator = 'greaterThan'
                }
                'GreaterEquals' {
                    $operator = 'greaterThanOrEqual'
                }
                'LessThan' {
                    $operator = 'lessThan'
                }
                'LessEquals' {
                    $operator = 'lessThanOrEqual'
                }
                'Match' {
                    $operator = 'match'
                }
                'NotMatch' {
                    $operator = 'notMatch'
                }
                'Contains' {
                    $operator = 'contains'
                }
                'NotContains' {
                    $operator = 'notContains'
                }
                'BeginsWith' {
                    $operator = 'beginsWith'
                }
                'EndsWith' {
                    $operator = 'endsWith'
                }
            }

            # Prepare detection types for the Intune detection method
            switch ($detectionType) {
                'Int64' {
                    $detectionType = 'integer'
                }
            }

            $object = [PSCustomObject]@{
                '@odata.type'          = '#microsoft.graph.win32LobAppRegistryDetection'
                'check32BitOn64System' = $check32BitOn64System
                'detectionType'        = $detectionType
                'detectionValue'       = $detectionValue
                'keyPath'              = $keyPath
                'operator'             = $operator
                'valueName'            = $valueName
            }
            return $object
        }
        
        # File or Folder detection method
        function Add-File {
            param(
                [string]$is64Bit,
                [string]$detectionType,
                [string]$detectionValue,
                [string]$fileOrFolderName,
                [string]$operator,
                [string]$path
            )

            # Prepare 64bit check
            if ($is64Bit -eq 'true') {
                $check32BitOn64System = [bool]$false
            }
            else {
                $check32BitOn64System = [bool]$true
            }

            # Set the detection type
            $detectionType = $detectionType.ToLower()

            # Prepare operands for the Intune detection method
            switch ($operator) {
                'Equals' {
                    $operator = 'equal'
                }
                'NotEquals' {
                    $operator = 'notEqual'
                }
                'GreaterThan' {
                    $operator = 'greaterThan'
                }
                'GreaterEquals' {
                    $operator = 'greaterThanOrEqual'
                }
                'LessThan' {
                    $operator = 'lessThan'
                }
                'LessEquals' {
                    $operator = 'lessThanOrEqual'
                }
                'Match' {
                    $operator = 'match'
                }
                'NotMatch' {
                    $operator = 'notMatch'
                }
                'Contains' {
                    $operator = 'contains'
                }
                'NotContains' {
                    $operator = 'notContains'
                }
                'BeginsWith' {
                    $operator = 'beginsWith'
                }
                'EndsWith' {
                    $operator = 'endsWith'
                }
            }

            # Check detection types
            if ($operator -eq 'notEquals' -and $detectionValue -eq 0 -and $detectionType -eq 'int64') {
                $operator = 'notConfigured'
                $detectionType = 'exists'
                $detectionValue = $null
            }

            $object = [PSCustomObject]@{
                '@odata.type'          = '#microsoft.graph.win32LobAppFileSystemDetection'
                'check32BitOn64System' = $check32BitOn64System
                'detectionType'        = $detectionType
                'detectionValue'       = $detectionValue
                'fileOrFolderName'     = $fileOrFolderName
                'operator'             = $operator
                'path'                 = $path

            }
            return $object
        }
        
        # MSI detection method
        function Add-MSI {
            param(
                [string]$productCode,
                [string]$productVersion,
                [string]$productVersionOperator
            )

            # Prepare operands for the Intune detection method
            switch ($productVersionOperator) {
                'Equals' {
                    $productVersionOperator = 'equal'
                }
                'NotEquals' {
                    $productVersionOperator = 'notEqual'
                }
                'GreaterThan' {
                    $productVersionOperator = 'greaterThan'
                }
                'GreaterEquals' {
                    $productVersionOperator = 'greaterThanOrEqual'
                }
                'LessThan' {
                    $productVersionOperator = 'lessThan'
                }
                'LessEquals' {
                    $productVersionOperator = 'lessThanOrEqual'
                }
            }

            # Check if the product version is not configured
            if ( -not $productVersion -and -not $productVersionOperator) {
                $productVersion = $null
                $productVersionOperator = 'notConfigured'
            }

            $object = [PSCustomObject]@{
                '@odata.type'            = '#microsoft.graph.win32LobAppProductCodeDetection'
                'productCode'            = $productCode
                'productVersion'         = $productVersion
                'productVersionOperator' = $productVersionOperator
            }
            return $object
        }
    }
    process {
        if ($PSCmdlet.ParameterSetName -eq 'Methods') {
            if ($PSBoundParameters.Keys.Count -gt 1) {
                Write-LogAndHost -Message 'Only one parameter is allowed in parameter set "Methods". Choose either "LocalSettings" or "Script"' -LogId $LogId -Severity 3
                return
            }
            else {
                if ($PSBoundParameters['LocalSettings']) {
                    $jsonArray = @()
    
                    foreach ($setting in $LocalSettings) {
                        switch ($setting.Type) {
                            'SimpleSetting' {

                                # Create the registry key path
                                $regPath = Join-Path -Path $setting.Hive -ChildPath $setting.Key -ErrorAction SilentlyContinue
    
                                # Add the registry detection object
                                $jsonArray += Add-SimpleSetting `
                                    -is64Bit $setting.is64Bit `
                                    -keyPath $regPath `
                                    -valueName $setting.ValueName `
                                    -operator $setting.Rules_Operator `
                                    -detectionType $setting.Rules_ConstantDataType `
                                    -detectionValue $setting.Rules_ConstantValue
                            }
                            'File' {
                                $jsonArray += Add-File `
                                    -is64Bit $setting.is64Bit `
                                    -detectionType $setting.Rules_ConstantDataType `
                                    -detectionValue $setting.Rules_ConstantValue `
                                    -fileOrFolderName $setting.Filter `
                                    -operator $setting.Rules_Operator `
                                    -path $setting.Path
                            }
                            'MSI' {
                                $jsonArray += Add-MSI `
                                    -productCode $setting.ProductCode `
                                    -ProductVersion $setting.Rules_ConstantValue `
                                    -ProductVersionOperator $setting.Rules_Operator
                            }
                            default {
                                Write-LogAndHost -Message "Unhandled detection type: $($setting.Type)" -LogId $LogId -Severity 3
                            }
                        }
                    }
    
                    # Convert to JSON
                    $json = $jsonArray | ConvertTo-Json -Depth 5
                    Convert-EmptyStringToNullInJson -Json $json
                }
                else {
                    Write-LogAndHost -Message 'No settings were passed to the function' -LogId $LogId -Severity 3
                    return
                }
            }
        }
    }  
}