Skip to content
February 27, 2026 Mid-Level (3-5 years) Script Drop

PowerShell Win32 App Installer Scripts

Essential PowerShell scripts for installing and managing Win32 apps in Intune. Automate your app deployment workflow.

PowerShell Win32 App Installer Scripts

Deploying Win32 apps in Intune is powerful but can be tricky. These scripts will help you package, install, and troubleshoot Win32 applications like a pro.

Script 1: Silent Install Wrapper

Every Win32 app needs a silent install. This wrapper handles the most common scenarios:

<#
.SYNOPSIS
    Universal silent installer wrapper for Win32 apps
    
.PARAMETER InstallerPath
    Full path to the installer file
    
.PARAMETER Arguments
    Silent install arguments
    
.PARAMETER ExpectedExitCode
    Expected exit code on success (default: 0)
#>
param(
    [Parameter(Mandatory=$true)]
    [string]$InstallerPath,
    
    [Parameter(Mandatory=$false)]
    [string]$Arguments = "/S",
    
    [Parameter(Mandatory=$false)]
    [int]$ExpectedExitCode = 0
)

$ErrorActionPreference = "Stop"
$LogFile = "$env:TEMP\Win32Install_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"

function Write-Log {
    param([string]$Message)
    $Timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
    $LogMessage = "[$Timestamp] $Message"
    Write-Host $LogMessage
    Add-Content -Path $LogFile -Value $LogMessage
}

Write-Log "Starting installation: $InstallerPath"
Write-Log "Arguments: $Arguments"

try {
    $Process = Start-Process -FilePath $InstallerPath -ArgumentList $Arguments -Wait -PassThru -NoNewWindow
    
    if ($Process.ExitCode -eq $ExpectedExitCode) {
        Write-Log "SUCCESS: Installation completed with exit code $($Process.ExitCode)"
        exit 0
    } else {
        Write-Log "WARNING: Installation completed with unexpected exit code $($Process.ExitCode)"
        exit $Process.ExitCode
    }
}
catch {
    Write-Log "ERROR: $($_.Exception.Message)"
    exit 1
}

Usage:

.\Install-App.ps1 -InstallerPath "C:\Apps\7zip\7zip-x64.msi" -Arguments "/quiet /norestart"

Script 2: Detection Rule Generator

Create detection rules for your Win32 apps automatically:

<#
.SYNOPSIS
    Generate Intune detection rules for Win32 apps
#>

param(
    [Parameter(Mandatory=$true)]
    [string]$AppName,
    
    [Parameter(Mandatory=$false)]
    [ValidateSet("File", "Registry", "MSI")]
    [string]$DetectionType = "File",
    
    [Parameter(Mandatory=$true)]
    [string]$DetectionPath,
    
    [Parameter(Mandatory=$false)]
    [string]$DetectionVersion
)

$Rule = @{
    "@odata.type" = "#microsoft.graph.win32LobAppDetectionRule"
    ruleType = switch ($DetectionType) {
        "File" { "file" }
        "Registry" { "registry" }
        "MSI" { "productVersion" }
    }
    path = $DetectionPath
    fileOrFolderName = Split-Path $DetectionPath -Leaf
}

if ($DetectionVersion) {
    $Rule["version"] = $DetectionVersion
    $Rule["operator"] = "greaterThanOrEqual"
}

$DetectionRule = @{
    rules = @($Rule)
} | ConvertTo-Json -Depth 5

Write-Output $DetectionRule

# Save to file for Intune Win32 import
$DetectionRule | Out-File -FilePath ".\$AppName-detection-rule.json"
Write-Host "Detection rule saved to .\$AppName-detection-rule.json"

Script 3: Pre-Install System Check

Check prerequisites before installing:

<#
.SYNOPSIS
    Pre-installation system checks for Win32 apps
#>

$ErrorActionPreference = "Continue"

Write-Host "=== System Prerequisites Check ===" -ForegroundColor Cyan

$Checks = @{
    "Disk Space (C:)" = {
        $Drive = Get-PSDrive -Name C
        [math]::Round($Drive.Free / 1GB, 2)
    }
    "OS Version" = {
        (Get-CimInstance Win32_OperatingSystem).Caption
    }
    "Architecture" = {
        $env:PROCESSOR_ARCHITECTURE
    }
    "Intune Agent Version" = {
        (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\IntuneAgent" -ErrorAction SilentlyContinue).Version
    }
    "PowerShell Version" = {
        $PSVersionTable.PSVersion.ToString()
    }
    "Free RAM (GB)" = {
        [math]::Round((Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory / 1MB, 2)
    }
}

$AllPassed = $true

foreach ($Check in $Checks.GetEnumerator()) {
    $Result = & $Check.Value
    $Status = if ($Result) { "✓ PASS" } else { "✗ FAIL" }
    $Color = if ($Result) { "Green" } else { "Red" }
    
    Write-Host "$($Check.Key): $Result - $Status" -ForegroundColor $Color
    
    if (-not $Result -and $Check.Key -ne "Free RAM (GB)") {
        $AllPassed = $false
    }
}

if ($AllPassed) {
    Write-Host "`nAll checks passed!" -ForegroundColor Green
    exit 0
} else {
    Write-Host "`nSome checks failed!" -ForegroundColor Red
    exit 1
}

Script 4: Uninstall Legacy App

Clean up old versions before installing new:

<#
.SYNOPSIS
    Uninstall existing versions of an application
#>
param(
    [Parameter(Mandatory=$true)]
    [string]$AppName,
    
    [Parameter(Mandatory=$false)]
    [string[]]$UninstallStrings
)

$ErrorActionPreference = "Continue"

Write-Host "Searching for existing $AppName installations..." -ForegroundColor Yellow

$InstalledApps = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*,
    HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* -ErrorAction SilentlyContinue

$FoundApps = $InstalledApps | Where-Object { $_.DisplayName -like "*$AppName*" }

if ($FoundApps) {
    foreach ($App in $FoundApps) {
        Write-Host "Found: $($App.DisplayName) - $($App.Version)"
        
        if ($App.UninstallString) {
            Write-Host "Uninstalling..."
            
            $UninstallString = $App.UninstallString
            
            # Handle different uninstall formats
            if ($UninstallString -match "msiexec") {
                $UninstallString += " /qn /norestart"
            }
            
            Start-Process -FilePath "cmd.exe" -ArgumentList "/c $($UninstallString)" -Wait -NoNewWindow
            Write-Host "Uninstalled successfully"
        }
    }
} else {
    Write-Host "No existing installations found" -ForegroundColor Green
}

Script 5: Post-Install Validation

Verify the app installed correctly:

<#
.SYNOPSIS
    Post-installation validation
#>
param(
    [Parameter(Mandatory=$true)]
    [string]$AppName,
    
    [Parameter(Mandatory=$false)]
    [string[]]$VerificationPaths
)

Write-Host "Validating $AppName installation..." -ForegroundColor Cyan

$ValidationPassed = $true

foreach ($Path in $VerificationPaths) {
    if (Test-Path $Path) {
        Write-Host "✓ Found: $Path" -ForegroundColor Green
    } else {
        Write-Host "✗ Missing: $Path" -ForegroundColor Red
        $ValidationPassed = $false
    }
}

# Check registry
$RegPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\*"
$RegApps = Get-ItemProperty $RegPath -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like "*$AppName*" }

if ($RegApps) {
    Write-Host "✓ Registry entry found" -ForegroundColor Green
} else {
    Write-Host "⚠ No registry entry (may be normal)" -ForegroundColor Yellow
}

if ($ValidationPassed) {
    Write-Host "`n✓ Validation PASSED" -ForegroundColor Green
    exit 0
} else {
    Write-Host "`n✗ Validation FAILED" -ForegroundColor Red
    exit 1
}

Wrap-Up

These scripts cover the full Win32 app lifecycle in Intune. Save them to your toolkit and customize for each app deployment.

Was this helpful?