Wednesday, February 14, 2018

Dell OneShot Driver Update

Sometimes when there is a problem with a machine an older driver is at fault. For firms that have standardized on Dell they have provided a nice tool call Dell Command  | Update. This is a nice tool Dell made to keep their business lines (OptiPlex, Precision, or Latitude for example) driver sets up to date.

It installs an agent that runs on a schedule (monthly by default) to keep the system up to date on drivers. It queries drivers from Dell directly (or via an on site repository) so you can get the latest drivers easily and automatically. As my firm has very few egress points, I chose not to use it in this capacity however it does have a CLI executable! While we use ConfigMgr to do driver management as issues dictate (needing newer nVidia non ISV driver for example), I put together a package in ConfigMgr for the techs to manually update all drivers on a device when it comes in for service. Known as the "OneShot Driver Update".

You can find install instructions to get Command | Update installed on a PC. Once installed, just copy the install folder to a source folder in SCCM. I created two BAT Files that perform the following:

  • Remove logs from a previous run
  • Pause Bitlocker
  • Update Drivers
  • Resume Bitlocker if no restart needed
  • Optionally copy the logs to a server location

As you are generally updating drivers that impact the boot chain (yes the video driver at times) you need to pause Bitlocker. Older versions of the tool did not handle Bitlocker, which is what started me down the path of a simple BAT wrapper for the tool. The Update drivers bullet above is handled via a specific BAT and custom XML file though I have though about doing a menu in the BAT at some point to combine them. For the XML, you can create it in the GUI version of the tool then save it out and therefore use it to update only the categories you want.

I have created two file sets. One that does all device drivers yet skips applications. The second only updates the system firmware, aka BIOS or UEFI. You just run the appropriate BAT as an admin. They are even called '_RunAsAdmin.BAT'.

For SCCM we just have a package with both BATs called out as Programs and have them published via our internal Package Downloader Tool (PDT). Otherwise you can simply advertise it as available to be ran from Software Center. Or just put on a network location somewhere.


This Script is provided as-is, no warranty is provided or implied.The author is NOT responsible for any damages or data loss that may occur through the use of this Script.  Always test, test, test before rolling anything into a production environment.

You can find these two scripts here.


Monday, January 29, 2018

Old School BitLocker Enable Script

A friend of mine has a small client with a few hundred systems. Recently they identified a business need to encrypt all their devices so he asked me for some assistance. As they were on Windows 10 this would be an easy exorcise but one I would have to do differently due to their maturity and lack of something like MBAM licensed or third party options so we elected to use native Bitlocker with AD DS integration. Instead of using Powershell we chose to do it oldshool so it was easier to follow.

We chose to do this in three steps:
  1. Enable TPM
  2. Configure Bitlocker
  3. Encrypt with Bitlocker
Luckily they were over 95% Dell OptiPlex systems so it was pretty easy. For the TPM we used the Dell Command | Configure (CCTK) to create SCE files. These were pushed out via GPO as a DOS script. The script does these tasks

  • Checks for a dropper file and exits out if ran. If not creates dropper file
  • Detects 32-Bit or 64-Bit so it runs the right SCE
  • Initiates a restart for the TPM to be actually setup

Per Dell requirements you have to set a firmware (BIOS) password if there is none, then turn on and enable the TPM, and then finally reset the password. You can follow the process in this White Paper by Dell instead of me rehashing. This script is attached at the bottom.

Next we had to configure Bitlocker and this was done via GPO. Choosing things such as 128-bit vs 256-bit and XTS vs CBC for Windows 10. We went with 128 bit XTS as well as configure it to escrow the key in AD.

Finally we had to start encryption. Some people think you just set the GPO policy and the system starts encryption. This is not true, GPO just sets all the settings or preferences. You still need to trigger encryption. We did this also via a GPO startup script a week after using GPO to enable TPM. It created a scheduled task to run the script.

While their %SYSTEMDRIVE% is on C: some of these systems have additional volumes on secondary drives that they needed to encrypt as well. I started with a for loop like this one but it was not that eloquent.

 ::look for drives  
 for %%a in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do if exist %%a:\nul (   
 Call :ENCRYPT %%a  
 Goto EXIT  

However these being OptiPlex units they had optical drives so that meant the OS was on C: and D: or maybe E: was the optical so I went a different path. Additionally they had network shares setup via GPO. While manage-bde would error out in these two situations it was not that pretty so I went with a different for loop that used diskpart. I modified one used previously for other tasks. I found it online and unfortunately I do not recall where to give credit.

   for /f "delims=" %%i in ('^  
     echo list volume ^|^  
     diskpart ^|^  
     findstr Volume ^|^  
     findstr /v ^  
     /c:"Volume ### Ltr Label    Fs   Type    Size   Status   Info"^  
     ') do (  
     set "line=%%i"  
     set letter=!line:~15,1!  
     set fs=!line:~32,7!  
     if not "    "=="!fs!" (  
       if not " "=="!letter!" (  
         call :Encrypt !letter!  

This spits out any physical volume simply as 'C' or 'E' which then calls the function :Encrypt. It will put the key into both AD and TPM, and then encrypt it. At the end it will prompt the user to restart as a restart is needed for the system drive to start encrypting.


This simply sets up shop. The loop passes C for example, but manage-bde wants the volume as C: so this addresses that but also changes to a more friendly variable used throughout the rest of the script. You could technically pass this via the loop by using:

      call :Encrypt !letter:!  

above. Since this is running via GPO we have a check to exit out if any volumes are already encrypted.

 ::Detecting if Bitlocker is already on  
 %WINDIR%\System32\manage-bde.exe -status %1 | FIND "Protection On" > nul2  

In addition I put in some friendliness in case it is ran outside of the GPO so there are ECHO statements throughout as well as the initial header.

 ECHO Encrypting Volume %DRIVELETTER% your PC, be patient . . .  
 ECHO There is no Need to write down the numerical password below  
 TITLE Encrypting your PC, be patient . . .  

The actual meat of it is to create the protectors and encrypt it. First it creates the password protector which then gets put into ActiveDirectory per GPO. then enables the TPM protector, and finally starts the encryption.

 ::Create Recovery Key  
 ECHO Create Recovery Key  
 %WINDIR%\System32\manage-bde.exe -protectors -add %DRIVELETTER% -recoverypassword  
 ::Create TPM Key  
 ECHO Create TPM Key  
 %WINDIR%\System32\manage-bde.exe -protectors -add %DRIVELETTER% -tpm  
 ::Enable Bitlocker on Windows Drive  
 ECHO Enable Bitlocker on Windows Drive  
 %WINDIR%\System32\manage-bde.exe -on %DRIVELETTER%  

Finally we need to exit out. If a volume was encrypted it will set a variable and exit the loop. Once all volumes are parsed it will initiate a restart which is when the Windows volume actually encrypts.

 Set BLEnabled=YES  
 EXIT /B  
 IF %BLENABLED%==YES %WINDIR%\System32\shutdown.exe /r /t 300 /c "IT Department made a change and your workstation will restart in 5 Mins. Questions? Please open a ticket with IT Support."  

Thats it. They were able to encrypt several hundred systems quickly to meet their business need and I did not have to spend a great deal of time helping my friend out and this was real easy for them to follow and understand how it worked. I would say it took you longer to read this then for me to write it.

On the lab system you can see the key is escrowed in AD and it matches if you manually print the key to PDF. AD also holds all the previous keys for that machine object. My friend ran it many times to validate it worked.


This Script is provided as-is, no warranty is provided or implied.The author is NOT responsible for any damages or data loss that may occur through the use of this Script.  Always test, test, test before rolling anything into a production environment.

You can find these two scripts here.


Monday, January 8, 2018

Windows 10 In-Place Upgrade Assessment Error Handling

As I progress to making Windows 10 available to end users I needed to polish out the error handling. While I am using the Upgrade Readiness tool that Microsoft provides to target successful systems, I am still performing one final check in the Task Sequence by having the Task Sequence do an assessment before continuing and capturing those results.

You just insert the Upgrade Operating System step and select the box 'Perform Windows Setup compatibility scan without starting upgrade' at minimum. I have also selected the other chekboxes below it such as 'Ignore any dismissible compatibility messages' checkbox. If unchecked, this will for example, trigger a failure for an incompatible driver that gets removed anyway. Useful if you have some weird driver for a microscope type device (I do!) but not useful if you accept the removal that the upgrade does. For those types of endpoints the Readiness tool has identified them.

I also enabled the last two check boxes. These will cause the eval step to pull the latest eval info from Microsoft instead of using what data shipped on the ISO. There may be some proxy concerns here.

Here is what that part of the Task Sequence looks like:

For initial roll out to IT, I am using Niall C. Brady's dialog Powershell Script so I wont cover that part here. I am working on a template script to pull HTML edited file to be more polished for an end user when I get to that point but Niall's script works great.

The 'Upgrade Assessment' step outputs to the read-only variable _SMSTSOSUpgradeActionReturnCode. SETUP.EXE actually outputs in hex whereas the variable is in decimal. Looking at Microsofts blog post these are the major exit codes. I converted the hex to decimal with a converter so I work in the same format ConfigMgr is.

  • No issues found:  0xC1900210 (3247440400)
  • Compatibility issues found (hard block):  0xC1900208 (3247440392)
  • Migration choice (auto upgrade) not available (probably the wrong SKU or architecture)· 0xC1900204 (3247440388)
  • Does not meet system requirements for Windows 10: 0xC1900200  (3247440384)
  • Insufficient free disk space: 0xC190020E (3247440398)

The 'Assessment Errors Detected' group has a condition of _SMSTSOSUpgradeActionReturnCode ≠ 3247440400 whereas the 'Upgrade the Operating System' group has _SMSTSOSUpgradeActionReturnCode = 3247440400.

Under the 'Assessment Errors Detected' Group, each of the 4 sub groups matches a code in _SMSTSOSUpgradeActionReturnCode. For example, the 'Compatibility Issues found (hard block)' group has a condition for _SMSTSOSUpgradeActionReturnCode = 3247440392.

Then each error code displays a custom message and errors the Task Sequence out. For the  'Compatibility Issues found (hard block)' error it shows

The Upgrade Assessment detected an error which is preventing a successful upgrade and it must be mitigated first. There is an application or driver that must be removed first. This is generally due to an old version of Sophos Safeguard present. Please contact the IT Service Desk for assistance.

Again, these groups are just a final sanity check, While the Readiness tool identifies bullet 2 impacted systems, ConfigMgr collections are identifying the last two bullets for example.


This TaskSequence is provided as-is, no warranty is provided or implied.The author is NOT responsible for any damages or data loss that may occur through the use of this TaskSequence.  Always test, test, test before rolling anything into a production environment.

Per request I have made a sample Task Sequence available here so you can see it in action.