Expert Level Integration of ThinInstaller with SCCM

Identifying Missing or Down-level Drivers and Hardware Applications on Think Products with ThinInstaller

This post is mainly for anyone using Update Retriever/ThinInstaller in their environment alongside SCCM (Current Branch).

If you use ThinInstaller to install drivers and hardware apps on your client systems, a recently added action called "SCAN" can be used in the command line when calling ThinInstaller.

An example of its use will look like this:

ThinInstaller.exe /CM -search A -action SCAN -repository \\<RepoShare> -noicon -includerebootpackages 3 -noreboot

What this will do is search your Update Retriever repository and find all applicable content for the system but not install anything.  A second log will be generated when using the SCAN switch titled "Update_ApplicabilityRulesTrace.txt" along with the expected "Update_log_<CurrentTimeStamp>.txt" that gets created any time ThinInstaller is executed.

A quick look inside the Update_ApplicabilityRulesTrace log:

-n1qww08w
   -DetectInstall(True), 
      -_Driver(True), 
         -HardwareID(NE), USB\VID_8087&PID_0A2B
         -Date(NE), 2017-06-21
         -Version(NE), 19.71.0.2^

-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-

-w10ioc1a0_64
   -DetectInstall(False), 
      -_RegistryKeyValue(False), 
         -Key(NE), HKEY_LOCAL_MACHINE\Software\Intel\Online Connect
         -KeyName(NE), Version
         -Version(NE), 1.2.32.0^

-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-

-w10ioc1a0_64
   -Dependencies(True), 
      -And(True), 
         -_OS(True), 
            -OS(False), WIN10
            -OS(False), WIN10.*
            -OS(True), WIN10-ENT
            -OS(True), WIN10-ENT.*
            -OS(False), WIN10-PRO
            -OS(False), WIN10-PRO.*
         -_Bios(True), 
            -Level(True), *
            -Level(False), R0IET*
            -Level(True), N1WET*
            -Level(False), N1VET*
            -Level(False), N1OET*
            -Level(False), R0HET*
         -_CPUAddressWidth(True), 
            -AddressWidth(True), 64
         -_RegistryKeyValue(True), 
            -Key(NE), HKEY_LOCAL_MACHINE\SOFTWARE\INTEL\SGX_PSW
            -KeyName(NE), Version
            -Version(NE), 1.6^
         -_ExternalDetection(True), mefwdetect.exe /fw 11.0.0.0
         -Or(True), 
            -_PnPID(False), USB\VID_138A&PID_0094
            -_PnPID(False), USB\VID_06CB&PID_0081
            -_PnPID(True), USB\VID_138A&PID_0097
            -_PnPID(False), USB\VID_138A&PID_0090

-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-

Highlighted in red is a package ID that was found in the repository, but was not detected as being installed.  You will also see a few lines below that which are the dependencies that are checked to determine applicability.  If you want to check what package that is, you'll have to find it in Update Retriever using the Package ID, which can be time consuming if there are a lot of updates.

So how can the data in this log be returned in an easy to read format while matching the package ID's to its friendly names?

Introduced in SCCM (Current Branch) 1706 is the ability to run PowerShell scripts against Device Collections or individual on-prem managed Windows PCs.

The below PowerShell script can be run against your Think products from the ConfigMgr console:

# Replace <RepoShare> with path where content is stored.
$URrepo = "\\<RepoShare>"

[xml]$URdb = Get-Content -Path $URrepo\database.xml
$Xpath = "/Database//Package"
$Pkgs = $URdb.SelectNodes($Xpath) | Select-Object -Property id,description
$PkgID = $URdb.SelectNodes($Xpath).id
$TI = Join-Path ([System.Environment]::GetFolderPath(ProgramFilesX86)) "ThinInstaller\ThinInstaller.exe"
$SystemVer = ((Get-WmiObject -Class Win32_ComputerSystemProduct | Select-Object -ExpandProperty Version))

# Check if ThinInstaller is installed
if(!(Test-Path $TI)) 
{
    Write-Host "ThinInstaller is not installed on $env:COMPUTERNAME"
    Exit
}

# Keep the 5 most recent logs and discard any older ones.
else{
    Get-ChildItem ${env:ProgramFiles(x86)}\ThinInstaller\Logs | Sort-Object CreationTime -Descending | Select-Object -Skip 5 | Remove-Item -Recurse -Force

# Run ThinInstaller to scan for updates
    Start-Process $TI "/CM -search A -action SCAN -repository $URrepo -noicon -includerebootpackages 3 -noreboot" -Wait
}

# Pull applicable packages from log
$ScanLog = Get-ChildItem -Path ${env:ProgramFiles(x86)}\ThinInstaller\Logs | Where-Object {$_.Name -eq "Update_ApplicabilityRulesTrace.txt"}

Write-Host "Here are the packages that are applicable for this $SystemVer - $env:COMPUTERNAME"

$ScanLogPkgs = $ScanLog | Get-Content | Select-String -SimpleMatch "DetectInstall(False)" -Context 1,0
$MissingPkgs = ForEach($ScanLogPkg in $ScanLogPkgs) {
    if($ScanLogPkg -like ">*") { continue }
        $ScanLogPkg.ToString().substring($ScanLogPkg.ToString().IndexOf('-')+1,$ScanLogPkg.ToString().IndexOf('>')-4)
}

foreach($Pkg in $Pkgs) {
    foreach($MissingPkg in $MissingPkgs) {
            if($MissingPkg -match $Pkg.id)   {
        $Pkg.id + " - " + $Pkg.description
        }
    }
}


A quick walkthrough of the script:

- Your Update Retriever repository share will be defined and the package ID's and friendly names will be pulled from the database.xml.
- It will check if ThinInstaller is installed on the system.  By default, ThinInstaller is installed to Program Files (x86)\Lenovo\ThinInstaller.  If it's not there, it will exit out.
- If ThinInstaller is present, older logs will be discarded, TI will execute with the SCAN action, and packages that are detected as not installed will be returned, matching the package ID to its friendly name.

The end result will look something like this when complete:







This may not be very appealing to look at but you are given the option to output as a Data Table, which you can then use the "Copy" button and paste the results to Excel, for example.












Further Reading:
http://thinkdeploy.blogspot.com/2016/06/intro-to-update-retriever-and.html 
https://docs.microsoft.com/en-us/sccm/apps/deploy-use/create-deploy-scripts