driverharvest.ps1


<#PSScriptInfo
 
.VERSION 5.0
 
.GUID 41277fb1-10a4-4933-9638-9ba6c2a82b29
 
.AUTHOR Kyle Taylor
 
.COMPANYNAME
 
.COPYRIGHT
 
.TAGS
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
#>


<#
 
.DESCRIPTION
 This script was created to harvest drivers to be used for Operating System Deployment. You must execute this script before installing any drivers to get a baseline of drivers already installed on the system. After you've run the script to get the baseline driver list, install all missing drivers. Run this utility again to gather all new drivers. The script will compare the baseline against the second harvest and separate out only the new drivers into a 'New-Drivers' Folder. These are the drivers that will need to be imported into SCCM.
 
#>
 


######################################################################################################
# This script was created to harvest drivers to be used for Operating System Deployment
# You must execute this script before installing any drivers to get a baseline of drivers
# already installed on the system.
#
# After you've run the script to get the baseline driver list, install all missing drivers.
#
# Run this utility again to gather all new drivers. The script will compare the baseline against
# the second harvest and separate out only the new drivers into a "New-Drivers" Folder. These are
# the drivers that will need to be imported into SCCM.
#
# The folder structure is built using the Make and Model pulled directly from registry and can be
# used as the WMI query for SCCM to the apply Drivers steps
#
# The script removes any smart card reader driver from the harvests
#
# The script will also move video drivers into a separate folder. The path is New-Drivers\Make\Video
#
# Script Author: Kyle Taylor
# Date 4/14/2017
# Version 4
#
#
######################################################################################################


#sets the working directory from where the script was launched
$PSScriptRoot

#checks to see if the system is a 64 bit machine. we are not gathering drivers on x86 machines
If ($ENV:PROCESSOR_ARCHITECTURE -ne "amd64"){
    Write-host "This is not an x64 system. The script will not continue."
    write-host ""
    exit
}

#gathers and places the manufacturer, family, and model of the system into variables for the folder creation
$MANUFACTURER=(Get-ItemProperty -Path HKLM:\HARDWARE\DESCRIPTION\SYSTEM\BIOS).SYSTEMMANUFACTURER
$FAMILY= (Get-ItemProperty -Path HKLM:\HARDWARE\DESCRIPTION\SYSTEM\BIOS).SYSTEMFAMILY
$MODEL= (Get-ItemProperty -Path HKLM:\HARDWARE\DESCRIPTION\SYSTEM\BIOS).SYSTEMPRODUCTNAME
$Display = "Video Driver"

If ($MANUFACTURER -eq "Dell Inc."){
    $MANUFACTURER=$MANUFACTURER.substring(0,8)
    }

#variables for the driver output locations
$baselinedrivers = join-path "C:\HarvestDrivers\First-Harvest\" -childpath $MANUFACTURER\$FAMILY\$MODEL
$updateddrivers =  join-path "C:\HarvestDrivers\Second-Harvest\" -childpath $MANUFACTURER\$FAMILY\$MODEL
$newdriverpath =  join-path "C:\HarvestDrivers\New-Drivers\" -childpath $MANUFACTURER\$FAMILY\$MODEL
$displaypath = join-path "C:\HarvestDrivers\New-Drivers\" -childpath $MANUFACTURER\$Display

#checks to see if a driver comparison has already been ran. This is to prevent overwritting a previous comparison
if (test-path $newdriverpath){
    Write-Output "A previous driver comparison has been ran. If you want to run a new comparison, remove the"
    write-host "'C:\Driverharvest' folder to re-run this utility"
    write-host ""
    exit
}

#First driver harvest
If (!(test-path $baselinedrivers)){

    write-host "Running the first driver harvest"
    write-host ""

    Export-WindowsDriver -Online -Destination $baselinedrivers | where {($_.ProviderName -ne "Microsoft") -and ($_.ClassName -ne "SmartCardReader") -and ($_.ClassName -ne "display")}
    
    write-host ""
    write-host ""
    write-host "First driver harvest is complete. Please install missing drivers and re-run this tool for driver comparison"
    exit
}

#second driver harvest and driver comparision
if (test-path $baselinedrivers){

    write-host "Running the second driver harvest and driver comparison"
    write-host ""

    Export-WindowsDriver -Online -Destination $updateddrivers | where {($_.ProviderName -ne "Microsoft") -and ($_.ClassName -ne "SmartCardReader")}
    #Export-WindowsDriver -Online -destination $displaypath| where {($_.ProviderName -ne "Microsoft") -and ($_.ClassName -eq "display")}

    
    #gets the Smart Card Reader .INF Files
    $SCRDriver = get-WindowsDriver -Online | where {($_.ProviderName -ne "Microsoft") -and ($_.ClassName -eq "SmartCardReader")}

    #Checks and removes any Smart Card Reader Drivers from C:\DriverHarvest\New-Drivers\Manufacturer\Family\Model
    foreach ($scrinf in $SCRDriver){
        $SCRINFname = [io.path]::getfilename($srcinf.originalfilename)
        $SCRpath= Get-ChildItem -path $updateddrivers | ?{ $_.PSIsContainer } |select -ExpandProperty name
        foreach ($SCRfolder in $SCRdpath){
        $inf= Get-ChildItem -Path "$updateddrivers\$SRCfolder" |select -ExpandProperty name
            if ($inf -notcontains $SRCINFname){ 
                Remove-Item $updateddrivers\$SRCfolder -force -Recurse
            }
        }
    }
    #gets the video driver .INF Files
    $DisplayDrivers = get-WindowsDriver -Online | where {($_.ProviderName -ne "Microsoft") -and ($_.ClassName -eq "display")}
        
    #checks for and moves any driver video drivers from C:\DriverHarvest\New-Drivers\Manufacturer\Family\Model to C:\DriverHarvest\New-Drivers\Manufacturer\video folder
    foreach ($DisplayDriver in $DisplayDrivers){
        $Displayinf = [io.path]::getfilename($DisplayDriver.originalfilename)
        $Vidpath1 =Get-ChildItem -path $updateddrivers | ?{ $_.PSIsContainer } |select -ExpandProperty name
            foreach ($vidfolder in $vidpath1){
                $inf= Get-ChildItem -Path "$updateddrivers\$vidfolder" |select -ExpandProperty name
                if ($inf -contains $Displayinf){
                    Copy-Item $updateddrivers\$vidfolder $displaypath\$vidfolder -Force -Recurse
                    Remove-Item $updateddrivers\$vidfolder -force -Recurse
            }
        }
    }

    #gets the driver folders from the driver output locations for the 1st and 2nd harvest
    $baseline=Get-ChildItem -path $baselinedrivers | ?{ $_.PSIsContainer } |select name
    $updated=Get-ChildItem -path $updateddrivers | ?{ $_.PSIsContainer } |select name

    write-host ""
    Write-Host "Running the driver comparison between the first harvest and second harvest"

    #compares drivers from the 1st harvest and 2nd harvest and only gathers drivers that only exisits in the 2nd harvest
    $Indicators=Compare-Object -ReferenceObject $updated -DifferenceObject $baseline -property name | select name, sideindicator

    write-host ""
    write-host "New Drivers:"

    #for every new folder, its copied from the 2nd harvest folder location to a third location
    foreach ($indicator in $Indicators){if ($indicator -match "<="){$folder=$indicator | select -ExpandProperty name
        copy-item $updateddrivers\$folder $newdriverpath\$folder -Recurse
        write-host $folder
        }
    }
  
    #if there are no differences from the 1st and 2nd harvest, the third folder is not created as there is no output.
    if (!(test-path $newdriverpath)){
        Write-Output "There were no new drivers discovered."
        exit
        }

    #If there are new drivers, this outputs that the script is done and the path where the drivers are placed
    if (test-path $newdriverpath){
        Write-host ""
        write-host "The driver comparison has completed. Please submit all new drives to the Enterprise Team."
        write-host "the new drivers can be found at the following location."
        write-host ""
        write-host $newdriverpath
        write-host ""
        exit
        }
}