Dell PowerShell Provider Install w/ ConfigMgr

I just created an App for the Dell PowerShell Provider 1.3.0, was able to learn what I needed from Mike’s Blog (THANK YOU). I thought I’d add a cmd file install for 1.3.0 and do a more graphical walk through (I’m a visual guy).

To get the download, go HERE (DellCommandPowerShellProvider1.3_259.zip)

Download, grab the DellBIOSProvider folder
image

Copy that to your Source (\\CMSRC\SRC$\Apps\Dell\DellPowerShellProvider\1.3.0\x64)
image

Programs:
Install: "Load_DellPowerShellProviders-x64.cmd"

Uninstall: cmd.exe /c rd "%programfiles%\WindowsPowerShell\Modules\DellBIOSProvider" /S /Q

image

Detection Method:
File Path: %PROGRAMFILES%\WindowsPowerShell\Modules\DellBIOSProvider
File Name: DellBIOSProvider.dll
Version: 1.3.0.0
image

Requirements: (x64 & Dell) – See previous post on creating Dell Requirement
image

Once Installed, you can test by launching PowerShell and loading the Module
image

import-module DellBIOSProvider

image

I highly recommend reading Mike’s Blog Post from last year when he blogged the install of version 1.1, he goes into additional detail and background.

Dell Bios Updates - ConfigMgr App Model - Post OSD

I’m pretty good about keeping our Dell machines at the current BIOS level, usually a couple models get updates every month… then there was that Intel AMT vulnerablity, and they released updates for nearly all of our models, so that was fun.  I tweeted about my exploits and had requests to share how I’m doing it… so here it is…

App Model & Power Shell

I blogged a 3 part post back in Dec 2015, I’m not going to redo everything, but send you there if you need to build your collections yet:

https://garytown.com/updating-dell-bios-with-configmgrpost-1creating-model-based-collections

Another Pre-Req is having a global condition for “Model”, which I cover here: https://garytown.com/updating-dell-bios-with-configmgrpost-3the-application-deployment

Once you have that out of the way, it’s just building your App.

 

It’s really simple, we have a PowerShell script that will:

  1. Suspend Bitlocker (Works for Win 7-10)
  2. Stop the MBAM Service (So MBAM doesn’t start Bitlocker again before rebooting)
  3. Grab Dell Bios info from the Bios EXE file in same directory
  4. Create Log File name based on that EXE
  5. Confirm Bitlocker is Suspended
  6. Update Bios, creating Log File
  7. Reboot Machine
    1. Reboots right away if no one is logged on
    2. Give 5 Minute & 2 Minute warnings if someone is logged on

The nice thing about this method, it’s one script, that never changes. You just add it to your Model Folder. Every time a new BIOS comes out, replace the BIOS.EXE in the source, update the Application Detection Method, and update the content for that deployment.  All Set!

Now the Script:

There are 2 parameters, you tell it where you want your log file, and what your BIOS password is.  That’s it:

The Application
image

Deployment Types, One Per Model, this will make the download quick, as it only downloads the one for that model, and gives you the ability to do easy detection rules.

image

Programs: powershell –executionpolicy bypass –file "BiosUpdate.ps1" –Biospassword P@ssw0rd -LogPath C:\Cabs\InstallLogs
- Change your Bios Password & where you want to save the log files.
image

Detection is just a Registry Key:
image

image

Requirements: Model = the Model (see previous post for more details)

image

Return Code, Change 0 = Hard Reboot

image

My Source Folder Structure:
image

Actual Content for Deployment Type:
Contains the PowerShell File (Which you don’t need to change, works for every model & every version of the Bios)
image

 

There you have it, for your deployments

Download AppExport & Script HERE. If you choose to import the App, you’ll want to build your own Folder Structure and update the Content Tab for each deployment.

Leave a comment if you have a question, or hit me up on Twitter – @gwblok

Dell BIOS update–WinPE–Model Independent–From Internet

Update 5/26 - Updated Script to use Dell's Enterprise Cab XML data, instead of the ever changing Support Site.  This now truly does work for all Dell Models that I know of. 🙂  Thanks Mark - POST HERE Mark gives some back story as to how we came up with this idea, and why we wanted to switch from our old method.

Updated Script: (Mark Updated to fix some model name changes 2/26/2018) - Please grab the updated Script from Below and replace the one in the download.  I have not updated the Download.
For any questions regarding the download portion, check Mark's GitHub

The new Package contents:

 

 

 

The Task Sequence:

Just an FYI... you might notice that it's not updating the BIOS to the latest BIOS update for that model.  Example, yesterday several bios updates were released for several models to their WebSite. Those will not install using this method.  The Enterprise CAB data has extra layers of Change Management / Testing, so you can feel even better about applying the BIOS updates automatically. Once those extra layers have completed, then they become available.

 

Until Then, I’ve updated scripts and added a script for the TPM update.

2 scripts now, based on Dell Driver Cab, instead of HTML scraping.

  1. DellTPMDownloadUpdatePE – Downloads and install the TPM 2.0 x64 Update for that model (if available)
  2. DellCabBiosUpdate.ps1

----------------

Original Post:

Ok, so you’re thinking, Gary, you just posted about this, and you’d be right, I did, see.. https://garytown.com/dell-bios-upgrade-in-osd-winpe-x64, but in the past week or so, I’ve come up with an idea, after looking at Maurice Daly’s download utilities, thinking, why can’t I just do something like that, and not have to have any content (beside the script and utility) to update the bios, and have it work on any dell model?  So that’s what I did, with the help of @modaly_IT & @geodesicz (my personal powershell guy), we came up with this solution.

DOWNLOAD HERE

Goal of Script:  Update Dell Bios on Any Model without having to maintain and update packages.

What it does:

  1. Gets Model info from WMI
  2. Downloads latest Bios directly from Dell
    1. No testing with Proxy server done, you can probably add this into the script, just don’t ask me how. (I don’t know, ask Maurice, he has it figured out in his cool GUI version)
    2. Mark (@Geodesicz) was able to make the changes to have this work in PE.
  3. Applies Bios to system during WinPE
  4. Create variables to do extra steps based on exit codes

Pros:

  1. Never manually download a BIOS update and build a BIOS package again
  2. Always install the latest Dell BIOS on the system you’re imaging
  3. Works on all dell models, no tracking down a bios per model
  4. See Number 1

Cons:

  1. Giving up control of the Bios Version you’re installing
    1. This doesn’t bother me personally, I haven’t ever had a BIOS update brick a machine, and if the BIOS is coming directly from Dell, it’s supported by them, and they will assist if anything did happen.
  2. Uses the Internet to pull content, while only 8-12MB per Computer, if you’re imaging large numbers, and you don’t plan ahead, this could be potential issue.
  3. Uses HTML scraping, so if Dell ever changes their website, we’d have to update the script.

 

The Script… while very similar to my last one, it has some key differences.

  1. The Bios Password is now parametrized, no longer requiring the text file to pull password (Thanks Mark)
  2. Has large download section in which it has the logic to get the right Bios file (from Maurice) & the Actual download step, (from Mark).
  3. Validating the Bios downloaded.

This script is quite simple still, feel free to add additional logic to it for error handling.

image

image

 

in the TS:

image

Package Content:
image

As before, it will create logs in the SMSTSLog folder in %temp%.
The only difference now, I added a group that will only run if the Download Fails based on lines 86-90 of the script.

For more details on how to setup the rest, check out the old Post:
https://garytown.com/dell-bios-upgrade-in-osd-winpe-x64

Maurice’s new GUI version: http://www.scconfigmgr.com/2017/03/01/driver-automation-tool/

Maurice’s older version, where I stole the code from: https://gallery.technet.microsoft.com/scriptcenter/SCCM-Dell-Client-Bios-ee577b04

Dell Bios Upgrade in OSD WinPE x64

Update 3/17 – Update a couple sections to fix Bug in Script with assistance from the Dell BIOS Dev team. Uploaded the TS Export of this section.

Download Here:  3/24 – Removed all of the Bios Files and Update Utility to comply with Dell’s EULA.

Task Sequence Export HERE – You can import this into your system and it will have all the steps., Then copy the steps into your working TS.  No Content is included in this export.  Create your own Package with the “Full Folder Structure Download” and link to that in your TS

image_thumb3

Original Post:

Ok, So for a long time, You couldn’t upgrade Dell’s Bios in WinPE x64 because they didn’t have native x64 bios installer, this has recently changed. – Download HERE
Mike wrote up a nice intro to the new utility HERE

I do all of our bios updates using the “Application Model” after the OS is laid down, so it has the 32bit subsystem, it works fine. But I know many people like to do it during PE.  So I thought I’d play with it this morning and write up a script.

PreReqs for my script: Enabled PowerShell.  Here are the things we’ve enabled: (Win10 1607 Boot Media)
image_thumb21

Benefits of doing it how I’ve setup.

  1. One Script works for all models, you just have to setup your folder structure to match the Computer Model in WMI.
  2. Grabs Bios Password from File, you only have to update one File if you change your Bios Password
  3. Creates TS Variables to avoid Rebooting if already on same bios version.
  4. Creates Log file based on the Bios Update in the %temp%\SMSTSLog Folder (X:\windows\temp\SMSTSLog\BiosFileName.log)
  5. New Bios version release? No Problem, delete the old one, add the new one, update Package, done, no script change required.
  6. It’s Fun

Package Folder Structure.  Make sure the subfolders exactly match the WMI Model Name
Get-WmiObject -Class Win32_computersystem | Select-Object -ExpandProperty Model
image_thumb23

image_thumb31

Once you’ve created your Folder Structure, populate it with the latest Bios files for each model. (Just download and place in the folder, no renaming required)
Also, create a txt file in the package root called Bios.txt and put your Dell Bios password in that file.
image_thumb6

Now, the PowerShell script will query WMI for the Model, look for the bios file inside of the corresponding folder and apply it to the system using the Flash64w.exe utility. (It will pull the password from the bios.txt file in the root of your package)

Updated Script from 3/17 Shown HERE:
image_thumb1

Based on the Exit Code of the Bios Update, it will create a TS Variable you can use to reboot, retry if low battery or continue on with your TS. – More info about Dell Exit Codes here… I noticed it didn’t have them all though: http://en.community.dell.com/techcenter/enterprise-client/w/wiki/3462.dup-bios-updates.  I trigger events based on Exit Code 2 (Successful but requires Reboot) and Exit Code 10 (Battery too Low).  You can easily add additional Exit Codes and create custom variables to have your TS do other thing based on those Exit codes.

Now in your TS:
Create Dell Upgrade Bios Group, and set to only run if a Dell Computer:
select * from Win32_ComputerSystem where Manufacturer like "%Dell%"
image_thumb56
Create Run Command Line Step:
powershell.exe -NoProfile -ExecutionPolicy ByPass -file .\DellBiosUpgradePackage-2.0.ps1
image_thumb57

Create another Group, This will run if the battery was too low to update the Bios.  It will wait 10 minutes and try again.  If the Battery is still too low after that Point, it will continue on without updating Bios. – You can easily put a step here that will popup a message box about how the Bios Didn’t update, etc.
SMSTS_BiosUpdateBatteryCharge = True
image_thumb58
Command Line Step: powershell.exe -NoProfile -ExecutionPolicy ByPass -Command "Start-Sleep -s 600"
image_thumb59
image_thumb41

It will then wait 10 minutes and try again, if successful, it will set variable SMSTS_BiosUpdateRebootRequired = true and continue onto the next group to reboot.  If it fails due to battery again, it will set SMSTS_BiosUpdateBatteryCharge = True and show a Message that it probably has faulty battery.  At this Point, you can click “OK” and let it continue, or turn it off and replace battery.

image_thumb60

Create another Group which will reboot the computer and any other steps needed to get back to where you were before the reboot. (TS Variable = SMSTS_BiosUpdateRebootRequired equals true)
I added a “Format” step, just to ensure there was a place for the Boot Image to download too, this might not be needed in your environment depending on placement of the Bios Upgrade.
image_thumb61

Ok, that should be it.

Note, I was running into some issues with the flashw64.exe utility from Dell, getting this error:
image_thumb19

Once I added another line into the script to launch the software once with minimal arguments, it worked fine. I’ve contacted Dell Support to see if they have any ideas on that.

This is the line I added to fix that error:
start-process "$PSScriptRoot\Flash64W.exe" /"p=$BiosPassword /s"
image_thumb1[1]

However, changing the Argument Line & Update Bios lines fixed the issue, and I haven’t needed that.  I’ve heard from commenters that people are still getting that message, so hopefully this will help. If you do get that message, Open a support issue with Dell, they will help address it.  FYI, I’m also using WinPE 1607, not sure if the Build has anything to do with that error.

Update: 2/27/17 – Response from Dell:
Hello, Gary: I heard back from the BIOS engineering group. They said that they have not tested the utility using Powershell scripts. They do not support Powershell scripts. They only support use of the utility within a command prompt in Windows… It is also supported within WinPE (in a command prompt).

Update 2/28/17 – Call From Dell, they are escalating the issue to the BIOS engineering group and will be looking into the problem to see if they can resolve the issue when using it in PowerShell.

Update 3/17/17 – After working will BIOS Dev team, was able to rework the script to resolve the error I was seeing.  Updated Script in Download and in this Blog Post.

If you run into any problems, let me know and I’ll test that model if I have it.
Tested on so Far:

  1. Laptops
    1. Latitude E5550
    2. Latitude E5470
    3. Latitude E6540
    4. Latitude E6530
    5. Latitude E6430
    6. Latitude E7250
    7. Latitude E7240
    8. Precision 7510
  2. Desktops
    1. OptiPlex 7010

Dell Warranty Reporting via ConfigMgr - Dell Warranty API

Update 11/3 – Contact info for Dell API key has changed: (Info directly from Dell API Support team)
New process - The customer should create ticket via TechDirect
https://techdirect.dell.com;
Alternatively they can reach out to us at
APIs_TechDirect@Dell.com

Update 10/20  - Nickolaj posted his Dell Right Click tool, so if you’ve take then time to get the Dell API, you should add his tool for individual lookups in the Console.

Update 8/18 – Finally received our Production Key.  In the Meantime @Geodesicz also modified the script to run in either Sandbox or Production mode.  It will try if the Key can be used on Dells production API environment, and move forward if it can, otherwise, if errors, then falls back to the SandBox API. – I’ve pasted the updated Script in below and updated the latest version in the download.

Update 7/15 - Working with Dell, found we were using the older API, needed to be using v4 instead of v2 API.  Currently rewriting entire Script to use new API calls.  Will update this Post once the new script is done and tested with the updated API URL.  Will provided updates scripts and Reports once complete.

Update 7/11 - Modified Script to use the Actual Dell API URL instead of their SandBox URL. (Updated Text below & Download Zip File)

 

Recently I attended MNSCUG meeting where Jason Sandys presented on ConfigMgr database.  He showed his OSD Info Script that would write information to WMI so that you could then capture it with the hardware inventory to report back on additional information.  That got me thinking about what else I'd like to have in WMI to report on... Dell Warranty Info!

Started looking for a Dell Warranty Script to get me started, found one HERE. Used that to sparks some other ideas.  Contacted Dell to get the Dell Warranty API access process started. – https://techdirect.dell.com – Create a ticket, or alternatively, contact APIs_TechDirect@Dell.com.
Once you’ve contacted Dell to get the conversation started, you'll have to fill out some questionnaire, etc., but eventually, you'll get your access and own personal API Key.

I worked with my friend @Geodesicz (Mark) who is a PowerShell wizard, and he was able to build me the script I wanted.  Pulls Dell Warranty Info from Dell's warranty API and places that info into WMI on the workstation.  We are using a new namespace called ITLocal, which was already on the machines since we had implemented Jason Sandys OSDInfo Script the week before and decided to use that namespace for consistency.

Download Our Script HERE - Code shown below:

<#
Write Dell Warranty Information to WMI V2.2
Queries Dell Web Service API V4 for Warranty Info
Creates Custom WMI Namespace and Class
Writes Warranty Info to WMI
Requires PowerShell V5
---------------
You can also add this custom class to be collected by Configuration Manager hardware inventory
---------------
Script written by Mark Godfrey (http://www.tekuits.com/blog) and Gary Blok (http://garytown.com/) - MN.IT
#>

[CmdletBinding()]
Param(
    [Parameter(Mandatory=$true,Position=1,HelpMessage="APIKey")]
    [ValidateNotNullOrEmpty()]
    [string]$APIkey
)

# Get Service Tag of Local Machine
$ServiceTag = Get-WmiObject -Class Win32_Bios | select -ExpandProperty SerialNumber
      
# Query Web Service API
Try
{
    $URL1 = "https://api.dell.com/support/assetinfo/v4/getassetwarranty/$ServiceTag"
    $URL2 = "?apikey=$apikey"
    $URL = $URL1 + $URL2
    $Request = Invoke-RestMethod -URI $URL -Method GET
}
Catch [System.Exception]
{
    Write-Output "Production API URL failed, switching to sandbox API"
    $URL1 = "https://sandbox.api.dell.com/support/assetinfo/v4/getassetwarranty/$ServiceTag"
    $URL2 = "?apikey=$apikey"
    $URL = $URL1 + $URL2
    $Request = Invoke-RestMethod -URI $URL -Method GET
}
$Warranties = $Request.AssetWarrantyResponse.assetentitlementdata | where ServiceLevelDescription -NE 'Dell Digitial Delivery'
$AssetDetails = $Request.AssetWarrantyResponse.assetheaderdata

# Set Vars for WMI Info
$Namespace = 'ITLocal'
$Class = 'Warranty_Info'

# Does Namespace Already Exist?
Write-Verbose "Getting WMI namespace $Namespace"
$NSfilter = "Name = '$Namespace'"
$NSExist = Get-WmiObject -Namespace root -Class __namespace -Filter $NSfilter
# Namespace Does Not Exist
If($NSExist -eq $null){
    Write-Verbose "$Namespace namespace does not exist. Creating new namespace . . ."
    # Create Namespace
       $rootNamespace = [wmiclass]'root:__namespace'
    $NewNamespace = $rootNamespace.CreateInstance()
    $NewNamespace.Name = $Namespace
    $NewNamespace.Put()
    }

# Does Class Already Exist?
Write-Verbose "Getting $Class Class"
$ClassExist = Get-CimClass -Namespace root/$Namespace -ClassName $Class -ErrorAction SilentlyContinue
# Class Does Not Exist
If($ClassExist -eq $null){
    Write-Verbose "$Class class does not exist. Creating new class . . ."
    # Create Class
    $NewClass = New-Object System.Management.ManagementClass("root\$namespace", [string]::Empty, $null)
    $NewClass.name = $Class
    $NewClass.Qualifiers.Add("Static",$true)
    $NewClass.Qualifiers.Add("Description","Warranty_Info is a custom WMI Class created by Gary Blok(@gwblok) and Mark Godfrey(@geodesicz) to store Dell warranty information from Dell's Warranty API.")
    $NewClass.Properties.Add("ComputerName",[System.Management.CimType]::String, $false)
    $NewClass.Properties.Add("Model",[System.Management.CimType]::String, $false)
    $NewClass.Properties.Add("ServiceTag",[System.Management.CimType]::String, $false)
    $NewClass.Properties.Add("ServiceLevelDescription",[System.Management.CimType]::String, $false)
    $NewClass.Properties.Add("ServiceProvider",[System.Management.CimType]::String, $false)
    $NewClass.Properties.Add("StartDate",[System.Management.CimType]::String, $false)
    $NewClass.Properties.Add("EndDate",[System.Management.CimType]::String, $false)
    $NewClass.Properties.Add("ItemNumber",[System.Management.CimType]::String, $false)
    $NewClass.Properties["ItemNumber"].Qualifiers.Add("Key",$true)
    $NewClass.Put()
    }

# Write Class Attributes
$Warranties | ForEach{
    $wmipath = 'root\'+$Namespace+':'+$class
    $WMIInstance = ([wmiclass]$wmipath).CreateInstance()
    $WMIInstance.ComputerName = $env:COMPUTERNAME
    $WMIInstance.Model = "Dell " + ($AssetDetails.MachineDescription)
    $WMIInstance.ServiceTag = $AssetDetails.ServiceTag
    $WMIInstance.ServiceLevelDescription = $PSItem.ServiceLevelDescription
    $WMIInstance.ServiceProvider = $PSItem.ServiceProvider
    $WMIInstance.StartDate = ($PSItem.StartDate).Replace("T00:00:00","")
    $WMIInstance.EndDate = ($PSItem.EndDate).Replace("T23:59:59","")
    $WMIInstance.ItemNumber = $PSItem.ItemNumber
    $WMIInstance.Put()
    Clear-Variable -Name WMIInstance
    }

Syntax: WriteDellWarranty2WMI.ps1 -APIKey Y0UR@P1K3Y  (Get your APIKey from Dell)
image

Make a Package & Program and push it out to your dell Computers. (remember to have Windows Manage Framework 5 already installed on your workstations).

image

We also added this to OSD, like so:
image

 

Here is a capture of the info in WMI after the Script has been run: (Using Coretech WMI Browser)
image

Once in WMI, we have to add this to our Hardware Inventory:

Go into the Default Client Settings, Hardware Inventory -> Set Classes -> Add... -> Connect to WMI namespace root\ITLOCAL
image

Once Connected, you should see the Warranty_Info

image

After you check the box, and click OK, it should show up in your classes list:
image

I unchecked everything here, because I only want to apply this to my Dell Workstations.
I opened our Dell Client Workstation Settings (We have one that applies only to Dell Workstations, which I borrowed the idea from Mike Terrill after reading this Post about inventory bios settings.

image

Ok, now wait for your Hardware Inventory cycles to run and the data to populate in your ConfigMgr DB.

Ok, Building reports... Fun with SQL Report Builder!
Mark & I have created two quick and easy reports for now, just as proof of concept, but will probably find ways to pull this data into other reports as well.

  1. Dell Warranty Expired Report - This report shows all of the Computers in ConfigMgr that have expired Warranties:
    image
    You can click on the + next to the computer name to expand if has more than 1 warranty associated with it.
  2. Dell Warranty Expires between dates - This report will let you pick dates and show you the computers that will expire. (If computer has more than 1 warranty, it will only use the warranty with the latest end date)
    image
  3. Dell Warranty Info for specific Computer: Super simple report that lets you put in a computer name and get the info:
    image

 

We created a new folder called Hardware - Warranty, created our reports there.  I've added those 3 reports to the ZIP file you can download with the Script.

Just import them into your system, as long as you kept the namespace the same as the one in our script, it should work fine.  Update your Data source in each report, and you should be set.

In the 2 reports, I have it so if you click on the computer name, it links to a hardware report with more info about that specific computer.  I think it's a built in ConfigMgr report, so it should still work, if not, just delete that action:
image

 

I really hope I didn't miss anything, there was a lot of parts to this.  Mark will also be blogging this, since it was a joint project.  He'll probably have more info about the Powershell stuff itself.

Couple of things to remember... ConfigMgr DB is NOT the same as a Configuration Management Database.  When you delete the computer from ConfigMgr, there goes the data along with it.  I make sure to tell our management, this data is ONLY useful for computers currently active in our system, we do NOT keep historical data.

As always, if you run into any problems, please feel free to contact me, I'll update the Blog to correct anything found.  Sometimes its hard to get the proper screen captures after you've already set it up and been using it.

Also, I highly recommend checking out Jason's OSDInfo Script & Mike Terrill's Dell Posts, those might help shed some light on what we've done.