Quantcast
Channel: OS|DC
Viewing all articles
Browse latest Browse all 64

SCCM 2012R2: make Import-CMDriver cmdlet work for you.

$
0
0

zgenics_by_NEDxfullMOon

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"
PS C:\> cd Ps1:
PS PS1:\> foreach($item in $Drivers)
{
Import-CMDriver -UncFileLocation $item.FullName -ImportDuplicateDriverOption AppendCategory -EnableAndAllowInstall $True
}


ApplicabilityCondition             :
CategoryInstance_UniqueIDs         : {}
CI_ID                              : 16777424
CI_UniqueID                        : SCOPEID_DAFF1EFF-C9B2-41AE-B628-41E8107C5D8A/DRIVER_8EEA5A1885FF113D3F53C5811F0B4B2C57A2DE53_2BA2183632327B34E06DC096AB83AA53F07D7FE
                                     A808E2D3A801FA9624D1BECCD
CIType_ID                          : 6
CIVersion                          : 2
ContentSourcePath                  : \\cm01\Sources\OSD\DriverSources\System-chipset
CreatedBy                          : VIAMONSTRA\Administrator
DateCreated                        : 12/04/2015 15:16:21
DateLastModified                   : 12/04/2015 15:22:59
DriverBootCritical                 : False
DriverClass                        : System
DriverDate                         : 04/08/2014 17:00:00
DriverINFFile                      : Chipset_SMBus.inf
DriverProvider                     : Intel

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
PS PS1:\> foreach($item in $Drivers)
{
$DriverPackage = Get-CMDriverPackage -Name "Lenovo T450"
Import-CMDriver -UncFileLocation $item.FullName -ImportDuplicateDriverOption AppendCategory -EnableAndAllowInstall $True -DriverPackage $DriverPackage -UpdateDistributionPointsforDriverPackage $False|Out-Null
}
Import-CMDriver : Invalid object path

At line:4 char:1
+ Import-CMDriver -UncFileLocation $item.FullName -ImportDuplicateDriverOption App ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Microsoft.Confi...rtDriverCommand:ImportDriverCommand) [Import-CMDriver], WqlQueryException
    + FullyQualifiedErrorId : UnhandledExeception,Microsoft.ConfigurationManagement.Cmdlets.Osd.Commands.ImportDriverCommand
Import-CMDriver : Invalid object path

At line:4 char:1
+ Import-CMDriver -UncFileLocation $item.FullName -ImportDuplicateDriverOption App ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Microsoft.Confi...rtDriverCommand:ImportDriverCommand) [Import-CMDriver], WqlQueryException
    + FullyQualifiedErrorId : UnhandledExeception,Microsoft.ConfigurationManagement.Cmdlets.Osd.Commands.ImportDriverCommand
Import-CMDriver : Invalid object path

 

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)
{
$DriverInfo = Import-CMDriver -UncFileLocation $item.FullName -ImportDuplicateDriverOption AppendCategory -EnableAndAllowInstall $True
}
PS PS1:\> $DriverInfo
The following exception occurred while retrieving members: "Object reference not set to an instance of an object."
à : ligne:0 caractère:0

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)
{
$DriverPackage = Get-CMDriverPackage -Name "Lenovo T450"
$DriverInfo = Import-CMDriver -UncFileLocation $item.FullName -ImportDuplicateDriverOption AppendCategory -EnableAndAllowInstall $True|Select-Object *
}
PS PS1:\> $DriverInfo


ApplicabilityCondition             :
CategoryInstance_UniqueIDs         : {}
CI_ID                              : 16777428
CI_UniqueID                        : SCOPEID_DAFF1EFF-C9B2-41AE-B628-41E8107C5D8A/DRIVER_677AB9E4AC9BC31271CAA0D8B8188775BBE58732_D8338CEAAB248550205C79DBED812E9AB6A7F3E
                                     D75D8340CC431E3106D61ADC2
CIType_ID                          : 6
CIVersion                          : 4
ContentSourcePath                  : \\cm01\Sources\OSD\DriverSources\System-intelpcc
CreatedBy                          : VIAMONSTRA\Administrator
DateCreated                        : 12/04/2015 15:23:03
DateLastModified                   : 12/04/2015 22:14:21
DriverBootCritical                 : False
DriverClass                        : System
DriverDate                         : 24/04/2014 17:00:00
DriverINFFile                      : IntelPcc.inf
DriverProvider                     : Intel
DriverSigned                       : True
DriverSigner                       : Microsoft Windows Hardware Compatibility Publisher

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
PS PS1:\> foreach($item in $Drivers)
{
$DriverPackage = Get-CMDriverPackage -Name "Lenovo T450"
$DriverInfo = Import-CMDriver -UncFileLocation $item.FullName -ImportDuplicateDriverOption AppendCategory -EnableAndAllowInstall $True|Select-Object *
Add-CMDriverToDriverPackage -DriverId $DriverInfo.CI_ID -DriverPackageName "Lenovo T450"
}

Done !!!!

2015-04-13_07h26_18

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.


Viewing all articles
Browse latest Browse all 64

Trending Articles