04/18/2015 update : Good news, Microsoft has just released an updated version of his set of SCCM cmdlet as a separate package. Lot of cmdlet are fixed including Import-CMDriver. you can download it here.
“Why the hell Microsoft ???!!!” is probably one of the first question that comes to mind after playing around with Powershell and SCCM 2012 R2. For those who haven’t tried yet ; the implementation looks very hazardous to say the least, some cmdlet are buggy, some doesn’t works, and most of the time you’ll need to go the WMI way, which is really far from taking the most benefits out of Powershell if you ask me.
Today our guilty cmdlet is called Import-CMDriver, and I will show you a small tip to make it work better on SCCM 2012 R2 with CU4.
The bug
Import-CMDriver, as you have guessed allow to import driver to SCCM. But not only, it can also (in theory) add category, and put the driver in a driver package.
If you just import drivers, it will hopefully works :
PS C:\> $Drivers = Get-childitem -path "\\cm01\Sources\OSD\DriverSources" -Recurse -Filter "*.inf"
|
But if you try to import drivers and want to put them in a package, it will miserably break…!!!
PS PS1:\> New-CMDriverPackage -Name "Lenovo T450" -Path "\\cm01\Sources\OSD\DriverPackages\Lenovo T450"|Out-Null At line:4 char:1 At line:4 char:1 |
The solution
As you can see in the first console capture, the cmdlet cast out a resulting object, but for some reasons does not remember it. You can see it clearly if you try to catch the result in a variable, it will definitely stays empty :
PS PS1:\> foreach($item in $Drivers) |
While not being directly related to the cmdlet failure (it’s just my guess), it’s one of the bugs that we will try to overcome to allow the drivers to be injected in a package.
Thanks to Technet, there is an easy way to catch all this output, you can just pipe the cmdlet with a select-object *
PS PS1:\> foreach($item in $Drivers)
|
Now that all the drivers information are kept, we have all we need (for instance the driver’s CI_ID dynamically created during import) to put them in a package. We can use the cmdlet Add-CMDriverToDriverPackage to finish the job :
PS PS1:\> New-CMDriverPackage -Name "Lenovo T450" -Path "\\cm01\Sources\OSD\DriverPackages\Lenovo T450"|Out-Null |
Done !!!!
Lesson learned : Powershell is great, even at fixing Powershell !!!!
A Working example
I won’t leave you without putting down a full importation script example. This is a script that I borrowed to William Braken, thanks to him. I simply changed the import-CMDriver line at the end by the trick I presented above.
#==============================================================
#Import Drivers and Create Driver Package – SCCM 2012
#==============================================================
#==============================================================
# Set variables
#==============================================================
#== Example: "Dell Optiplex 7010" or "Dell Latitude E6540"
$Model="Lenovo T450"
#== Example: "Win7" or "Win8"
$DriverOS="Win8"
#== Options are "x86" or "x64"
$DriverArchitecture="x64"
#== Driver root source dir
$DriverRootSource="\\cm01\Sources\OSD\DriverSources"
$DriverPkgRootSource="\\cm01\Sources\OSD\DriverPackages"
#==============================================================
# Begin
#==============================================================
#Put together variables based on model, os, and architecture
$DriverPackageName=$Model+""+$DriverOS+""+$DriverArchitecture
$DriverSource=$DriverRootSource+"\"+$DriverOS+$DriverArchitecture+"\"+$Model
$DriverPkgSource=$DriverPkgRootSource+"\"+$DriverOS+$DriverArchitecture+"\"+$Model
# Verify Driver Source exists.
Write-Host"Checking for "$DriverSource
If(Get-Item$DriverSource-ErrorActionSilentlyContinue)
{
# Get driver files
$Drivers=Get-childitem-path$DriverSource-Recurse-Filter"*.inf"
}
else
{
Write-Warning"Driver Source not found. Cannot continue"
Break
}
# Create Driver package source if not exists
If(Get-Item$DriverPkgSource-ErrorActionSilentlyContinue)
{
Write-Host"$DriverPkgSource already exists… "
}
else
{
Write-Host"Creating Driver package source directory $DriverPkgSource"
New-Item-ItemTypedirectory$DriverPkgSource
}
# Import SCCM module
Import-Module"C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1"
#Your site code here
CDCM1:
If(Get-CMDriverPackage-Name$DriverPackageName)
{
Write-Warning"$DriverPackageName Already exists. Existing"
Break
}
else
{
Write-Host"Creating new Driver Package: "$DriverPackageName
New-CMDriverPackage-Name"$DriverPackageName"-Path"$DriverPkgSource"
$DriverPackage=Get-CMDriverPackage-Name$DriverPackageName
New-CMCategory-CategoryTypeDriverCategories-Name$DriverPackageName-ErrorActionSilentlyContinue
$DriverCategory=Get-CMCategory-Name$DriverPackageName
foreach($itemin$Drivers)
{
$DriverPackage=Get-CMDriverPackage-Name$DriverPackageName
$DriverInfo=Import-CMDriver-UncFileLocation$item.FullName-ImportDuplicateDriverOptionAppendCategory-EnableAndAllowInstall$True-AdministrativeCategory$DriverCategory-UpdateDistributionPointsforDriverPackage$False|Select-Object*
Add-CMDriverToDriverPackage-DriverId$DriverInfo.CI_ID-DriverPackageName$DriverPackageName
}
}
CDC:
Now creating drivers package in SCCM 2012 with Powershell is fun again.
Enjoy and see you soon.