Skip to content

Instantly share code, notes, and snippets.

@SMSAgentSoftware
Last active July 13, 2023 20:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SMSAgentSoftware/2d1cc4fa9718b1a8d1452b842ef34a7d to your computer and use it in GitHub Desktop.
Save SMSAgentSoftware/2d1cc4fa9718b1a8d1452b842ef34a7d to your computer and use it in GitHub Desktop.
Invokes an Intune remediations script on demand against one or more devices
function Invoke-IntuneRemediationOnDemand {
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true)]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[string[]]
$Computername
)
# Requires the Intune PowerShell SDK (Microsoft.Graph.Intune)
# MS Graph required permissions (delegated):
# DeviceManagementManagedDevices.Read.All
# DeviceManagementConfiguration.Read.All
# DeviceManagementManagedDevices.PrivilegedOperations.All
Begin
{
$script:GraphToken = Connect-MSGraph -PassThru
$ProgressPreference = 'SilentlyContinue'
Function script:Invoke-LocalGraphRequest {
Param ($URL,$Headers,$Method,$Body)
try
{
If ($Method -eq "POST")
{
$WebRequest = Invoke-WebRequest -Uri $URL -Method $Method -Headers $Headers -Body $Body -ContentType "application/json" -UseBasicParsing
}
else
{
$WebRequest = Invoke-WebRequest -Uri $URL -Method $Method -Headers $Headers -UseBasicParsing
}
}
catch
{
$Response = $_
$WebRequest = [PSCustomObject]@{
Message = $response.Exception.Message
StatusCode = $response.Exception.Response.StatusCode
StatusDescription = $response.Exception.Response.StatusDescription
}
}
Return $WebRequest
}
Function Get-IntuneManagedDevices {
param($DeviceName)
$URL = "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices?`$filter=deviceName eq '$DeviceName'"
$headers = @{'Authorization'="Bearer " + $GraphToken}
$GraphRequest = Invoke-LocalGraphRequest -URL $URL -Headers $headers -Method GET
return $GraphRequest
}
Function Get-IntuneDeviceHealthScripts {
param($URL)
If ($null -eq $URL)
{
$URL = "https://graph.microsoft.com/beta/deviceManagement/deviceHealthScripts"
}
$headers = @{'Authorization'="Bearer " + $GraphToken}
$GraphRequest = Invoke-LocalGraphRequest -URL $URL -Headers $headers -Method GET
return $GraphRequest
}
Function Invoke-IntuneOnDemandRemediation {
param($DeviceId,$RemediationId,$DeviceType)
if ($DeviceType -eq "CoManaged")
{
$URL = "https://graph.microsoft.com/beta/deviceManagement/comanagedDevices('$DeviceID')/initiateOnDemandProactiveRemediation"
}
else
{
$URL = "https://graph.microsoft.com/beta/deviceManagement/managedDevices('$DeviceID')/initiateOnDemandProactiveRemediation"
}
$headers = @{'Authorization'="Bearer " + $GraphToken}
$body = @{
"scriptPolicyId"="$RemediationID"
} | ConvertTo-Json
$GraphRequest = Invoke-LocalGraphRequest -URL $URL -Headers $headers -Body $Body -Method POST
return $GraphRequest
}
# Get list of remediations
$result = Get-IntuneDeviceHealthScripts
if ($result.StatusCode -ne 200)
{
Write-Error $result
break
}
# Do paging
$Content = $result.Content | ConvertFrom-Json
$ScriptList = [System.Collections.Generic.List[Object]]::new()
$ScriptList.AddRange($Content.value)
If ($null -ne $Content.'@odata.nextLink')
{
do
{
$result = Get-IntuneDeviceHealthScripts -URL $Content.'@odata.nextLink'
if ($result.StatusCode -ne 200)
{
Write-Error $result
continue
}
$Content = $result.Content | ConvertFrom-Json
$ScriptList.AddRange($Content.value)
}
until ($null -eq $Content.'@odata.nextLink')
}
# Check we have an actual list
$Scripts = $ScriptList | Select -Property displayName,version,description,publisher,id
if ($Scripts.Count -lt 1)
{
Write-Warning "No remediation scripts found"
break
}
# Prompt user to select a script
$script:SelectedScript = $Scripts | Sort -Property displayName | Out-GridView -Title "Select a remediation" -OutputMode Single
if ($null -eq $SelectedScript)
{
Write-Error "No remediation script selected"
break
}
}
Process
{
foreach ($Computer in $Computername)
{
# Find managed device in Graph
$result = Get-IntuneManagedDevices -DeviceName "$Computer"
if ($result.StatusCode -ne 200)
{
Write-Error $result
continue
}
# Make sure only 1 result returned
$Device = $result.Content | ConvertFrom-Json | Select -ExpandProperty value
if ($null -eq $Device)
{
Write-Error "Device not found"
continue
}
if ($Device.Count -gt 1)
{
Write-Error "Multiple devices found with the name '$Computer'. Device names must be unique."
continue
}
# Invoke the remediation
if ($Device.managementAgent -match "configurationManager")
{
$result = Invoke-IntuneOnDemandRemediation -DeviceID $Device.id -RemediationID $SelectedScript.id -DeviceType "CoManaged"
}
else
{
$result = Invoke-IntuneOnDemandRemediation -DeviceID $Device.id -RemediationID $SelectedScript.id
}
If ($result.StatusCode -ne 204)
{
# Try the other managament agent option
if ($Device.managementAgent -match "configurationManager")
{
$result = Invoke-IntuneOnDemandRemediation -DeviceID $Device.id -RemediationID $SelectedScript.id
}
else
{
$result = Invoke-IntuneOnDemandRemediation -DeviceID $Device.id -RemediationID $SelectedScript.id -DeviceType "CoManaged"
}
If ($result.StatusCode -ne 204)
{
Write-Error $result
continue
}
}
}
}
End
{
}
}
# Example usage
Invoke-IntuneRemediationOnDemand -Computername "PC001","PC002"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment