Windows 10 Updates failing with error code 0x80244018

Recently at a client site, I setup a new Windows 10 1809 VM to use as a Citrix XenDesktop template.  Based on the OU the VM was in, it had a GPO configured to make it use WSUS (Windows Server Update Services) for updates.  And I could see according to the WSUS console that the VM was 100% patched.  But in Windows 10, when I would go to Windows Update, Windows 10 was insisting there are still updates to install, but the updates would always fail within a minute or so with an error code of 0x80244018.  I even manually downloaded the updates from the MS Catalog Website and installed them using WUSA, and yet the updates still appeared as required in Windows Update, and it would still fail with an error code of 0x80244018.  I won’t mention the several swear words that followed each time it occurred during my troubleshooting!

As most IT admins know by now, Microsoft got rid of logging Windows Updates to C:\Windows\WindowsUpdate.log and switched to using trace files.  This method of logging is virtually impossible to read in it’s native format.  However, Microsoft has create a PowerShell command that will allow you to export those trace files to a good old fashion text file.  You just need to run Get-WindowsUpdateLog and it will spit out all those trace files to a new plain text file on your desktop called WindowsUpdate.log.

So once I had exported the trace files and opened WindowsUpdate.log with Notepad++, I found this (note – I replaced http with hxxp because WordPress loves to auto-convert to URLs without notice):

2019/07/31 08:44:35.0072804 9140  2220  DownloadManager DO job {CD46C84C-73C5-4002-8EC7-B4ACCE3140E2}, updateId = 9B908E38-BA5D-4462-81E6-C52E06A94B1A.1 failed on HTTP 403 error after retries

2019/07/31 08:44:35.0073096 9140  2220  DownloadManager DO job {CD46C84C-73C5-4002-8EC7-B4ACCE3140E2} failed, updateId = 9B908E38-BA5D-4462-81E6-C52E06A94B1A.1, hr = 0x80190193. File URL = hxxp://tlu.dl.delivery.mp.microsoft.com/filestreamingservice/files/63b17f3e-3249-4b95-a9a1-3f1ca42120ae?P1=1564574112&P2=402&P3=2&P4=hqIxtfL%2f07gwB6yrYcABiDi81z9v%2bBdWhjLyxABoWb6%2fexPpEJOzWczl1UJG03oAbamU3tsIvh50mHrSB1ltlg%3d%3d, local path = C:\Windows\SoftwareDistribution\Download\42dbab2cf910a424dffa836a33879dc0\DesktopDeployment.cab, The response headers = HTTP/1.0 403 Forbidden: body content-type denied  Content-Type: text/html; charset=iso-8859-1″    “

So Windows Update was ignoring WSUS and connecting directly to MS, even though the GPO was set to use my WSUS server – which is troubling to me, but not the the focal point of this writing today.

I took the File URL and pasted it into IE on the Windows 10 VM and got the following error:

2019.07.31 - 09.11.32 - SNAGIT - 0295

Ok… Now I’ve got the real reason for the 403 error.  So we are using a WatchGuard M370 cluster for this customer, and have an HTTP Proxy configured – which incidentally is blocking Windows CAB files (which it does by default).  So it was simply matter of adding *.microsoft.com to the HTTP Proxy Exceptions.

2019.07.31 - 09.29.10 - SNAGIT - 0296

After saving the updated configuration to the cluster, and rebooting the VM, Windows Update successfully downloaded the two outstanding updates and installed them.

So while this doesn’t address why Windows 10 felt the need to pull these updates down directly from the Microsoft servers instead of WSUS, at least now I’m no longer getting error 0x80244018, and I can roll it out to the XenDesktop users.

HOWTO: HTTP boot the HPE Proliant Service Pack ISO DVD using RESTfulAPI to update firmware without messing with WDS or PXE

Most of my customer sites consist of one to four HPE Proliant DL3xx servers running VMware ESXi and an additional HPE Proliant DL3xx running Windows 2012 R2 / 2016. HPE offers some great tools for managing their servers, but unfortunately for smaller organizations, most of HPE’s management tools (and I’m looking squarely at you Insight Control and OneView) take more time to setup and get running correctly then the time you’ll save by installing / updating a small handful of servers manually.  Therefore, I usually don’t deploy these tools to help install OSes or update firmware at my smaller client sites.  I generally just rely on booting the HPE Support Pack for Proliant (SPP) to update firmware, use a USB key with a scripted ESXi install on it for installing ESXi, and utilize WDS to install Windows directly on my Proliants when required.

Prior to HPE Proliant Gen 9 servers, I would PXE boot the Proliant Service Pack using PXELINUX and mount the ISO via NFS.  Then along came Gen 9 with UEFI.  Unfortunately, PXELINUX suffers from a complete lack of support for UEFI.  A couple of times I pestered some of the HPE SPP developers and managers in person while at HPE’s campus in Houston, but they never really showed much interest in explaining or documenting how to get network booting working with the SPP when the server utilized UEFI, so I had pretty much given up on ever getting it to work.

The other day I was playing with the HPE RESTful Interface Tool and decided to try configuring HTTP boot on DL380 Gen10 with the current SPP ISO image (P11740_001_spp-2018.11.0-SPP2018110.2018_1114.38.iso).  Much to my surprise, after modifying only a single configuration file on the ISO image, I was able to successfully boot the current SPP ISO image via HTTP and run a full firmware update on the Gen10 I was playing with.

The nice thing about this method is that because it is all done via HTTP, you don’t have to mess with or disable your WDS (Windows Deployment Services) server to add Linux support (which is what the SPP ISO is based on).  So this is great news for pure Windows shops!  And as a bonus, these steps works with Gen 9 servers too.

So how did I do it?  Before I share that, as always:

Use any tips, tricks, or scripts I post at your own risk.

First, you need to slightly modify the SPP ISO image.  Copy the original SPP ISO image to your web server (i.e. c:\inetpub\wwwroot).

Open the ISO image with your favorite ISO editor and extract \efi\boot\grub.cfg, then open the grub.cfg with a decent text editor (i.e. Notepad++, but definitely not the built-in Windows Notepad).  Scroll down the first menuentry, which will be “Automatic Firmware Update”.  Then copy and paste the following just above that menuentry:

menuentry "HTTP Firmware Update Version 2018.11.0" {
set gfxpayload=keep
echo "Loading kernel..."
linux /pxe/spp2018110/vmlinuz media=net root=/dev/ram0 ramdisk_size=10485760 init=/bin/init  iso1=http://xxx.xxx.xxx.xxx/spp.iso iso1mnt=/mnt/bootdevice hp_fibre cdcache TYPE=MANUAL AUTOPOWEROFFONSUCCESS=no modprobe.blacklist=aacraid,mpt3sas  ${linuxconsole}
echo "Loading initial ramdisk..."
initrd /pxe/spp2018110/initrd.img
}

So your grub.cfg will look like this when you are done:

2018.12.20 - 17.45.17 - SNAGIT - 0027

Adjust the http address (xxx.xxx.xxx.xxx), path, and ISO image name as required for your network, then save the updated grub.cfg and inject it back into the ISO image, over-writing the existing \efi\boot\grub.cfg, and then save the updated ISO image.

Be sure to add the .ISO mime type to your web server so that the ISO file type can be handled correctly.  The command below will work with IIS 8.5 and above to add a new mime type to IIS for .ISO.

C:\Windows\System32\inetsrv\appcmd.exe set config -section:system.webServer/staticContent /+"[fileExtension='iso',mimeType='application/iso']"

Now, you need to install the HPE RESTful Interface Tool on your machine.  The current version at the time of this writing is 2.3.4.0.  Go to the Hewlett Packard Enterprise Support Center and search for “RESTful Interface Tool for Windows”, then download and install the .msi (there is a Linux version available as well there).

Once the HPE RESTful Interface Tool is installed, run it as an Administrator.  Next, you need to connect to your server’s ILO, select the Bios object, set the UrlBootfile Entry and commit the changes.

*** NOTE: Make sure the UrlBootFile entry matches the url of your ISO image that your put on your webserver and specified as the iso1 switch in the grub.cfg entry.

ilorest
login ilo_ip_address -u admin -p password
select Bios.v1_0.0
set UrlBootFile=http://xxx.xxx.xxx.xxx/spp.iso
commit

2018.12.19 - 13.56.41 - SNAGIT - 0003

This takes care of the changes you must make to your Proliant server (keep in mind each server that you want to HTTP boot needs to have this this done).

The next time your server boots, the UrlBootFile change will be applied at the end of POST, then server will automatically reboot and start to POST again.

2018.12.19 - 14.18.08 - SNAGIT - 0005

That’s it – your configuration is all done.  Now when you reboot your server, if you hit F11 for the Boot Menu, you’ll have an entry for HTTP there – select it.

2018.12.19 - 14.20.01 - SNAGIT - 0006

After maybe 30 to 45 seconds (depending on your network speed – I’m using 10GbE), you’ll see the familiar SPP boot menu, but with an extra entry which is set as the default entry.

2018.12.19 - 14.21.25 - SNAGIT - 0009

Select it, and after about a minute (again – I’m using 10GbE) you’ll see the ISO image get mounted.

2018-12-20_17-54-25

If the image fails to mount, verify you are able to download the image you specified as the UrlBootFile from your PC.  If that works, then verify that the grub.cfg is correctly updated, with no typos.  Also – verify your server has 16GB+ of RAM in it, as the grub entry creates a 10GB RAM disk.  You may also need to upgrade the ILO firmware and drivers to current builds (such as 2.61 for ILO4 or 1.39 for ILO5) before using the iLOrest tool.

If you so desire, you could also set the new grub entry to be totally automatic by grabbing the proper switches out of the “Automatic Firmware Update” entry.  I suspect it may also be possible to split the ISO and boot one ISO without the packages folder (so it boots quicker) and mount a second the ISO with the packages folders still there to run the upgrades from.  Just to be clear, I haven’t tested that yet – it’s just a theory at this point.

I have tested this by HTTP booting over a branch office VPN tunnel which tops out at 100Mbps – it took a while for the image to load (I didn’t time it as I was working on other things at the time), but it did eventually load and it successfully updated the remote server.

When the next Support Pack for Proliant is released, all you need to do is update the grub.cfg with the correct paths and copy the updated ISO to your webserver with the same file name you used here.  You shouldn’t need to adjust the UrlBootFile on your servers.

Happy updating!

 

 

HOWTO: Set the creation and modification timestamp on a file via #PowerShell

Recently, I updated one of our internal tool kits, and then packaged it for distribution.  It was a busy day when I updated it, so I didn’t manage to package it on the same day as I had updated / built / compiled it.  Internally, we use the date as the version number of the tool (occasionally suffixed with a letter which indicates my screw-ups in the build process on that given day).  In this particular case, the version number was 2018-11-24b, indicating I updated it on 2018-11-24, and that this was the 3 revision (no suffix, a, then b) that I had created on 2018-11-24 (I found bugs in the first two after testing the packaging).

Because I wasn’t packaging on the same day as I updated it, the time stamps on my archives didn’t match the build date, so I need to change them – all of them!  So I figured up PowerShell and used it instead.  Below are the commands necessary to view and set both the creation and modification timestamps on a file via an elevated PowerShell prompt.

As always – Use any tips, tricks, or scripts I post at your own risk.

To view the file creation timestamp:

(Get-ChildItem “c:\path\file_to_change.wim”).CreationTime

To set the file creation timestamp:

(Get-ChildItem “c:\path\file_to_change.wim”).CreationTime = ’11/24/2018 11:24AM’

To view the file modification timestamp:

(Get-ChildItem “c:\path\file_to_change.wim”).LastWriteTime

To set the file modification timestamp:

(Get-ChildItem “c:\path\file_to_change.wim”).LastWriteTime = ’11/24/2018 11:24AM’

To set the creation and modification timestamp on every single file in a folder:

foreach ($objFile in Get-ChildItem “c:\path\*”) {$objFile.Creationtime = ’11/24/2018 11:24AM’}

foreach ($objFile in Get-ChildItem “c:\path\*”) {$objFile.LastWriteTime = ’11/24/2018 11:24AM’}

 

 

HOWTO: Permanently replace the ugly Windows 10/2016 login screen background and colors for all users with #PowerShell

I can’t stand the default Windows 10 and Windows Server 2016 logon background, and one of the first things I do when I build a new Windows template at a customer site is wipe that default background out!  I typically replace it with a single solid color, and I’m kind of fond of the old blue backgrounds that came with Windows XP (or was it Windows NT 4 – or may Windows 2000, I don’t remember now) as they are easy on the eyes… Anyways – the background color I like and use has a RGB value of 58 110 165.

I used to have a basic batch file to wipe it Microsoft’s stock background out by copying an existing background over from my staging server, but with every iteration of Windows 10 and Windows Server 2016, the path to img100.jpg in C:\Windows\WinSxS changes.  So last night I decided it was time to use some PowerShell to take care of this menace and allow the script to run on multiple platforms and software updates.

I struggled with creating a new solid color background jpg in PowerShell using the RGB value I wanted, but eventually I found some code that someone had posted elsewhere on how to create a gradient jpg, so I snagged it and set the gradient to be same at the end as the beginning, which results in a solid color all the way across.  I’m sure someone with better skills than me could clean this up properly – but this suits my purposes for what I need so I stopped searching for a better way.

So basically what this script does is create a new jpg that is 640×480 in C:\Windows\Web\Wallpaper\Staging, adjusts the accent colors for the current user and the default user profile, finds the path to img100.jpg and replaces it after taking ownership and setting appropriate ntfs rights to it, then clears out the lock screen jpgs using RoboCopy.  The lock screen jpgs are owned by the System account, and Robocopy /mir /zb is the simplest way to wipe them out that I know of without using Sysinternals Suite psexec to involve System account privileges and delete the jpgs.

You definitely need to run this in an elevated PowerShell session too!

As always – Use any tips, tricks, or scripts I post at your own risk.

New-Item -Path "C:\Windows\Web\Wallpaper\Staging" -ItemType "Directory" -Force -Confirm:$false | out-null
Add-Type -AssemblyName System.Drawing
$newbackground = New-Object System.Drawing.Bitmap 640, 480
[System.Drawing.Graphics]::FromImage($newbackground).FillRectangle(
(New-Object System.Drawing.Drawing2D.LinearGradientBrush(
(New-Object System.Drawing.Point(0, 0)),
(New-Object System.Drawing.Point(640, 480)),
[System.Drawing.Color]::FromArgb(58, 110, 165),
[System.Drawing.Color]::FromArgb(58, 110, 165))),
0, 0, $newbackground.Width, $newbackground.Height)
$newbackground.Save('C:\Windows\Web\Wallpaper\Staging\background.jpg',[System.Drawing.Imaging.ImageFormat]::Jpeg)
copy-item -path C:\Windows\Web\Wallpaper\Staging\background.jpg -destination c:\windows\web\wallpaper\background.jpg -force -confirm:$false
REG LOAD HKEY_USERS\ZZZ C:\USERS\DEFAULT\NTUSER.DAT
REG ADD "HKEY_USERS\ZZZ\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Accent" /f /v "StartColor" /t REG_DWORD /d 0xffa66c39
REG ADD "HKEY_USERS\ZZZ\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Accent" /f /v "AccentColor" /t REG_DWORD /d 0xffb51746
REG UNLOAD HKEY_USERS\ZZZ
REG ADD "HKEY_USERS\.DEFAULT\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Accent" /f /v "StartColor" /t REG_DWORD /d 0xffa66c39
REG ADD "HKEY_USERS\.DEFAULT\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Accent" /f /v "AccentColor" /t REG_DWORD /d 0xffb51746
REG ADD "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Accent" /f /v "StartColor" /t REG_DWORD /d 0xffa66c39
REG ADD "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Accent" /f /v "AccentColor" /t REG_DWORD /d 0xffb51746
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Accent" /f /v "DefaultStartColor" /t REG_DWORD /d 0xffa66c39
takeown /f C:\ProgramData\Microsoft\Windows\SystemData /a /r /d y
takeown /f C:\Windows\Web\Screen\img100.jpg /a
icacls C:\Windows\Web\Screen\img100.jpg /grant Administrators:F
$lockscreen = "C:\ProgramData\Microsoft\Windows\SystemData\S-1-5-18\ReadOnly\LockScreen_Z"
$tempfolder = "C:\ProgramData\Microsoft\Windows\SystemData\S-1-5-18\ReadOnly\LockScreen_Temp"
$img100 = Get-ChildItem C:\Windows\WinSxS -Recurse -Include img100.jpg
write-host $img100
takeown /f $img100 /a
icacls $img100 /grant Administrators:F /q
copy-item -path c:\windows\web\wallpaper\background.jpg -destination $img100 -force -confirm:$false | out-null
copy-item -path c:\windows\web\wallpaper\background.jpg -destination C:\Windows\Web\Wallpaper\Windows\BlueBackground.jpg -force -confirm:$false | out-null
copy-item -path c:\windows\web\wallpaper\background.jpg -destination C:\Windows\Web\Screen\img100.jpg -force -confirm:$false | out-null
New-Item -Path $tempfolder -ItemType "Directory" | out-null
Robocopy $tempfolder $lockscreen /zb /mir /njh /njs
Remove-Item -Path $tempfolder -force -confirm:$false | out-null

 

HOWTO: #PowerShell script to download, extract and add #SysinternalsSuite to the path

I absolutely love Microsoft’s Sysinternals Suite – it’s an amazing set of tools for troubleshooting and tweaking Windows machines.  Heck – there isn’t a day goes by that I don’t use at least one of the tools out of the suite.  I generally try to download, extract and add the suite to the path of any computer I touch.

This morning while building a new 2016 template for a customer, I realized I had missed downloading and adding it to the path, but the VM was in a firewalled VLAN and unable to reach my staging and support server – so I couldn’t just grab the extracted directory from my staging server.  This got me to thinking there must be a simple way to use a cli or script to download, extract, and add the extracted folder to the computer’s path.  So I took 30 minutes and wrote one.

Basically, this script can be cut and pasted into an elevated PowerShell session, and it will grab the most recent SysinternalsSuite.zip from Microsoft, extract the .zip to C:\Program Files\SysinternalsSuite, and then add C:\Program Files\SysinternalsSuite to the computer’s path if it does not already exist in the path.

I’ve tested this with Windows 7, Windows 10 (1803), Windows Server 2012 R2 and Windows Server 2016.

As always – Use any tips, tricks, or scripts I post at your own risk.

Import-Module BitsTransfer
$url_zip = "https://download.sysinternals.com/files/SysinternalsSuite.zip"
$output_path = "C:\Program Files\SysinternalsSuite"
$output_zip = $output_path + '\SysinternalsSuite.zip'
Remove-Item -Path $output_path\*.* -force -confirm:$false
New-Item -Path $output_path -ItemType "Directory" -Force -Confirm:$false | out-null
Start-BitsTransfer -Source $url_zip -Destination $output_zip
Add-Type -AssemblyName System.IO.Compression.FileSystem
function Unzip
{
param([string]$zipfile, [string]$outpath)
[System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath)
}
Unzip $output_zip $output_path
Remove-Item -Path $output_zip -force -confirm:$false
$oldpath = (Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment" -Name PATH).path
If ($oldpath -NotLike "*SysinternalsSuite*") {
$newpath = "$oldpath;$output_path"
Set-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment" -Name PATH -Value $newPath
}
$writtenpath = (Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment" -Name PATH).path
write-host $writtenpath

 

 

HOWTO: Manually uninstall Citrix StoreFront after a 1603 MSI Installer error during an upgrade or uninstall (#Citrix #StoreFront #msiexec)

Many of my clients utilize Citrix XenDesktop or XenApp and thus Citrix StoreFront.  Once it is initially configured and running, things are generally pretty smooth going.  But when it comes time to perform in-place upgrades of Citrix StoreFront, sometimes things get a bit hairy and go off track, usually ending up with a dreaded 1603 MSI installer error.  Then you are royally screwed because the StoreFront installation is half installed (or half uninstalled if you are an optimist) and you can’t repair, reinstall, or even uninstall using normal methods.  Below are the notes I’ve developed for myself and my support team to manually uninstall StoreFront should the need arise – which it does, often.

2017-02-21-19-14-07-snagit-0020

These notes are based on single server stand alone installs of Citrix StoreFront versions 2.6.0.5031, 3.0.1.55 , and 3.6.0.33 (as in I’ve used these notes to manually uninstall those versions before).  I have used these notes on XenApp 6.5 servers and on XenDesktop 7.x controllers without any issues.  Your mileage may vary though.

As always – Use any tips, tricks, or scripts I post at your own risk.

**Warning** Reboot and take a VM snapshot of the StoreFront server before doing anything else.  A reboot is a requirement before doing anything with StoreFront, it doesn’t matter if you are doing an install / upgrade, or are already screwed and need to manually uninstall – reboot before continuing!!!  And if you do not reboot – YOU WILL GET ERRORS that will prevent the instructions below from working.

Immediately after you have rebooted, open an elevated Command Prompt and remove all thumbs.db files on the StoreFront server which can be locked opened by Windows Explorer and cause the uninstaller to fail:

c:
cd \
del /s thumbs.db

2017-02-21-19-24-22-snagit-0022

Next, verify that the HTML5 Client is actually installed on the machine, otherwise the uninstaller will likely fail later on.

msiexec /i "C:\Program Files\Citrix\Receiver StoreFront\Features\HTML5Client\template\HTML5Installer.msi"

If you get a repair / remove Windows Installer dialog box, then it is installed and you can just exit the installer, otherwise install using the default settings.

Open the StoreFront MMC, and if it allows you (which it likely won’t), delete all your stores.

Open Add/Remove Programs and uninstall the Citrix Receiver if it is installed.

Open an elevated Powershell console.  Add the Delivery Services Framework snapin,  remove all the Feature Instances, then confirm they are all removed.

**Note – only add the single snapin listed below, otherwise you potentially will end up with files locked open during the removal process, which can cause the removal to fail**

### Add the Citrix Delivery Services Framework Powershell Snapin
add-pssnapin Citrix.DeliveryServices.Framework.Commands

### Remove all DS FeatureInstances
Remove-DSFeatureInstance -all -confirm:$false

### Verify all FeatureInstances are deleted - you should see just {} listed
Get-DSFrameworkController

### If any FeatureInstances are still listed, remove manually them with the next line, otherwise skip to Uninstall-DSFeatureClass
remove-dsfeatureinstance -featureinstanceid feature_name

2017-02-21-19-35-01-snagit-0025

Stop the Storefront services if they are still running before continuing.

Close Powershell

**Note – it is very important you close the PowerShell console at this point and reopen a new one before continuing below and attempting to remove StoreFront’s Feature Classes, otherwise the removal of the Feature Classes will fail**

Open a new elevated Powershell console (see warning above).  Add just the Delivery Services Framework snapin,  remove all the Feature Classes, then confirm they are all removed.

###Add the Citrix Delivery Services Framework Powershell Snapin
add-pssnapin Citrix.DeliveryServices.Framework.Commands

###Remove all FeatureClasses
Uninstall-DSFeatureClass -all -confirm:$false

###Verify all Feature Classes have been removed - you should only see {} listed
Get-DSFrameworkController

2017-02-21-19-39-03-snagit-0026

If there are no DSFeatureClasses are still listed, skip to Citrix.DeliveryServices.UninstallUtil.exe below.  Otherwise, some extra manual cleanup is going to be required.  Using your favorite text editor (Notepad++ in my case), open the Framework.xml file (I usually just run the following from an elevated command prompt.

start notepad++ "C:\Program Files\Citrix\Receiver StoreFront\Framework\FrameworkData\Framework.xml"

Within Notepad++, search for the tag “<Type>” to get all the guid’s of any remaining Feature Classes.

Back in the elevated Powershell console, repeatedly run the Uninstall-DSFeatureClass for each <Type> guid you found in the Framework.xml:

Uninstall-DSFeatureClass -Type {guid}

Run the uninstall for each guid one at a time – if you get an error, don’t worry about it, skip it and continue on with the next one.  Once you have gone through all of the guids, run:

Uninstall-DSFeatureClass -all -confirm:$false
Get-DSFrameworkController

Verify all DSFeatureClasses have now been removed.  You may need to repeat the above three steps a few times to completely remove all the DSFeatureClasses due to dependencies within them.

**note – don’t forget to reload/refresh Framework.xml in your text edit of choice if you need to go back and do it again to the list of the remaining DS Feature Classes**

Once all DS Feature Classes have been removed, close PowerShell and open an elevated Command Prompt and run Citrix.DeliveryServices.Install.Uninstall.exe.

C:\ProgramData\Citrix\DeliveryServicesUninstall\UninstallUserInterface\Citrix.DeliveryServices.Install.Uninstall.exe

2017-02-21-19-41-51-snagit-0028

StoreFront should successfully uninstall for you now and disappear from Add/Remove programs.  Reboot the machine from the elevated command prompt:

shutdown /f /r /t 0

After logging back in, open an elevated Command Prompt and cleanup any leftover folders by running:

rd /q /s "C:\ProgramData\Citrix\DeliveryServicesUninstall"
rd /q /s "C:\Program Files\Citrix\Receiver StoreFront"

Don’t worry if you get a “The system cannot find the file specified” error message – that just means the folder has already been removed or doesn’t exist anymore.

Finally, using Windows Explorer navigate to C:\Inetpub\wwwroot and verify the Citrix directory has been removed – if it has not been removed, manually check it’s contents for anything you need to keep and then delete C:\Inetpub\wwwroot\Citrix.

You should now be ready to install a fresh version of StoreFront.

HOWTO: Send “Shift + F10” to a remote #VMware / #vPro console over #RDP

We typically do a lot of our work at client locations over RDP to a server that resides on-prem in the client’s data center.  We then use that on-prem server as a jump server to manage other systems that reside on-prem and for the most part it works well except for the occasion keyboard combo press that just won’t go through to the client machine we are remoted into via the RDP jump server.  This is particularly a problem is when we are deploying Windows images to machines, which we do either via Intel’s vPro KVM controls (if it is physical) or via VMware Console (if it is virtual).  Occasionally the Windows machine will fail to boot during the specialize phase of sysprep, and we need to troubleshoot the issue.

If we were physically sitting in front of the machine, the process would be pretty simple – hit Shift + F10 and a command prompt pops open, and from there you navigate to C:\Windows\Panther and access the sysprep logs using Notepad.  But in our case, because we are utilizing a jump server via RDP to access the console (either vPro or VMware), Shift + F10 is being intercept by the jump server and not passed on to the vPro KVM session or the VMware Console, which means we can’t get to a command prompt to start troubleshooting.  When this happens, we need to disconnect from the RDP session, and use either RealVNC Plus (for the vPro console) or the VMware client directly from our local machines over VPN, which in some cases is deathly slow at best.

After getting stuck the other day having to troubleshoot a sysprep error over VPN using vPro instead of RDP using vPro, I decided there had to be a way to script a hotkey to send Shift + F10 to the console via RDP.  Unfortunately, I didn’t find anything readily available, so I scripted my own using AutoIt, which I then compiled into an .exe and digitally signed with my code signing certificate.

Basically the script searches for a window that has a title of “Intel(r) AMT KVM – VNC Viewer Plus” or a window that has a title that contains ” on ” (as in Windows7 on ESXiHost” and makes the first instance it finds the active window, then sends a Shift + F10 to the window.

Now when I have to send a Shift + F10 to a remote console during troubleshooting, I simply run the correct executable on our RDP jump servers and up comes the command prompt in the remote console!

Below are the two AutoIt scripts and further down are the two compiled .exe files.

As always – Use any tips, tricks, or scripts I post at your own risk.

Code for Intel(r) AMT KVM – VNC Viewer Plus:

$Title = "Intel(r) AMT KVM - VNC Viewer Plus"
WinWait ($Title)
WinActivate ($Title)
Send ("+{F10}")
Sleep (100)
Exit

Code for VMware Console:

Opt("MouseCoordMode", 0)
Opt("WinTitleMatchMode", 2)
$Title = "[REGEXPTITLE:(?i)(.* on .*)]"

WinWait ($Title)
WinActivate ($Title)

MouseClick ( "right",9,88,1 )
Send ("+{F10}")
Sleep (100)
Exit

Already compiled and digitally signed AutoIT executables:

SendShiftF10toVMware
SendShiftF10tovPro

HOWTO: Fix Windows Server 2016 BSOD Stop 0x00000133 after a failed Cumulative Update installation (#WindowsServer2016 #BSOD #Microsoft)

This morning I logged into my HPE Proliant DL60 which is running Windows Server 2016 (1607) and noticed it wanted to install KB4093119, which is the “2018-04 Cumulative Update for Windows Server 2016 for x64-based Systems (KB4093119)”.  When I was done doing what I had originally logged in for, I told the update to install and reboot.  After many reboots (I don’t have an LCD on the DL60, but it’s here in my office so I can tell every time it reboots by the fans), I figured something was wrong and hopped on the ILO to see what was going on where I was greeted by a BSOD loop – STOP 0x00000133 (DPC WATCHDOG VIOLATION).  After troubleshooting (I couldn’t even get it to boot into the current build of Microsft DaRT as it too would cause a BSOD), I decided to make a Windows Server 2016 installation USB key from the setup DVD using Rufus.  (I could have booted off the DVD ISO image via the ILO, but the ILO emulates USB 2 as opposed to the physical USB 3 ports in the server, so it would have been much slower).  I copied the boot.wim to my C: drive and injected the most recent driver pack into it from the current HPE Support Pack for Proliant (in the root of the HPSPP DVD, called \WIN_DRV) before copying the wim back to the USB key.

I then booted off the USB key and when the Windows Server 2016 Setup Window opened, I hit Shift + F10 to open a command prompt.  I deleted C:\Windows\winsxs\pending.xml then ran “wpeutil reboot“.  As soon as the F9 to F12 function keys became available in the Proliant POST screen, I hit F11, which eventually brought me to the Proliant boot menu.  Here I selected “Windows Boot Manager” and then immediately started hitting F8 to get to the Windows boot options.  This allowed me to select “Last Known Good Configuration”, which allowed the server to boot into Windows without a Stop 0x00000133 (note – selecting just “Last Known Good Configuration”, or deleting just C:\Windows\winsxs\pending.xml won’t help – I found you must do both).

I retried the Windows Update a couple of times only to have the same thing happen again and again, so I followed the above steps again and again to get Windows Server 2016 running again.  Then I Googled the KB number (KB4093119) and went to the Microsoft Support article about it.  At the bottom of the support article, under “How to get this update” is a link to the stand-alone installation package on the Microsoft Update Catalog website.  This allowed me to download the .msu for KB4093119, which I saved to C:\DL\UPDATES as KB4093119.msu.

I rebooted once again off the Windows Server 2016 installation USB key.  When the Windows Server 2016 Setup Window opened, I hit Shift + F10 to open a command prompt.  In the command prompt, I ran the following two commands:

md c:\temp
dism /image:c:\ /add-package /packagepath:c:\dl\updates\KB4093119.msu /scratchdir:c:\temp

Once dism finished successfully, I rebooted the server with “wpeutil reboot

Windows Server 2016 finally booted successfully with the Cumulative Update installed, and I did another check for updates – there were no updates left to install.  I suspect these same steps would work on a Windows 10 machine that is having similar issues – although I don’t know if “Last Known Good Configuration” is an option with the most current version of Windows 10.

As always – Use any tips, tricks, or scripts I post at your own risk.

HOWTO: Enable Jumbo Frames in Windows 2012R2 VMs via #PowerShell

Cleaning up my Inbox, I found this nugget that I had sent to myself and I figured I would share… For reasons that now escape me, a few months ago I had the need to enable Jumbo Frames inside of several VMs (ESXi 6.x). Sure, I could have used the mouse and the Network Control panel to do so, but why wear out the ball on my trackball needlessly when I had a ton of HP keyboards laying about that I could abuse instead… So, off to PowerShell!

Basically, open an Administrative PowerShell and run one of these three sets of commands depending on the type of vNIC you have.

For the E1000E:

$NICNameE1000E = Get-NetAdapter | Where-Object { $_.InterfaceDescription –Like "Intel(R) 82574L Gigabit Network Connection" } | Select -expand nameSet-NetAdapterAdvancedProperty -Name $NicNameE1000E –DisplayName "Jumbo Packet" –DisplayValue "9014 Bytes"

For the E1000:

$NicNameE1000 = Get-NetAdapter | Where-Object { $_.InterfaceDescription –Like "Intel(R) PRO/1000 MT Network Connection" } | Select -expand nameSet-NetAdapterAdvancedProperty -Name $NicNameE1000 –DisplayName "Jumbo Packet" –DisplayValue "9014 Bytes (Alteon)"

For the VMXNET3:

$NicNameVMXNet = Get-NetAdapter | Where-Object { $_.InterfaceDescription –Like "vmxnet3 Ethernet Adapter" } | Select -expand nameSet-NetAdapterAdvancedProperty -Name $NicNameE1000 –DisplayName "Jumbo Packet" –DisplayValue "Jumbo 9000"

As always – Use any tips, tricks, or scripts I post at your own risk.

HOWTO: Approve just the #WSUS updates that are needed using #PoshWSUS and #PowerShell on a schedule

Recently we deployed a new “do-all, be-all” server (AD, WSUS, etc) to a small client with very poor bandwidth availability.  Just allowing WSUS to auto-approve every published update across all categories and all select products just wasn’t an option (and really shouldn’t be anyways) because it would have taken a month to download them over 3Mbps DSL.  So I wanted to only approve and download those updates that were needed, as opposed to WSUS built-in process of automatic approve everything in a classification or product then immediately trying to download it.

For a bit more background information, typically we configure WSUS at our smaller “hands off clients” to check for new updates at 4 am daily (although I’m considering switching to manual synchronization and using PowerShell to invoke the check on a schedule that is more “robost” shall we say.  This gives us about a day to vet the basic updates on our own production system (which is typically close in configuration to our smaller “hands off clients”) before the updates auto-approve after synchronization at the client locations.

In the past I have played with the native Windows Server Update Services PowerShell cmdlets, but lets be honest, they are only about half baked and certainly not ready for enterprise IT production (I’m really not sure what Microsoft was thinking).  The inability to auto-accept EULAs is bad.  Even worse is that if there is a EULA waiting to be accepted, Approve-WsusUpdate just pukes, exits, and refuses to acknowledge, and refuses to approve any other updates (even without EULAs on them).  So this means there really is no hands free way provided by Microsoft to auto-approve just the needed updates as they come out…

After some research, I settled on PoshWSUS.  In my honest opinion however, it is not well documented or supported (but it is good given the resources the author likely has at his disposal)…  It took me 4 hours of scouring Google and trial and error to come up with this basic script, which simply looks at all the needed updates and approves them, in the fewest lines of PowerShell possible.  In the end I had to mash together both the native WSUS PowerShell cmdlets and the PoshWSUS cmdlets to make this work, but it does work (so far anyways).

So, download PoshWSUS_2_3_1_0.zip from GitHub, drop it in C:\Windows\System32\WindowsPowerShell\v1.0\Modules and lets go…

First of all, we need to find just updates that are needed – err – rather **ALL** the updates that are needed.  I didn’t find a way in PoshWSUS to do this, but the native WSUS cmdlets let you do this.  Great – but you can’t pipe these updates (directly out of Get-WsusUpdate) into PoshWSUS’s Approve-PSWSUSUpdate, and I couldn’t find any way to get all needed updates out of Get-PSWSUSUpdate (which can pipe to Approve-PSWSUSUpdate), so I needed to get creative…  Get-PSWSUSUpdate, using a piped Where will allow you to select by the UpdateId, and Get-WsusUpdate will output UpdateId…  Hmmm….

Now – how to get the UpdateId from Get-WsusUpdate to Get-PSWSUSUpdate…  How about by piping the UpdateId via >> to a text file, then use foreach to read that text file into Get-PSWSUSUpdate, which then pipes to Approve-PSWSUSUpdate…  It’s ugly, it’s slow, but hey it works, and should only take a minute or two to run even on the heaviest of Patch Tuesdays…  And along the way, the text file needs cleaned up before being fed into Get-PSWSUSUpdate.

So here is the entire process (save this script as C:\Windows\WSUS_Updates_Approval.ps1)…

Import-Module PoshWSUS
$DNSDomainName=$env:userdnsdomain
$ThisComputersFQDN = "$env:computername"+"."+"$DNSDomainName"
Connect-PSWSUSServer -WsusServer $ThisComputersFQDN -Port 8530
$UpdateIDFile = "C:\Windows\Temp\UpdateIDFile.txt"
If (Test-Path $UpdateIDFile){Remove-Item $UpdateIDFile}
Get-WsusUpdate -Approval Unapproved -Status Needed | Select-Object UpdateId >> $UpdateIDFile
(Get-Content $UpdateIDFile| Select-Object -Skip 3) | Set-Content $UpdateIDFile
(Get-Content $UpdateIDFile| Foreach {$_.TrimEnd()}) | Set-Content $UpdateIDFile
$Groups = Get-PSWSUSGroup -Name 'All Computers'
foreach ($NewUpdateID in get-content $UpdateIDFile) {Get-PSWSUSUpdate | Where {$_.UpdateID -eq "$NewUpdateID"} | Approve-PSWSUSUpdate -Action Install -Group $Groups -Confirm:$false}

Finally, we just need to schedule this script to run on a regular basis… I typically schedule it to run every 15 minutes.  To do that, run this in an Administrative Command Prompt:

schtasks /create /tn "WSUS Updates Approval" /tr "\"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe\" -ExecutionPolicy RemoteSigned -noprofile -File C:\Windows\WSUS_Updates_Approval.ps1" /sc minute /mo 15 /st 00:02:00  /rp "*" /ru "%userdomain%\%username%"

As always – Use any tips, tricks, or scripts I post at your own risk.