Last week I wrote about a basic process I have in place to fire off a Slack notification when a Task Sequence completes. As I wrapped up that post, I'd mentioned how it would be feasible to directly fire off the notification via webhook from a Powershell step in the Task Sequence by modifying a few arguments to Invoke-RestMethod
and generating the Slack block bits in Powershell instead of PHP.
I had some time this past week and decided to give it a go. And it was (more or less) as "simple" as I'd expected!
It's Lightweight
The direct method has several fewer moving parts and is still invoked via a Run PowerShell Script
step in the TS. For my own testing purposes, I use the embedded script type:
The Script Itself
The script isn't fundamentally different than the PHP variant TSCompleteNotifier.php
. The most complicated difference is in how the Block structure itself is curated due to how the JSON payload must be provided. This means a combination of Powershell arrays and hashtables, and took the most fiddling of it all to get the proper structure (see the $blockFields
and $attachments
variables below).
$deviceName = hostname
$slackWebhookURL = 'https://hooks.slack.com/you/generated/when/setting/up';
$formattedDateTime = (Get-Date).ToString("MMMM d, h:mm tt")
# Task Sequence Variables
$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
# These variables are globally available
$MACAddress = (Get-NetAdapter | Where-Object Status -eq "Up").MacAddress
$OSInfo = (Get-ComputerInfo | Select-Object OsName, OsVersion)
$OSData = ($OSInfo.OsName -replace "Microsoft ", "") + " (" + $OSInfo.OsVersion + ")"
if ($MACAddress.Count -gt 1) {
$MAC = $MACAddress[0]
} else {
$MAC = $MACAddress
}
# These variables are custom and will be empty unless your TS declares/sets them
$InstallType = $tsenv.Value("InstallType")
$OSDOUCN = $tsenv.Value("OSDOUCN")
$FirmwareRev = $tsenv.Value("OSDDeviceFirmwareVersion")
# Variables containing the bits to submit in the Slack webhook
$channel = '#quiet-private-channel-name-goes-here';
$bot_name = 'Device Rebuild Completed';
$icon = ':information_source:';
$message = '';
$blockMessage = ":computer: $deviceName completed task sequence on $formattedDateTime";
# Create the block fields for data points (array of hashtables)
$blockFields = @(
@{
title = 'Rebuild Details:'
value = $blockMessage
short = $false
}
@{
title = 'Installation Details:'
value = ":triangular_flag_on_post: ``$InstallType``
``$OSData``"
short = $true
}
@{
title = 'Device Details:'
value = ":desktop_computer: ``$MAC``
firmware revision ``$FirmwareRev``"
short = $true
}
@{
title = 'AD Organizational Unit:'
value = "``$OSDOUCN``"
short = $false
}
)
# Create the attachments payload
$attachments = @(
@{
fallback = "Device rebuild detected: $deviceName completed task sequence on $formattedDateTime"
pretext = ':information_source: Device Rebuild Completed'
color = '#8c1919'
fields = $blockFields
}
)
# Create the actual webhook data payload
$data = @{
channel = $channel
username = $bot_name
text = $message
icon_emoji = $icon
attachments = $attachments
}
# Convert the payload to JSON (recursively)
$data_string = $data | ConvertTo-Json -Depth 4
# Create Headers
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Content-Type", "application/json")
$headers.Add("Content-Length", $data_string.Length)
# Parameter Hashtable
$Params = @{
Uri = $slackWebhookURL
Method = "Post"
Headers = $headers
Body = $data_string
}
# Submit!
$response = Invoke-RestMethod @Params
$response | ConvertTo-Json
An interesting side note about this script is that I needed to provide the -Depth
argument for ConvertTo-Json
in creating the $data_string
declaration, otherwise the output JSON wouldn't be properly formatted. This was a bit surprising to me coming from PHP land where json_encode
handles it all automatically, but wasn't terribly surprising given the complex Block structure (and thus array/hashtable bits).
The Result
It works great directly from Powershell!
The Repo
I have updated the starter repo with additional documentation and the "Direct" script that can be used in lieu of the multi-step process. Hopefully this combination of posts and some starter code is helpful/useful for your own case! Good luck!