Roberts Blog

The House of SCCM and Intune on System Center Street

Win7 to Win10 IPU – With ConfigMgr but without Desktop Analytics

With the race on to replace Windows 7 I recently had a request backed out from a customer to implement Desktop Analytics, while still requiring us to move forwards with their Windows 7 to Windows 10 IPU (In-Place Upgrade).

I think most people know that 14th of January 2020, Windows 7 support ended.

Losing Desktop Analytics from the project was a set back, it takes out a lot of leg work for an IPU, the service is used to light-up the upgrade issue areas on your Windows 7 estate and give you an insight in to upgrade readiness, in conjunction with ConfigMgr its a complete boon, bringing that service to bear on several thousand devices would have revealed all of the setup blockers and application incompatibilities that would snag a successful upgrade to Windows 10.

Desktop Analytics is a cloud-based service that integrates with
Configuration Manager. The service provides insight and intelligence for
you to make more informed decisions about the update readiness of your
Windows clients. It combines data from your organization with data
aggregated from millions of devices connected to Microsoft cloud

We still needed insights on upgrade readiness to see what kind of Windows 10 setup blockers are out there, which meant falling back to running Windows 10 setup in Compatibility Scan mode against the targets, and then farming the resulting data for errors and warnings.

In this post I’m going to share a PowerShell script I wrote to ‘bridge’ the gap between this ConfigMgr-based solution, and the analysis of the resulting data set consisting of LOG and XML files.

Before we get underway it is worth noting that once the Windows 10 Setup Compatibility scan has completed, there are a bunch of log and xml files left laying around, and some registry keys created. These files and keys reference what issues were found and the exit code of setup.

The solution linked above sets you up to deploy a task sequence from ConfigMgr which initially references a Package\Program, containing a CMD file, that UNC’s back to an SMB share so as to launch Windows 10 setup in the right mode, and once setup has finished scanning some additional steps are then run to store the resulting log\xml payload on the SMB share for later analysis.

The task sequence could just as easily export the registry keys to the SMB share for you, and the PowerShell script I wrote could be adjusted to parse those. We’ll go with the log and xml files and do something with them using SETUPDIAG. As an aside you could also collect those registry keys by extending your Hardware Inventory out which is yet another route you can take to arrive in Rome.

I created an SMB share called RetroAnalytics, created a folder called Media in there to store the Windows 10 setup media, which is referenced in the Package\Program’s CMD script, also created another folder to receive the data from setup called Logs, another for SetupDiag, and finally another to contain the results from SetupDiag aptly named as Results.

Take heed that when you create the CMD script for the Package\Program you should make sure that the path in the SMB share points to where you’ve stored the Windows 10 setup media, in this case \\Server\RetroAnalytics\Media and call it from there.

When it comes to monitoring and initial harvesting of results from your IPU compatibility scan only task sequence deployment, you can immediately turn to deployment monitoring in ConfigMgr and monitor the task sequence’s deployment, which will represent the error codes returned by Windows 10 setup after its done a compatibility scan on each target device.

This will in a sense give you an immediate green and red light view on the upgrade readiness of the estate.

Where Windows 10 has found a problem you’ll get an exit code to troubleshoot with, however we can dig in and find out more information about the blocker by analysing the setup log and xml files that are copied to the SMB share.

The first part of the solution is documented over here, which entails setting up a share to host the full Windows 10 media, which will then be referenced from a ConfigMgr Package’s CMD script tucked into a task sequence, which should look like this:

* Note that I added an extra step to the TS to create a completion flag file in the machine folder, on the SMB share once the file copies are completed, this stops the PowerShell script from processing machine folders that are still being written too. You really should do this as well

The target devices will run the task sequence which will then run windows 10 setup over-the-wire, no caching, nothing stored in ConfigMgr’s SIS. This will mean that circa 360MB will traverse the network from the SMB share to each target device.

If you have low-bandwidth network links here and there, you can put some thought into how to overcome possible congestion with a localised SMB share or something.

Once you’ve got the above solution in place, and its returning data back to the SMB share, you can do something with it. I have a simple PowerShell script to do just that.

Parsing the log and xml files for each machine is a chore, best carried out using Windows 10 SetupDiag.

Using SetupDiag we can distil a single log file for each file-set, and the resulting log file can easily be parsed for errors and warnings.

Windows 10 setup compatibility scan results:

Results from SetupDiag:

And here’s a snippet from the SetupDiag log:

So in summary to get some valuable information back from all this data, all we have to do is implement the ConfigMgr the solution shown here, make a slight modification to it (Complete.flag and the UNC path set correctly), deploy that out to the target machines, then with the results on the SMB share literally loop around the data in every machine folder and call SetupDiag, finally, process the setup log file and print out the results to a CSV file. Not that difficult at all!

We can then bring the CSV file into Excel later on, pretty it up, then mine it for valuable information on upgrade readiness.

The PowerShell script shown below does just that, it fires off SETUPDIAG then it harvests the data from the resulting log into information which is stored in a CSV file.

The script has to be run on the server hosting the SMB share as it references fixed volumes in the paths, you can tweak this if you want to run it remote from the SMB share.

Before you can run this you’ll need the SetupDiag tool which is linked for download from here, and store it away in the SMBShare\SetupDiag folder.


# Robert Marshall - V1 - 17/12/2019

# Robert Marshall - V2 - 13-01-2020

# Identify undiscovered IPU target devices and process them

# $host.PrivateData.ErrorForegroundColor = 'White'


$MatchFound = $false

# Create CSV if it does not exist

if (!(Test-Path -Path "E:\RetroAnalytics\Results\IPU-Repository.csv" -PathType Leaf)) {

    New-Item "E:\RetroAnalytics\Results\IPU-Repository.csv" -type file > $null

# read CSV hostname column into our array

$hostnameArray = @()

Import-Csv -Path "E:\RetroAnalytics\Results\IPU-Repository.csv" | ForEach-Object {
    # Poke hostname column into the array

    $hostnameArray += $($_.Machine)


gci E:\RetroAnalytics\Logs | select Name | sort Name | ForEach-Object {
    $FolderSourceMachine = $($_.Name)

    $MatchFound = $false                      

    # Check if the folder source machine is in the array

    if ($hostnameArray | where { $_ -eq  $($_.Machine)}) {

        $MatchFound = $true

    if (!$MatchFound) {

        Write-Host "No match found for $FolderSourceMachine, begin processing ..."
        # Check if flag file is present, skip if not

        if (Test-Path -Path "E:\RetroAnalytics\Logs\$FolderSourceMachine\COMPLETE.FLAG" -PathType Leaf)
            Write-Host "COMPLETE flag found, logs are ready, launching SETUPDIAG against this devices logs"

            # Create new directory $FolderSourceMachine

            if (!(Test-Path -Path "E:\RetroAnalytics\Results\$FolderSourceMachine")) {

                New-Item -ItemType directory -Path "E:\RetroAnalytics\Results\$FolderSourceMachine" > $null
            # Launch Windows 10 SetupDiag.exe and analyse the resulting log file, we are going to wait for it to return control back to this script

            Start-Process -Wait -FilePath "E:\RetroAnalytics\SetupDiag\SetupDiag.exe" -ArgumentList "/Output:E:\RetroAnalytics\Results\$FolderSourceMachine\$FolderSourceMachine.log","/LogsPath:E:\RetroAnalytics\Logs\$FolderSourceMachine"

            # Process the resulting log to retrieve the lines containing strings "warnings" and "errors", storing them in an array
            $storageArray = @()

            foreach($line in [System.IO.File]::ReadLines("E:\RetroAnalytics\Results\$FolderSourceMachine\$FolderSourceMachine.log")) {
                if ($line.StartsWith("Warning:"))
                    $storageArray += $line

                if ($line.StartsWith("Error:"))
                    $storageArray += $line
            # Empty the array into the CSV repository
            for ($i=0; $i -lt $storageArray.length; $i++) {

                Add-Content "E:\RetroAnalytics\Results\IPU-Repository.csv" "$FolderSourceMachine,$($storageArray[$i])"

            # Just for neatness add the machine to the in-memory list of devices to keep in sync with whats in the CSV
            $hostnameArray += $FolderSourceMachine            

            Clear-Variable -Name "storageArray"
            Write-Host "Completion flag not present so skipping, cause most likely is that the task sequence is still writing to this log folder for $FolderSourceMachine"

It’s a bit of a clunky-looking solution I must admit, but once you lay all this down and get it working, once things are settle down with the deployment hitting most machines, you can kick-back and open the CSV file (will reside in the Results folder) in Excel to find out what kind of errors and warnings are being reported by the Windows 10 setup compatibility scan.

A poor man’s Desktop Analytics, Retro Analytics.

Buzz me on twitter @RobMVP if you want to talk about this solution further, I assume most are done upgrading from Windows 7 to 10 already 🙂

I’d like to thank Arnab Mitra and team for the source article on Microsoft Docs, which describes the heavy-lifting needed to get ConfigMgr rigged out right.


ConfigMgr Build 1910– Run Command Line–Output to task sequence variable


Intune Standalone – Part 4–Managed BYOD – iOS and Android


  1. X-wing Pilot #5

    That’s very interesting and informative!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Powered by WordPress & Theme by Anders Norén