Batch – PowerShell – Inject Windows Updates into WIM

email me

Inject Windows Updates right into your WIM, aka slipstreaming.

Batch Method – Single or Multiple Updates

@echo off

:: add your update(s) here
set UDates=C:\MSUpdates

:: The mount path
set WMount=c:\WINMOUNT

:: Your WIM
set WIMPath=c:\image.wim

:: A single update
set SUpdate=windows10.0-kb3214628-x64-1511.msu

:: ————

:: Make folder
MD %UDates%

:: Make the mount folder
MD %WMount%

:: Command to mount wim to folder
DISM /Mount-Wim /WimFile:%WIMPath% /Index:1 /MountDir:%WMount%

:: Add a single update
:: DISM /image:%WMount% /Add-Package /Packagepath:%UDates%\%SUpdate%

:: Add multiple updates – do not add a specific update
Dism /image:%WMount% /Add-Package /PackagePath:%UDates%\

:: Save changes and unmount
DISM /Unmount-Wim /MountDir:%WMount% /Commit

:: Perform cleanup
DISM /Cleanup-Wim

Screenshot of script running

more info…
PowerShell Method – Multiple Updates

# Add all MSUs/CABs here
$UpdatesPath = "C:\MSUpdates\*"

# Windows will be mounted here
$MountPath = "C:\WINMOUNT"

# Your WIM file
$WimFile = "C:\image.wim"

# Mount command
DISM /Mount-Wim /WimFile:$WimFile /index:1 /Mountdir:$MountPath

# Load updates into array
$UpdateArray = Get-Item $UpdatesPath
ForEach ($Updates in $UpdateArray)
{
# Add update
DISM /image:$MountPath /Add-Package /Packagepath:$Updates
Start-Sleep –s 5
}
Write-Host "Microsoft updates have been added to WIM!"

# Unmount
DISM /Unmount-Wim /Mountdir:$MountPath /commit
DISM /Cleanup-Wim

Screenshot of script running

Batch – Install Windows Updates – Suppress Reboots

email me

This script allows you to cycle through any amount of Windows updates (MSUs), and install them silently while suppressing reboots. I was able to install 180+ updates…without rebooting every few updates.

Code

@ECHO OFF
title Administrative Windows Updates
CLS

setlocal enabledelayedexpansion

:START
REM GO TO UPDATES PATH
C:
CD\MS_Updates\

REM SCAN THROUGH INSTALLING EACH UPDATE SILENTLY
FOR %%# IN (*.msu) DO (
Echo Installing Microsoft Update: %%#
C:\Windows\System32\Wusa.exe “%%#” /quiet /norestart
)
ECHO.

:END
ECHO Windows Update is complete!
PING -n 10 127.0.0.1>nul
EXIT

 

Screenshot of the script running (click image to zoom)

 

Notes

If you think you need to update the Wusa, run this:

windowsupdateagent-7.6-x64.exe /quiet /norestart

And, with very little effort, you could throw in cab files

For %%# in (*.cab) Do (

Echo Installing Microsoft Update: %%#
C:\Windows\System32\dism.exe /online /add-package /packagepath:”%%#” /quiet /norestart
)
Or even MSIs…

For %%# in (*.msi) Do (
Echo Installing Microsoft Update: %%#
C:\Windows\System32\msiexec.exe /i “%%#” /quiet /norestart
)

 

It may be the case your MSUs aren’t installing as intended (error 50, error 85, error 87). This is because the cab itself has to be extracted, and then installed.

Here is the code for that (the ‘expand‘ command does it).

@Echo off
title Microsoft Windows Updates
cls

setlocal enabledelayedexpansion

c:
cd C:\setup\PostSetup\Updates_MS
set Updates=C:\setup\PostSetup\Updates_MS
cd "%~dp0"

goto EXP rem expands files


:EXP
echo Scanning MSUs...
For %%# in (*.msu) Do (
    Echo Expanding: %%#
	Expand -F:* %%# %Updates%	
)
echo.

:INSTALL
for /R "%~dp0" %%# IN (*-KB*.MSU) DO (
call :GETFILE %%~n#
echo Installing Windows Update: KB!update!...
start /wait c:\windows\system32\wusa.exe "%%#" /quiet /norestart
C:\Windows\System32\dism /online /add-package /packagepath:"%Updates%\%%#" /quiet /norestart
)

::QUIT
:END
Echo.
Echo Windows Updates are complete^^!
timeout /t 4 >nul
pause
exit /b 0


:GETFILE
SET "update=%*"
FOR /F "DELIMS=-" %%U IN ("%update:*-KB=%") DO SET "update=%%U"

More about Dism

Pending Reboots in LANDesk, SCCM, etc.

email me

From time to time, you will notice that when you deploy a package from LANDesk or SCCM, it will fail. This failure may be due to a pending reboot.

The reboot status is located in the following reg keys

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SessionManager\PendingFileRenameOperations

Screenshot

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\LANDesk\ManagementSuite\WinClient\VulscanReboot

Screenshot

 

If you’re looking to start a LANDesk deployment, without rebooting, delete the contents in those keys.

 

Alternatively, you can set the agent from the LANDesk management suite to ignore pending reboots.

1 – Open the Agent’s Distribution and Patch settings.
2 – Navigate to Patch-only settings | Install/remove options.
3 – Click the checkbox that says Start repair even if Reboot is already pending.
4 – Click Save.

* If you have individual agent profiles set up, you may just be able to select a non-reboot profile for a specific computer. That is under Task, Properties, Agent settings.

 

Notes

Delete
Delete C:\Program Files (x86)\LANDesk\Shared Files\cbaroot\actions.ini
Delete everything from C:\ProgramData\LANDesk\Data
Delete everything from C:\ProgramData\LANDesk\Policies
Delete everything from C:\ProgramData\LANDesk\Log

Registry
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Control\Session Manager\
Search for “Pending” and delete or set to “2”

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\
If there, Delete “RebootRequired”

Search Registry for UpdateExeVolatile
Change value to “0”

Services
Stop and Start all the LANDesk services

 

All Pending Reboot Keys

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Updates\UpdateExeVolatile

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations2

HKEY_LOCAL_MACHINE\SYSTEM\CurrentSet001\Control\Session Manager\

HKEY_LOCAL_MACHINE\SYSTEM\CurrentSet002\Control\Session Manager\

HKEY_LOCAL_MACHINE\SYSTEM\CurrentSet003\Control\Session Manager\

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Services\Pending\

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired\Mandatory

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\PostRebootReporting

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce\DVDRebootSignal

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootInProgress

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ServerManager\CurrentRebootAttempts

Always Run As Admin

email me

A simple way to force an EXE to run as admin is to use the registry. You just add the path to the specific EXE here:

The Reg Key

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers]
C:\\MyApp\\MyCoolApp.exe“=”~ RUNASADMIN” 



This is essentially what’s happening

 

 

For each application there are three settings that can be applied. The compatibility mode, (Display) Settings and the Privilege Level. One or multiple values can be set (separated by a space).

Compatibility Modes

Value Description
WIN95 Windows 95
WIN98 Windows 98
WIN4SP5 Windows NT 4.0 SP5
WIN2000 Windows 2000
WINXPSP2 Windows XP SP2
WINXPSP3 Windows XP SP3
VISTARTM Vista
VISTASP1 Vista SP1
VISTASP2 Vista SP2
WIN7RTM Windows 7
WINSRV03SP1 Windows Server 2003 SP1
WINSRV08SP1 Windows Server 2008 SP1

 

Display Settings

Value Description
DISABLETHEMES Disable Visual Themes
640X480 Run in 640 x 480 screen resolution
HIGHDPIAWARE Disable display scaling on high DPI settings
256COLOR Run in 256 colors
DISABLEDWM Disable Desktop Composition

 

Privilege Level

Value Description
RUNASADMIN Run program as an administrator

 

If the settings are written into the HKEY_LOCAL_MACHINE part of the registry, the settings cannot be changed by a user that has no local administrative rights.

Windows Server 2008 SP1

VBScript – Encode/Obfuscate Numbers in the Registry

email me

Let’s say you are writing a series of numbers to the registry for desktop management scanning or security purposes (Bitlocker passwords, phone numbers, serial numbers, etc.). In these scenarios, you want the numbers to be available to desktop software, however not be visible by the end-user. A great way to secure these numbers is through simple numeric to alpha translation.

For example,

On Error Resume Next

Set objShell = WScript.CreateObject("WScript.Shell")

'RegValue
numValue = objShell.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\TheNumber\RegValue")
if numValue = "" then WScript.Quit()

Set re = New RegExp
re.Pattern = "[A-Z]"
re.IgnoreCase = True
re.Global = True
hasMatches = re.Test(numValue)

If hasMatches = True Then
wscript.quit
End If

'ENCODING HERE
EncodedValue = (Replace(numValue,"0","Z"))
EncodedValue = (Replace(EncodedValue,"1","K"))
EncodedValue = (Replace(EncodedValue,"2","Y"))
EncodedValue = (Replace(EncodedValue,"3","X"))
EncodedValue = (Replace(EncodedValue,"4","D"))
EncodedValue = (Replace(EncodedValue,"5","O"))
EncodedValue = (Replace(EncodedValue,"6","C"))
EncodedValue = (Replace(EncodedValue,"7","V"))
EncodedValue = (Replace(EncodedValue,"8","S"))
EncodedValue = (Replace(EncodedValue,"9","P"))
EncodedValue = (Replace(EncodedValue,"-","Q"))

'WRITE TO REGISTRY HERE
objShell.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\TheNumber\RegValue",EncodedValue,"REG_SZ"

 

Screenshot 1 – Before script

 

Screenshot 2 – After script

What’s great about this, is that no matter what the length or complexity of the number, it can be translated into something more secure.

So, how do you reverse the process? Easy. Just swap your translation alphanumerics.

For example: 0 Z becomes Z 0.

Example script

On Error Resume Next

Set objShell = WScript.CreateObject("WScript.Shell")

'RegValue
numValue = objShell.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\TheNumber\RegValue")
if numValue = "" then WScript.Quit()

Set re = New RegExp
re.Pattern = "[A-Z]"
re.IgnoreCase = True
re.Global = True
hasMatches = re.Test(numValue)

If hasMatches = False Then
wscript.quit
End If

'DECODING HERE
DecodedValue = (Replace(numValue,"Z","0"))
DecodedValue = (Replace(DecodedValue,"K","1"))
DecodedValue = (Replace(DecodedValue,"Y","2"))
DecodedValue = (Replace(DecodedValue,"X","3"))
DecodedValue = (Replace(DecodedValue,"D","4"))
DecodedValue = (Replace(DecodedValue,"O","5"))
DecodedValue = (Replace(DecodedValue,"C","6"))
DecodedValue = (Replace(DecodedValue,"V","7"))
DecodedValue = (Replace(DecodedValue,"S","8"))
DecodedValue = (Replace(DecodedValue,"P","9"))
DecodedValue = (Replace(DecodedValue,"Q","-"))

'WRITE TO REGISTRY HERE
objShell.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\TheNumber\RegValue",DecodedValue,"REG_SZ"

 

 

PowerShell GUI and Package

email me

PowerShell is definitely the scripting flavor of the week. Thus, I have ended up purchasing several PowerShell books, just to learn the ins and outs of the scripting language. Something I have noticed in 100% of the books…is what they are missing, which is GUI coding and how exactly to create finished EXE packages.

Well, because of this, I bought some scripting tools, you know, the ones that provide a full IDE. They are nice, and even allow you to build some GUI components. But, sadly, a complete package still could not be built. Why not? Hundreds of dollars spent…but you can’t do something as simple as code a PowerShell script and package it with some resource files.
{eye-roll}

So, as a workaround, I figured out how to code my GUI components in PowerShell, package my resource files, and create an EXE. The answer was to use to WinRAR. That’s right, the compression utility. Here is an example.

In this example, I wanted to create a simple tool for scanning and deleting all duplicate files on a computer. And, the tool needed GUI components, was to be coded in PowerShell, and had to be contained in a single EXE file.

First, I created a PowerShell form in my IDE. It has a main function button, access to a log, and an info button. But, as you can see, there is a background (a picture of the friend I was creating it for).

And, I also had an animation that pops up using HTA, which contains a background image and a gif animation.

Using WinRAR, you have the ability to add all files, including your compiled PowerShell script, and then save it as an EXE file. Main.exe is the PowerShell script. Delete_Dupes.exe is the name of the WinRAR EXE.

The magic happens by selecting what to do after the files are extracted. You put your compiled PowerShell file name here:

When you’re done, the EXE file should look like this:

Now, when you click the Delete_Dupes.exe, it extracts the files, and launches the PowerShell script! I will cover the details of the Delete_Dupes.exe in another post.

As a side note, you may wonder…but, what about that ugly icon? Can it be changed? Yes! Using Resource Hacker, you can easily replace the embedded WinRAR icon with one of your own.

Resource Hacker (just open the archive in here)

The updated icon

Notes

This isn’t the first time I have packaged PowerShell scripts into EXEs. If you happen to have a compiler tool, I use EXEScript, you can create a wrapper/launch file that jumps to your PowerShell script. This would permit you to have an EXE that contains all your files, while still being able to do most of your coding in PowerShell. This method offers a little more security and allows you to add/edit the EXE file properties. For example, this is a wrapper I used in EXEScript to jump to a PS script:

@echo on
title SCCM Installation
color 0b
cls
  
set CurDir=%CD%
set PSPath=C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
set Timer=ping -n 2 127.0.0.1
 
%PSPath% -Command "Set-ExecutionPolicy RemoteSigned"
%PSPath% -file "%CurDir%\script.ps1"
%Timer%>nul
exit /b 0

 

Full Solution

Windows 10 BitLocker Commands

email me

Overview

 
BitLocker Drive Encryption is a data protection feature that integrates with the operating system and addresses the threats of data theft or exposure from lost, stolen, or inappropriately decommissioned computers.

BitLocker provides the most protection when used with a Trusted Platform Module (TPM) version 1.2 or later. The TPM is a hardware component installed in many newer computers by the computer manufacturers. It works with BitLocker to help protect user data and to ensure that a computer has not been tampered with while the system was offline.

On computers that do not have a TPM version 1.2 or later, you can still use BitLocker to encrypt the Windows operating system drive. However, this implementation will require the user to insert a USB startup key to start the computer or resume from hibernation. Starting with Windows 8, you can use an operating system volume password to protect the operating system volume on a computer without TPM. Both options do not provide the pre-startup system integrity verification offered by BitLocker with a TPM.

In addition to the TPM, BitLocker offers the option to lock the normal startup process until the user supplies a personal identification number (PIN) or inserts a removable device, such as a USB flash drive, that contains a startup key. These additional security measures provide multifactor authentication and assurance that the computer will not start or resume from hibernation until the correct PIN or startup key is presented.

See wiki

 

Commands and Scripting

 
Show BitLocker Status

Get-BitLockerVolume -MountPoint “C:”

COMMAND: manage-bde -status C:

 

Show BitLocker Password

(Get-BitLockerVolume -MountPoint C).KeyProtector.recoverypassword

COMMAND: manage-bde -protectors C: -get

 

Output BitLocker Password to Text File

(Get-BitLockerVolume -MountPoint C).KeyProtector.recoverypassword | select -Skip 1 | Out-File C:\password.txt

 

Read BitLocker Text File

$password = Get-Content C:\password.txt

 

Removing All Protectors (save as script.cmd)

for /f “skip=2 tokens=2 delims=:” %%f in (‘”C:\Windows\system32\manage-bde.exe -protectors -get c:”‘) do (
echo Removing Protector ID:%%f
echo.
“C:\Windows\system32\manage-bde.exe” -protectors -delete c: -id %%f >nul
)

 

Remove a Single Protector

$BitProtector = Get-BitLockerVolume -MountPoint “C:”
Remove-BitLockerKeyProtector -KeyProtectorId $BitProtector.KeyProtector[1].KeyProtectorId -MountPoint “C:”

 

Initializing TPM

C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -Command “Initialize-Tpm

COMMAND: manage-bde -tpm -turnon

See What is TPM?

 

Enabling TPM – Enable the F1 prompt

enableBitLocker.vbs /on:tpm /l:C:\BitLocker\BitLockerlog.txt
—still looking into a PowerShell method that works

 

Adding Protector for System Drive

C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -Command “Enable-BitLocker -MountPoint C: -EncryptionMethod Aes128 -UsedSpaceOnly -RecoveryPasswordProtector -SkipHardwareTest”

COMMAND: manage-bde -protectors -add C: -tpm

 

 

Enable BitLocker

Enable-BitLocker -MountPoint c: -UsedSpaceOnly -SkipHardwareTest -RecoveryPasswordProtector

COMMAND: manage-bde –on C:

 

Suspend BitLocker

Suspend-BitLocker -MountPoint “C:” -RebootCount 0

COMMAND: manage-bde –pause C:

 

Resume BitLocker

Resume-BitLocker -MountPoint “C:”

COMMAND: manage-bde –resume C:

 

Returning Protector Numerical ID (save as script.cmd)

for /f “skip=2 tokens=2 delims=:” %%g in (‘”C:\Windows\system32\manage-bde.exe -protectors -get c:”‘) do set MyVar=%%g
echo Protector ID:%MyVar%
set MyVar=%MyVar: =%

 

Verify a BitLocker Password was Returned

SET “var=”&for /f “delims=0123456789-” %%i in (“%Pass%”) do set var=%%i
rem if not matching the delims, exit
if defined var (exit)

 

Importing BitLocker Password into Active Directory using Numerical ID

C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -Command “Get-BitLockerVolume -MountPoint C: | Backup-BitLockerKeyProtector -KeyProtectorID ‘%MyVar%’ “

 

Writing BitLocker Password to the Registry (save as script.cmd)

for /f “skip=5 tokens=1 delims=Password ” %%h in (‘”%ThePath%\manage-bde.exe -protectors -get c:”‘) do set Pass=%%h

reg.exe add HKEY_LOCAL_MACHINE\SOFTWARE\BitLockerPW /v PW /t REG_SZ /d %Pass% /f /reg:64

Note: If writing BitLocker PW to the registry, a good practice would be to encrypt/obfuscate it.

Note: There is a good chance if you’re compiling your scripts (in a non-64 bit manner), you may need to change from c:\windows\system32 to %windir%\sysnative. The System32 is reserved for 64 bit applications, while the WOW64 will recognize 32 bit applications.

 

 

NOTES


Note#1
The TPM chip can store numerous BitLocker IDs and passwords. If this isn’t cleared between computer setups, a new BitLocker password will be appended.

Note#2 If you have key rotation enabled, after a BitLocker password has been once, a new one will be created and securely stored [in SCCM or Azure].

Note#3 As newer Windows operating systems are released, TPM 2.0 (or newer) will become a requirement. This may prompt upgrading your fleet.

 

Plan for BitLocker management

Deploy BitLocker management

Manage BitLocker policy for Windows 10 in Intune