There are still many applications that cannot be installed via MSI or a simple installation routine. This is where the win32 app comes into play in Intune (Microsoft Endpoint Manager). In Intune, this allows us to deal with routines and processes in a script and then check the installation with another script (custom detection script) or predefined detection rules (MSI, EXE, file or registry key).

In the past few years, I have accumulated a few different variations of detection scripts, which I am trying to collect here.

Use the button above to find my current collection of custom detection scripts for Intune win32 apps. It is important that you only use one of the blocks for your detection rule. If you want to know how a win32 app is structured in general and how I handle it, you can find it here (my take on win32 apps - Intune) one of my past blog posts.

You can currently find the following detection rules in my GitHub repository:

  • Detection of an EXE or a file
  • Validation file with specific content (e.g. versioning)
  • Existing EXE with exact target version
    • or higher version
    • and additional registry key
  • Registry key comparison
  • Detection of a scheduled task
  • Detection of a scheduled task including version

Custom Detection Scripts in Intune: Best Practices

Before diving into custom detection scripts, it's essential to understand one key principle: always use Intune's built-in detection options whenever they meet your needs.

Built-in options, like checking for registry keys or file existence, are faster, more reliable, and better integrated with the Intune service. They reduce complexity and potential points of failure.

Use a custom script only when:

  1. OR logic is required (e.g., detecting one of multiple possible registry keys).
  2. You need to combine registry checks with additional logic or conditions.
  3. The built-in options cannot cover your specific scenario.

For cases involving single registry keys or AND conditions across multiple keys, always prefer Intune's built-in detection rules. Here's why:

  • Single Keys: Intune's built-in registry check is straightforward and reliable.
  • AND Conditions: Intune's built-in detection supports multiple checks that must all be true, making it perfect for this scenario.

Now that we've established when custom scripts are necessary, let's explore their implementation.

Explanation / example EXE with exact version

The recognition rules are all structured in such a way that the criteria are defined first:

$ProgramPath = "C:\Program Files\XXXXX\XXXXXX.exe"
$ProgramVersion_target = '1.0.2' 
$ProgramVersion_current = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($ProgramPath).FileVersion

The definitions are then compared or checked and if they apply, "Found it!" issued. This signals Intune that the package is installed successfully. Alternatively, you can end the script with 'exit 0'.

if($ProgramVersion_current -eq $ProgramVersion_target){
    Write-Host "Found it!"
}

Using Registry Keys in Custom Detection Scripts

Single Registry Key Detection

For detecting a single registry key, use Intune's built-in functionality whenever possible. However, if you need a custom script (e.g., to combine this with another condition), here's an example:

$RegPath = 'HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{SCLOUD00-3E57-3F0B-9332-48A0A5671812}'
$Version = '2022,01,19'

$RegContent = Get-ItemProperty -Path $RegPath
if($RegContent.Version -eq $Version){
  Write-Host "Found it!"
}

Multiple Registry Keys with OR Logic

When you need to check if any one of several registry keys exists and matches the criteria, a custom script is necessary. Here's how to implement this:

# Array of registry paths and expected versions
$RegistryChecks = @(
    @{ Path = 'HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{SCLOUD00-3E57-3F0B-9332-48A0A5671812}'; Version = '2022,01,19' },
    @{ Path = 'HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{SCLOUD00-3E57-3F0B-9332-48A0A5671813}'; Version = '2023,05,01' }
)

# Variable to track if any key matches
$MatchFound = $false

foreach ($Check in $RegistryChecks) {
    try {
        $RegContent = Get-ItemProperty -Path $Check.Path -ErrorAction Stop
        if ($RegContent.Version -eq $Check.Version) {
            Write-Host "Found it at $($Check.Path) with version $($Check.Version)!"
            $MatchFound = $true
            break
        }
    } catch {
        Write-Host "Registry key not found or inaccessible: $($Check.Path)"
    }
}

if ($MatchFound) {
    Write-Host "Found it!"
    exit 0
} else {
    Write-Host "No matching registry key found."
    exit 1
}

This script ensures the detection succeeds if at least one registry key matches, which cannot be handled by Intune's built-in rules.

Multiple Registry Keys with AND Logic

For scenarios where all keys must match, Intune's built-in detection options are the better choice. You can define multiple registry key checks within the Intune console, each of which must pass for the detection to succeed.

However, if you combine these with other logic or non-registry-based conditions, you might need a script like this:

# Array of registry paths and expected versions
$RegistryChecks = @(
    @{ Path = 'HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{SCLOUD00-3E57-3F0B-9332-48A0A5671812}'; Version = '2022,01,19' },
    @{ Path = 'HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{SCLOUD00-3E57-3F0B-9332-48A0A5671813}'; Version = '2023,05,01' }
)

# Variable to track overall match
$AllMatched = $true

foreach ($Check in $RegistryChecks) {
    try {
        $RegContent = Get-ItemProperty -Path $Check.Path -ErrorAction Stop
        if ($RegContent.Version -ne $Check.Version) {
            Write-Host "Version mismatch at $($Check.Path)."
            $AllMatched = $false
            break
        }
    } catch {
        Write-Host "Registry key not found: $($Check.Path)"
        $AllMatched = $false
        break
    }
}

if ($AllMatched) {
    Write-Host "All registry keys match."
    exit 0
} else {
    Write-Host "Not all registry keys match."
    exit 1
}

This script works when additional custom logic is required beyond Intune’s capabilities, but generally, you should avoid using a script for this scenario.


Do you have any other custom detection scripts in Intune that help you in your everyday life or which you are up against?
Let me know in the comments. I would like to add them to my collection.