Can't figure out why complaining about catch block missing
I have this code I'm trying to generate for pulling information out of Intune. It gets most of the way thru but it's complaining with this:
>
At C:\temp\Intune\Get-UnassignediOSDEPDevices.ps1:293 char:14
>+ }
>+ ~
>The Try statement is missing its Catch or Finally block.
>At C:\temp\Intune\Get-UnassignediOSDEPDevices.ps1:294 char:8
>+ }
>+ ~
>Unexpected token '}' in expression or statement.
>At C:\temp\Intune\Get-UnassignediOSDEPDevices.ps1:295 char:3
>+ }
>+ ~
>Unexpected token '}' in expression or statement.
>+ CategoryInfo : ParserError: (:) [], ParseException
>+ FullyQualifiedErrorId : MissingCatchOrFinally
I went thru and lined up all the brackets and seems like it's correct but haven't been able to nail it down. Anyone else seeing what's going on?
<#
.SYNOPSIS
Lists all unassigned devices from Apple Device Enrollment Program (DEP) tokens in Microsoft Intune
.DESCRIPTION
This script connects to the Microsoft Graph API and retrieves all imported Apple device identities
from enrolled DEP tokens, then filters for devices that have not been assigned a user yet.
.PARAMETER ShowAllTokens
Display devices from all DEP tokens even if only one exists
.EXAMPLE
.\Get-UnassignediOSDEPDevices.ps1
Lists all unassigned iOS DEP devices across all enrollment program tokens
.EXAMPLE
.\Get-UnassignediOSDEPDevices.ps1 -ShowAllTokens
Shows devices with additional token information
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[switch]$ShowAllTokens,
[Parameter(Mandatory = $false)]
[string]$ExportPath
)
# ============================================================================
# MODULE CHECK AND IMPORT
# ============================================================================
Write-Host "\n========================================" -ForegroundColor Cyan`
Write-Host " iOS DEP Unassigned Devices Report" -ForegroundColor Cyan
Write-Host "========================================\n" -ForegroundColor Cyan`
$RequiredModules = @("Microsoft.Graph.Authentication", "Microsoft.Graph.Intune")
foreach ($Module in $RequiredModules)
{
if (-not (Get-Module -ListAvailable -Name $Module))
{
Write-Warning "Module '$Module' not found. Installing..."
Install-Module -Name $Module -Force -Scope CurrentUser -AllowClobber -ErrorAction SilentlyContinue
}
Import-Module -Name $Module -Force -ErrorAction Stop
}
# ============================================================================
# AUTHENTICATION
# ============================================================================
Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Yellow
try
{
Connect-MgGraph -Scopes @("DeviceManagementServiceConfig.Read.All",
"DeviceManagementManagedDevices.Read.All") -NoWelcome -ErrorAction Stop
}
catch
{
Write-Error "Failed to connect to Microsoft Graph: $_"
exit 1
}
# ============================================================================
# HELPER FUNCTIONS
# ============================================================================
function Get-MgGraphAllPages
{
param(
[Parameter(Mandatory = $true)]
[string]$Uri,
[int]$DelayMs = 50
)
$AllResults = @()
$NextLink = $Uri
do
{
try
{
if ($null -ne $NextLink)
{
Start-Sleep -Milliseconds $DelayMs
}
$Response = Invoke-MgGraphRequest -Uri $NextLink -Method GET
if ($Response.value)
{
$AllResults += $Response.value
}
else
{
$AllResults += $Response
}
$NextLink = $Response.'@odata.nextLink'
}
catch
{
Write-Warning "Error fetching data from $NextLink : $_"
break
}
}
while ($null -ne $NextLink)
return $AllResults
}
function Get-UnassignedDevicesFromToken
{
param(
[Parameter(Mandatory = $true)]
[string]$TokenId,
[Parameter(Mandatory = $true)]
[string]$TokenName,
[Parameter(Mandatory = $false)]
[string]$ExpirationDate
)
try
{
Write-Host " Retrieving devices from token: $TokenName..." -ForegroundColor Gray
# Get imported Apple device identities for this DEP token
$Uri = "https://graph.microsoft.com/beta/deviceManagement/depOnboardingSettings/$($TokenId)/importedAppleDeviceIdentities"
$Devices = Get-MgGraphAllPages -Uri $Uri
Write-Host " Found $($Devices.Count) devices in this token..." -ForegroundColor Gray
# Filter for unassigned devices (no userPrincipalName assigned)
$UnassignedDevices = @()
foreach ($Device in $Devices)
{
# A device is considered unassigned if it has no userPrincipalName or addressableUserName
$IsAssigned = $false
if ([string]::IsNullOrEmpty($Device.userPrincipalName))
{
$IsAssigned = $false
}
elseif ([string]::IsNullOrEmpty($Device.addressableUserName))
{
$IsAssigned = $false
}
else
{
# Check if the user is assigned but not yet enrolled
$IsAssigned = $true
}
if (-not $IsAssigned)
{
$UnassignedDevices += [PSCustomObject]@{
TokenName = $TokenName
DeviceId = $Device.id
SerialNumber = $Device.serialNumber
Model = $Device.model
Manufacturer = $Device.manufacturer
EnrollmentState = $Device.enrollmentState
UserPrincipalName = if ([string]::IsNullOrEmpty($Device.userPrincipalName)) { "<Unassigned>" } else { $Device.userPrincipalName }
AddressableUserName = if ([string]::IsNullOrEmpty($Device.addressableUserName)) { "<Not Set>" } else { $Device.addressableUserName }
CreatedDateTime = $Device.createdDateTime
LastContactedDate = $Device.lastContactedDateTime
}
}
}
return $UnassignedDevices
}
catch
{
Write-Warning "Error retrieving devices from token '$TokenName': $_"
return @()
}
}
# ============================================================================
# MAIN SCRIPT LOGIC
# ============================================================================
try
{
# Step 1: Get all DEP tokens (Enrollment Program Tokens)
Write-Host "\n[Step 1] Retrieving Enrollment Program Tokens..." -ForegroundColor Yellow`
$DepTokensUri = "https://graph.microsoft.com/beta/deviceManagement/depOnboardingSettings"
$AllTokens = Get-MgGraphAllPages -Uri $DepTokensUri
if ($AllTokens.Count -eq 0)
{
Write-Host "\n[!] No Enrollment Program Tokens found in this tenant." -ForegroundColor Red`
exit 1
}
Write-Host " Found $($AllTokens.Count) DEP token(s)" -ForegroundColor Green
# Step 2: Get all enrolled iOS devices from Intune for comparison
Write-Host "\n[Step 2] Retrieving managed iOS devices..." -ForegroundColor Yellow`
$ManagedDevicesUri = "https://graph.microsoft.com/beta/deviceManagement/managedDevices?\$filter=operatingSystem eq 'iOS'"`
$EnrolledDevices = Get-MgGraphAllPages -Uri $ManagedDevicesUri
Write-Host " Found $($EnrolledDevices.Count) managed iOS devices" -ForegroundColor Green
# Step 3: Build comparison dictionary for already enrolled devices
$EnrolledSerialNumbers = @{}
foreach ($Device in $EnrolledDevices)
{
if ([string]::IsNullOrEmpty($Device.serialNumber))
{
continue
}
$EnrolledSerialNumbers[$Device.serialNumber] = $true
}
# Step 4: Get unassigned devices from each token
Write-Host "\n[Step 3] Finding unassigned devices..." -ForegroundColor Yellow`
$AllUnassignedDevices = @()
foreach ($Token in $AllTokens)
{
`$DeviceList = Get-UnassignedDevicesFromToken ``
`-TokenId $Token.id ``
`-TokenName $Token.tokenName ``
-ExpirationDate $Token.tokenExpirationDateTime
# Filter out devices that are already enrolled (in managedDevices)
$FilteredDevices = @()
foreach ($Device in $DeviceList)
{
if (-not $EnrolledSerialNumbers.ContainsKey($Device.SerialNumber))
{
$FilteredDevices += $Device
}
}
$AllUnassignedDevices += $FilteredDevices
Write-Host " Token '$($Token.tokenName)': $($DeviceList.Count) unassigned devices" -ForegroundColor Gray
}
# Step 5: Display results summary
Write-Host "\n[Step 4] Results Summary..." -ForegroundColor Yellow`
if ($AllUnassignedDevices.Count -eq 0)
{
Write-Host "\n[✓] All DEP devices have been assigned a user!" -ForegroundColor Green`
}
else
{
# Group by token for summary display
$TokenSummary = $AllUnassignedDevices | Group-Object TokenName
Write-Host "Total unassigned devices: $($AllUnassignedDevices.Count)" -ForegroundColor Red
Write-Host "\nBreakdown by Enrollment Program Token:" -ForegroundColor Yellow`
foreach ($Group in $TokenSummary)
{
Write-Host " - $($Group.Name): $($Group.Count) unassigned devices" -ForegroundColor Cyan
}
# Display detailed list of unassigned devices
Write-Host "\n========================================`n" -ForegroundColor Cyan`
`$AllUnassignedDevices | Sort-Object TokenName, SerialNumber | Format-Table ``
`-AutoSize ``
-Property @(
@{Label="Token";Expression={$_.TokenName}},
@{Label="Serial Number";Expression={$_.SerialNumber}},
@{Label="Model";Expression={$_.Model}},
@{Label="Manufacturer";Expression={$_.Manufacturer}},
@{Label="Enrollment State";Expression={$_.EnrollmentState}},
@{Label="User Assigned";Expression={$_.UserPrincipalName}}
)
Write-Host "\n========================================`n" -ForegroundColor Cyan`
# Export to CSV if path specified
if ($ExportPath)
{
try
{
$AllUnassignedDevices | Export-Csv -Path $ExportPath -NoTypeInformation -Encoding UTF8
Write-Host "[✓] Results exported to: $ExportPath" -ForegroundColor Green
}
catch
{
Write-Warning "Failed to export to CSV: $_"
}
}
}
}
catch
{
Write-Error "\nScript failed: $($_.Exception.Message)"`
exit 1
}
finally
{
# Disconnect from Microsoft Graph
try
{
### Disconnect-MgGraph -ErrorAction SilentlyContinue | Out-Null
Write-Host "\nDisconnected from Microsoft Graph" -ForegroundColor Gray`
}
catch
{
}
}
Write-Host "\nScript completed successfully!" -ForegroundColor Green`
Note so in theory it's upset about one of the squiggly brackets between
Write-Warning "Failed to export to CSV: $_"
statement and the Catch statement.
Just everything seems matched up right.