System Center Configuration Manager OSD for Distributed Environments

My company is highly distributed. We have around 150 Config Manager boundaries assigned to 100+ different Distribution Points with network bandwidth ranging from 3Mb up to 1Gb. Yes, 3Mb, we’ve got some slower sites out there in the globe! Being the Primary OSD guy at my company, this creates a challenge. Let’s say I create a new OS Image the week of patch Tuesday, we test and target all distribution points that Friday. Considering that we have Patch content being distributed, plus now these large WIM files (not to mention anything else that may be distributing, site data, client data, etc…) most-often, we see the following patch Tuesday before we can add the new WIM into our task sequence. We have a CAS and elect to make all our changes then and there for the globe to use; this helps us achieve a consistent deployment process regardless of the geographical location of the site.

Obviously, our problem here is we may see 4-6 weeks before distributing new OS Image files; Considering we support a Windows 7 32/64-bit, Windows 8.1 32/64-bit, and now Windows 10 64-bit, this is a lot of data to push out! The slower cadence of our OS Images the more updates that need to run during the “Install Software Updates” steps. So, whats the solution? I can beg and beg until I retire to get our bandwidth updated but this can be VERY costly depending on the exact location around the world. We could only update our images quarterly, semi-annually, or annually? All this does is allow the updates to stack up during “Install Software Updates” which can cause issues, extend run-time, and in some case create a mess.

But…what if I had a way to make changes to our OSD process (New Image, New Driver Package, etc…) and (dynamically) as this content becomes available that content is used? I call this a “Dynamic Task Sequence” or DTS.

Theory of Operation


The Dynamic Task Sequence (DTS) System implements an additional layer on top of the traditional Operating System Deployment (OSD) Task Sequence. This added layer—Referred to as a Task Sequence Scenario—contains two OSD Task Sequences.

For each OSD Task Sequence Scenario there would be two Task Sequence: one with the latest and greatest updates/changes/modifications (hereby referred to as the “Fast”) and one referencing content that is known to be globally distributed (hereby referred to as the “Slow”). Rather than selecting a Task Sequence to run, a task sequence scenario would be selected (e.g.: Windows 32-bit, Windows 64-bit). This to be done during the Wizard or “Pre-Start” Command.

Upon selecting a scenario, the Fast task sequence would be evaluated to see if the references are available within the client’s ConfigMgr boundary (See my post on Content Location Requests). If all content is available to the client, the Fast Task Sequence would then be run. If any of the referenced content fails to validate, the Slow Task Sequence is run.

This allows updating the Fast task sequence as soon as changes are tested and validated to work. The beauty of this system, is that as content is distributed and arrives to ConfigMgr servers, locations will begin to use the Fast Task Sequence automatically.

Once Fast content is globally distributed, the Slow Task Sequence is updated with that content. The Fast Task Sequence is not used to “test” or “pilot” changes, but to make the latest changes available as soon as possible!

This allows locations to take advantage of changes as soon as the content reaches a client’s local servers rather than waiting for content to be distributed globally.

DTS versus Normal OSD

Normal Task Sequence OSD

In a normal Scenario, we would have one Task Sequence per Build (Example: 32-bit Windows 10 & 64-bit Windows 10). The task sequence consists of all the SCCM Packages that are referenced by the Task Sequence (Applications, Boot Media, OS Image, etc.…). In order for us to update a referenced Package in this Task Sequence, we would need that new package to be distributed to all servers. With highly distributed environments, this causes extended delays when we need to make changes to an OSD Task Sequence.

DTS Task Sequence OSD

Under the DTS system we add the scenario layer. A Scenario is a collection of Two Task Sequences. Rather than selecting a Task Sequence to run, you select the scenario. Similar to traditional OSD, the availability of each Task Sequence reference is performed; however, with DTS, we evaluate the Fast Task Sequence first. If criteria is met, that task sequence is used; if evaluation of the fast task sequence fails, we default to the “Slow”.

Under DTS we do not add a package to the Slow Task Sequence unless it is 100% distributed. This allows us to modify the Fast Task Sequence even before the content is distributed. Since the “Fast” task sequence is evaluated at run-time, as content becomes available to a location, those clients will begin running the “fast” task sequence automatically.

Effects of Missing Content

With Traditional OSD, if I update my Task Sequence with a package that is not completely distributed, those “pending” locations will be unable to run this Task Sequence.

With DTS, I update my Fast Task Sequence before content is completely distributed. At run-time (in WinPE), we validate the reference packages. If we have a failed content location request, we simply default to the “Slow”. No need to evaluate the Slow build as this will be done once we select a Task Sequence. In Theory, this prevents any sort of failed Task Sequence due to missing content (as long as we’re updating our Slow Task Sequence honestly 😉 ).

Maintenance Requirements

Now, this isn’t perfect! There are some additional maintenance items that we’ll need to perform.

  • Double Task Sequences
    • Since selection is based on Scenario, two task sequences will be required per “Scenario”
    • Changes now need to be made twice; once to the fast, then again to the slow when distribution is complete.
  • Additional SQL to Map Scenarios (if using SQL for this)
    • A basic SQL table is required to map a scenario to the respective fast and slow task sequences.
    • Typically, this will only need to be created once, unless a Scenario is added/removed, or a modified Task Sequence Package ID or Task Sequence Advertisement ID.
  • Additional Reporting
    • In order to maintain the “Slow” task sequence, we’ll need a report to give the distribution status of the “Fast” content. Once we see “Fast” content fully distributed, we can safely add this to the “Slow” Task Sequence.

Technical Breakdown


  • SCCM 2012 (or newer) Infrastructure
  • Scenario Mapping (Server running MS SQL [Recommended])
    • New Database or new Table in an existing Database; NOT YOUR SCCM DATABASE!
    • This will be used to handle mapping information from a Scenario to the Fast/Slow Task Sequences
    • Hosted SQL Server MUST have a linked server connection to the SCCM Server
    • This does not have to be on the SCCM Server itself.
  • Boundaries by AD Site (IP/Subnet could be used–I have not tested though)
  • Bootable Media with a Prestart Command

SCCM Infrastructure

For this to work, a SCCM infrastructure running version 2012 RTM or higher is required (Although you should be on the latest service pack of 2012/R2 if not the latest product!)

SCCM’s default configuration will work for this theory. The only specific requirement is that boundaries are defined by AD Site for Content Validation to work properly. You CAN manipulate a content location request using an IP address; but I have not tested this as we use AD Site configurations.

Each Scenario will require 2 Task Sequences: “Fast” and “Slow”

Scenario Mapping

With each “Scenario” you’ll have 2 Task Sequences: “Fast” and “Slow”. You’ll need something to tie a Scenario to each task sequence and each task sequences package ID and Advertisement ID. We chose to use SQL since this is where all our wizard content comes from. If you’re using MDT, you can use that same database (just add a new table). Alternatively, this information can be placed into a XML file and packaged with your pre-start command files. The only down-side to this is that anytime you have an update, you need new boot media (We try to limit our Boot Media Image updates only to hardware [driver] additions).

IMPORTANT: If you elect NOT to use SQL for storing your Scenarios and Scenario Details, you still need some method to query your ConfigMgr Database for Task Sequence References!

We’ll want to create a few tables, views, and stored procedures to make these actions easier for our OSD Wizard. I’ll have 2 tables: One showing the Scenario and Scenario ID (SQL id column), and another table referencing the Scenario table and then containing all the necessary information for our Task Sequence. Having these split up allows us to call unique Scenarios for our wizard. All the rest of the information is addressed and handled in the background hidden from the user.

SQL Table: TaskSequenceScenarios


This table will hold each Scenario. It contains an Identity column and a name column.


id groupName
0 Windows 7 (32-bit)
1 Windows 7 (64-bit)
2 Windows 10 64-bit


SQL Table: TaskSequenceScenarioDetail

This table will store the Task Sequences associated with a Scenario. It has an identity column, a column that links back to the id column of TaskSequenceScenarios, a Task Sequence Package ID, Task Sequence Advertisement ID, Description, Notation of Fast or Slow, Active, Date Added, and Date Removed.


id groupId taskSequencePkgId advertisementId description isFast active dateAdded dateRemoved
1  0  ABC00100  ABC20100  Windows 7 32-bit Fast TS  1  1  2016-03-16 06:54:34.160  NULL
2  0  ABC00101  ABC20101  Windows 7 32-bit Slow TS  0  1  2016-03-16 06:54:34.160  NULL
3  1  ABC00102  ABC20102  Windows 7 64-bit Fast TS  1  1  2016-03-16 06:54:34.160  NULL
4  1  ABC00103  ABC20103  Windows 7 64-bit Slow TS  0  1  2016-03-16 06:54:34.160  NULL
5  2  ABC00104  ABC20104  Windows 10 64-bit Fast TS  1  1  2016-03-16 06:54:34.160  NULL
6  2  ABC00105  ABC20105  Windows 10 64-bit Slow TS  0  1  2016-03-16 06:54:34.160  NULL


SQL Stored Procedure: SP_GetScenarioDetailsByGroup

You’ll want a stored procedure to ask the database for the details of a scenario. This Stored Procedure will obtain the Task Sequences (and their relevant OSD details) assigned to a Scenario. Ideally, your wizard would obtain the Scenario and ID from the TaskSequenceScenarios Table, list the “Name” to select, then use the corresponding ID against this procedure to get the necessary details.

	active = 1 and groupId = @TaskSequenceGroupId

SQL Stored Procedure: sp_GetTaskSequencePackageReferences

This is where the linked server back to your ConfigMgr server is required. This procedure takes the Task Sequence Package ID stored in your TaskSequenceScenarioDetails table and returns all of the referenced packages. We’ll need to get the PackageId and SourceVersion to do a proper content location request (See my post on Content Location Requests).

	(Select distinct ReferencePackageID
		from [ConfigManagerServer].[ConfigMgrDatabase].dbo.v_tasksequencereferencesInfo
		where PackageID = @TaskSequencePackageID
	inner join [ConfigManagerServer].[ConfigMgrDatabase].dbo.v_package P on TSPKG.ReferencePackageID = P.PackageID
order by P.PackageID


I’m going to assume that you’ll update your wizard/pre-start on your own to select the Task Sequence Scenarios for selection. Remember, if showing a selectable Scenario for a build, you’ll want to display the groupName column and preserve the id as the id will be needed to get the details.

At a high level summary, we’ll use our stored procedure (SP_GetScenarioDetailsByGroup) using the id from TaskSequenceScenarios. This will return (most importantly) our Task Sequence Package ID and Advertisement ID.

From here we’ll start with our “Fast” Task Sequence. We’ll need to perform a Content Location Request on each package (If you missed the first few links: See by blog post Configuration Manager: Content Location Requests).

You’ll need to point the Content Location Request to a management point server. You can simply use a hard-coded MP but that’s not very dynamic. You’ll be better off using the Task Sequence Variable “SMSTSLocationMPs” (this is a string of multiple MP’s separated by ‘*’). If you’re using Dynamic boot media, this may contain several servers, so how can you tell which is the correct one? We can do a simple http request to any of those MP’s with our ip address and subnet address to get the appropriate MP for where we’re at:

The function below will do just that! It will return a hashtable of SiteCode, and ManagementPoint from the http command used. If you want, this http command can be used inside any browser if you want to verify.

function Get-SMSMpInformationOSD()
        [string] $ClientIpAddress,
        [string] $ClientSubnetAddress
    $TsEnv = New-Object -Comobject Microsoft.SMS.TSEnvironment
    $ManagementPoints = $TsEnv.Value("SMSTSLocationMPs").Split('*')
    [xml]$locationResponse = $null

    foreach ($mp in $ManagementPoints)
        if (-not (Test-Connection -ComputerName $($mp.TrimStart('http://').TrimStart('https://')) -Count 1 -ErrorAction SilentlyContinue))
        { continue }
        $serverResponse = Invoke-WebRequest -Uri "$mp/sms_mp/.sms_aut?MPLocation&ir=$($ClientIpAddress)&ip=$($ClientSubnetAddress)" -UseBasicParsing
        [xml]$locationResponse = $serverResponse.Content

    if ($locationResponse -eq $null)
        throw "Unable to contact any ($($ManagementPoints.Count)) Management Point Server(s)"

    return @{"SiteCode"=$($locationResponse.MPLocation.Location[0].SiteCode);
            "ManagementPoint"=$($locationResponse.MPLocation.Location[0].MP) }


If you need some assistance getting the Subnet Address, head over to TechNet and pick this one up.

Now that we have our local Management Point and it’s site code, we can begin to do the Content Location Request (You guessed it: See by blog post Configuration Manager: Content Location Requests). Analyze the xml returned and if the request shows at least 1 “Local” location, we can continue. As soon as a content location request fails, you can break out of the loop.

Whether or not the Fast or Slow has all of the references we need a way to set what Task Sequence will be run. If we don’t, we could have a list of Task Sequence to select, and may not know which one to run (And if we have multiple scenarios, each with 2 task sequences, this may be a long list!). The answer comes from the “advertisementId” column in the TaskSeqeunceScenarioDetails SQL Table. Set the Task Sequence Variable “SMSTSPreferredAdvertID” with the Advertisement ID from your SQL Table. If the task sequence finds that advertisement targeted, no more “Select a Task Sequence”; instead you just have a message saying “‘x’ Task Sequence is about to be run”.

Simple right? It’s a bit to grasp and certainly isn’t something that Microsoft will support. If you’re interested in implementing this, as with anything else, test it in a lab over and over. Just when you think it’s working, test it again!



Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s