Troubleshooting and Upgrading AD FS Farms

, ,

Troubleshooting and Upgrading an AD FS farms is usually a straightforward and easy task. There are many blogs detailing the process from Server 2012R2 to Server 2016/2019. Here are the general steps for upgrading a farm.

  1. Setup up a new server and install the AD FS role.
  2. Add the server to the existing farm.
  3. Set the new server as the primary server.
  4. Point the other servers to the new primary server.
  5. Install additional servers to the AD FS farm.
  6. Uninstall AD FS on the old servers to remove them from the farm.

What are your options when this process doesn’t work? In my case, I could not add a new server to the farm. PowerShell and the GUI both returned errors when attempting to add a new Windows Server 2019 to the farm. I started looking at troubleshooting options and eventually decided to proceed with an attempt to in-place upgrade the Server 2012R2 farm to Server 2019.


Microsoft provides some powerful tools for troubleshooting AD FS issues. AD FS Help provides several troubleshooting guides and diagnostic tools that can help resolve issues with your AD FS farm. The tools are located here:

The AD FS Diagnostic Analyzer tool can provide a health check for you AD FS farm. To use the AD FS Diagnostic Analyzer, you need to install the AD FS Toolbox PowerShell Module.

Install-Module -Name ADFSToolbox -Force

Import-Module ADFSToolbox -Force

Once the AD FS Toolbox is installed, run the Export-AdfsDiagnosticsFile command which will generate a JSON file for upload. The command will run against the local AD FS server unless the farm is Windows Server 2016 or higher. You can also list the servers with the -adfsServers parameter. The -adfsServers parameter is required for 2012R2 farms. Upload the JSON file to the site and the site will display the Health Test Results. The site will detail any problems and offer step by step guides or links to documentation to remediate the issues.

Backup and Restore

There is also the AD FS Rapid Restore Tool found here: The tool backs up the following AD FS configuration data:

  • AD FS database
  • Configuration file
  • Automatically generated token signing and decrypting certificates and private keys
  • SSL certificate and any externally enrolled certificates and corresponding private keys
  • The custom authentication providers, attribute stores, and local claims provider trusts that are installed

Unfortunately, the Restore Tool only supports a restore to the same version as the backup. This means that you cannot use this method to restore AD FS to a newer version of AD FS. You could restore the AD FS farm to a new set of servers and attempt to add upgraded servers to the farm as outlined above.

Other Tools

The site provides a number of other tools and support options. There is a full list of AD FS event items for 2012R2/2016/2019 with ID, Name, and Description. Claims X-Ray assists with debugging claims issues in your applications. The AD FS Event Module provides tools to gather and review the events from multiple servers. There are several more tools available as well.

In-Place Upgrade

Even after running the diagnostic tools several times and making the recommended changes, I still was unable to add a new server to the existing farm. The other option is to attempt an in-place upgrade of the servers in the AD FS farm. Technically, this is not supported as upgrading Windows Server with AD FS installed will uninstall the AD FS role. Prior to attempting this method, I made a snapshot (Hyper-V virtual Machines) of the AD FS servers and a backup of the AD FS farm’s current state. I started by upgrading the secondary AD FS server first. If I was unable to add the server back into the farm and promote it to the primary server, then my plan was to use the AD FS Restore Tool and rebuild the farm. These are the steps I took for the in-place upgrade.

  1. Upgrade the secondary AD FS server to Server 2019.
  2. Install the AD FS role.
  3. Add the upgraded server back into the farm.
  4. Set the server as the primary AD FS server in the farm.
  5. Verified that AD FS was still working for our services.
  6. Upgrade the former primary server, reinstall the AD FS role and set it as the primary server.

I also did an in-place upgrade of the Web Application Proxy server and added it to the farm with the Install-WebApplicationProxy cmdlet. The final step is raising the farm functional level with the Invoke-AdfsFarmBehaviorLevelRaise cmdlet. This will enable the new features to Verify the update completed with the Get-AdfsProperties | Select CurrentFarmBehavior cmdlet.

While it is not a supported option, the in-place upgrade of my AD FS farm worked perfectly. Hopefully, it is not an option you will need.

read more Troubleshooting and Upgrading AD FS Farms

How to – IPU Collections

, ,

IPU Collections

In this blogpost we will cover some of the logic for how we are handling the IPU Collections. In order to create the “Compat Scan Passed” collection you are not able to use the “Drop down” actions to create this so you might not know how to do it. We are first going to assume that you have already extended client settings to absorb Nomad Cache job.


Compat Scan Passed Collection:

select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,
SMS_R_SYSTEM.Client from SMS_R_System inner join
inner join SMS_ClassicDeploymentAssetDetails on SMS_ClassicDeploymentAssetDetails.DeviceID =
SMS_R_System.ResourceId    where SMS_G_System_OPERATING_SYSTEM.Version = “10.0.10586”
and SMS_G_System_OPERATING_SYSTEM.OSLanguage = 1033    and SMS_ClassicDeploymentAssetDetails.PackageID = ‘XXXXXXXX’
and SMS_ClassicDeploymentAssetDetails.StatusDescription = “-1047526896”

IPU Collections

NOTES: This collection will produce a syntax error but trust me it works! My where statements basically OS = Win10 v1511, the language is English (1033), fill in your own PackgeID, and the exit code is compat scan pass!. You can use this format in your environment if needed.


Nomad Cached Content Collection:

select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,

SMS_R_SYSTEM.Client from SMS_R_System   inner join SMS_G_System_COMPUTER_SYSTEM on SMS_G_System_COMPUTER_SYSTEM.ResourceID = SMS_R_System.ResourceId
where SMS_G_System_COMPUTER_SYSTEM.Model = “Latitude 5289”
and SMS_R_System.ResourceId in (select SMS_R_System.ResourceId from  SMS_R_System inner join SMS_G_System_1E_NomadPackages_1_0 on SMS_G_System_1E_NomadPackages_1_0.ResourceId = SMS_R_System.ResourceId where SMS_G_System_1E_NomadPackages_1_0.PackageID = “XXXXXXXX” and SMS_G_System_1E_NomadPackages_1_0.OptInfo = “Completed”)
and SMS_R_System.ResourceId in (select SMS_R_System.ResourceId from  SMS_R_System inner join SMS_G_System_1E_NomadPackages_1_0 on SMS_G_System_1E_NomadPackages_1_0.ResourceId = SMS_R_System.ResourceId where SMS_G_System_1E_NomadPackages_1_0.PackageID = “XXXXXXXX” and SMS_G_System_1E_NomadPackages_1_0.OptInfo = “Completed”)

NOTE: Also for this collection add any item that you have pre-cached by modifying the where statement. In my example I have a specified model + only 2 packages that are pre-cached. In my production collections I have 19 packages I need pre-cached so it’s just easy to show you a few items.


SQL Track Individual System For Required Cached Content For IPU:


sys.Name0 as ‘Computer Name’


,sys.User_Name0 as ‘Last User’

,U.mail0 as ‘Email’

,CS.Manufacturer0 as ‘Manufacturer’

,CS.Model0 as ‘Model’

,OS.Caption0 as ‘Operating System’


, case


WHEN ‘10586’ THEN ‘Win10 v1511’

WHEN ‘14393’ THEN ‘Win10 v1607’

WHEN ‘15063’ THEN ‘Win10 v1703’

END AS [OS Version]

,PR.AddressWidth0 as ‘OS Architecture’









FROM v_R_System sys

Full Outer join v_FullCollectionMembership FM ON FM.ResourceID = sys.ResourceID

Full Outer join v_GS_PC_BIOS BIOS ON BIOS.ResourceID = sys.ResourceID

Full Outer join v_GS_COMPUTER_SYSTEM CS ON CS.ResourceID = sys.ResourceID

Full Outer join v_GS_WORKSTATION_STATUS WKS ON WKS.ResourceID = sys.ResourceID

Full Outer join v_GS_OPERATING_SYSTEM OS on OS.ResourceID = sys.ResourceID

Full Outer join v_GS_PROCESSOR PR on PR.ResourceID = sys.ResourceID

Full Outer JOIN v_R_User u on u.User_Name0 = sys.User_Name0

Full Outer join v_GS_SYSTEM_ENCLOSURE se on se.ResourceID=sys.ResourceID

Full Outer join _E_NomadPackages_DATA nm on nm.MachineID=sys.ResourceID

Full Outer join v_Package PKG on pkg.PackageID = nm.PackageID00

WHERE sys.name0 = ‘HOSTNAME’

and nm.packageID00 in (‘XXX00B8A’,‘XXX00B81’,‘XXX00AB3’,‘XXX00AB2’,‘XXX00AB6’,‘XXX00AD7’)


NOTE: Make sure to modify your where statement with all the possible packages a system in your IPU Collections will need. For my production environment once A system registers saying it has 19 packages then I know It is ready to be upgraded. I also reccoment adding a little section where it says what each package iD is I have that in my query but is not posted here.


note: If WordPress reformats the queries let me know so I can work on getting that fixed! I may update this blogpost to include more screenshots if anybody has any problems.

ALSO CHECK: How To – In Place Upgrade

Importing drivers into SCCM in bulk

, , , , , ,

Importing SCCM drivers in bulk

This is taken from my TechNet gallery here:

When you’re tasked with something like a Windows 10 upgrade, you’ll find yourself spending lots of time downloading and importing SCCM drivers.  While this script won’t go out and download them for you (like the Dell and HP Driver Import tools I’ve seen out there), it manufacturer, model, and architecture agnostic, you don’t get caught up trying to negotiate your way past your firewall and proxy teams, and it runs in a bit under 50 lines of code (including comments). Rather than pasting in the entire thing, I’ll do a screenshot and walk through from there.

sccm drivers

For this script to work, there’s some groundwork required on your part. When you download the drivers, they need to be downloaded into a folder that has whatever name you want for your driver package later.  If you’re like me, you’re already doing this as you download. If I need drivers for an HP Z230 desktop, the folder they’re saved in is already called “HP Z230 Windows 10 x64” or something similar so I can find them later.  The way this script works, whatever your folders’ names are is what names your driver packages will end up with.
Aside from that, all you need to do is plug in the path to the file share that has all your make/model folders in the root, as well as the location where you want to store your driver packages.
Something you will notice in this script is that I bounce between my C: drive and my SCCM drive. This is because UNC paths don’t always work as expected when you’re on the SCCM drive, and SCCM cmdlets don’t play nice running from anything other than the SCCM drive.  To guarantee they both work when needed, I just switch between locations, and it’s no big deal.
This script can take a little while to run, but it will give you feedback as it goes, and it doesn’t lock you out of the SCCM GUI while it runs.