Connect Your OSD Task Sequence to Microsoft Flow

I recently had a need to trigger a complex set of actions during an operating system deployment and to use data from the task sequence environment in those actions.  I immediately thought to use Microsoft Flow.  Flow lets you construct automated routines across a wide range of connected services and applications.  In this article, I'll show how I managed to send a data payload from an OSD task sequence to Microsoft Flow and use it as a trigger.  Using this basic framework, you can then build out any routine in Flow that you'd like.

Important note: You'll need an Office 365 license to use Flow (and to use many of the connected services).

In order to transmit the data payload, we're going to send an HTTP POST request to the Flow web service.  So, first, we'll configure a new HTTP Request trigger in Flow to receive and process the data.  Then, we'll build a PowerShell script that our task sequence will use to create the HTTP request.

Part 1: Create the HTTP Request Trigger

Open the Flow website and login with your Office 365 account.  Choose My flows in the nav pane and create a new blank Flow.

Create a blank Flow

We're going to use an HTTP Request trigger.  You can find it by searching for "HTTP", and then selecting the "When a HTTP request is received" trigger.

Create a new HTTP Request Trigger

If you don't need to pass any data from your task sequence to the Flow, then your trigger is done.  Just add the action steps that you desire and click Save.  After you save the Flow the first time, the HTTP Request item will be updated automatically with the assigned HTTP POST URL.  

HTTP POST URL Generated

Save this URL for your use later, but store this in a secure location!  There won't be any authentication required to send a POST to this web service.  The unique GUID in the URL should be treated like any other API secret key.

Customize the HTTP Request Trigger

In most cases, you'll want to include a data payload with your HTTP POST so that you can reference that data in your subsequent actions.  To accomplish this, we'll need to send that data formatted as JSON text, which means we need to provide the web service with information about how the JSON payload will be formatted.  If you're not familiar with JSON, go ahead and google it now.  It's very straightforward, and you can easily convert a PowerShell hashtable to JSON with a native cmdlet (as we will do later).

At this point, create an example JSON payload containing an example of the type of data that you expect to send from your script.  For this example, I'll use this:

{
	"ComputerName": "PC-123ABC",
	"ComputerModel": "HP ZBook Studio G4",
	"Status": "Failed"
}

In your Flow, choose to "Use sample payload to generate schema", and then paste in your sample JSON output.  If you provided properly formatted JSON, then you should end up with an auto-generated JSON schema.

Auto-generated JSON Schema

Now, when we create an action, we'll be able to reference these JSON fields as dynamic content.  In this example, I'll use a simple email notification.  Notice that each of the properties defined in the JSON schema is available for reference.

JSON Properties in Dynamic Content

And that's it for the Flow side.  Save your changes and then break out your favorite ISE, because we're ready to build the PowerShell script.

Part 2: Create the PowerShell Script

It's quite easy to create the anonymous HTTP request from PowerShell.  This short script here would be enough to generate a sample HTTP request in order to test our new Flow.

$uri = "[Insert HTTP POST URL here]"

$payload = @{
	computername = "PC-123ABC"
	computermodel = "HP ZBook Studio G4"
	status = "Failed"
}

$json = $payload | ConvertTo-Json

Invoke-WebRequest -UseBasicParsing -Uri $uri `
	-ContentType "application/json" `
	-Method POST `
	-Body $json

The specifics of your script will come down to collecting the data you need for your payload.  For this example, in order to demonstrate a few key concepts, I'll assume that data for the payload is coming from a few different sources.  Here's my example script, which assumes the status will be passed via the command line, the model is obtained from WMI, and the name is retrieved from a task sequence variable.

param (
	[parameter()]
	[ValidateNotNullOrEmpty()]
	[string]$Status
)

# Load Microsoft.SMS.TSEnvironment COM object
try {
    $TSEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment
}
catch [System.Exception] {
    Write-Warning -Message "Unable to construct Microsoft.SMS.TSEnvironment object"
    exit 1
}

# Get computer name from task sequence variable 'OSDComputerName'
$computername = $TSEnv.Value('OSDComputerName')

# Get computer model from WMI
$pcmodel = (Get-WmiObject -Namespace root\cimv2 -Class win32_ComputerSystemProduct).Name

# Create POST
try {
    $uri = "[Insert HTTP POST URL here]"

    $payload = @{
        computername = $computername
        computermodel = $pcmodel
        status = $Status
    }

    $json = $payload | ConvertTo-Json

    $result = Invoke-WebRequest -Uri $uri -UseBasicParsing `
		-ContentType "application/json" `
		-Method POST `
		-Body $json

    # check response
    if ($result.StatusDescription -ine 'Accepted') { exit 2 }
}
catch [System.Exception] {
    Write-Warning -Message "An error occured during POST attempt. Error message: $($_.Exception.Message)"
    exit 2
}

I definitely recommend testing the API request portion of your script outside of the OSD process so that you can troubleshoot it more easily.  Once your script is ready, create a package for it in SCCM.

Part 3: Trigger the Flow From Your Task Sequence

Sending the trigger from your OSD task sequence is very straightforward.  Just use a Run PowerShell Script step, reference your package and script name, and include any parameters that your script needs.

Create the Task Sequence Step

I hope this was helpful. If you have any comments or questions, or if you have an idea about how to further improve this approach, you can connect with me via the comments below or via Twitter.

Show Comments