DiskCleanup – Remove Previous Windows Versions – PowerShell Module

Over the last few weeks I have upgraded and reinstalled a number of Windows 10 machines and as part of my routine after an upgrade to a later build of Windows 10 I would clean up both the Upgrade files as well as the old version of Windows. The steps to do this involves starting the Disk Cleanup tool, with Administrative credentials, and clicking through the interface in order to clean up the files and save up some of those precious GBs of storage space. After repeating this process a few times in the past week it started to become a bit tedious.

In order to do this is use the command line options that are available with the Disk Cleanup tool, cleanmgr.exe. While it is unfortunately not possible to use this tool directly to clean up specifically the left over files of an Upgrade of Windows 10, it does allow for using the GUI to create a ‘StateFlags’ which is stored in the registry. Using this methodology in combination with Sysinternals Procmon I established where this information was written in the registry and I came up with the following three lines of PowerShell code that allowed me to create the job required to do this job:

New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Temporary Setup Files' -PropertyType 'DWORD' -Force -Name 'StateFlags1337' -Value 0x2
New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Previous Installations' -PropertyType 'DWORD' -Force -Name 'StateFlags1337' -Value 0x2
cleanmgr.exe /SAGERUN:1337

This will code will first create two registry keys and after creating those registry keys, specify the Disk Cleanup application to run with job number 1337. This worked, although unfortunately it is not possible to hide the GUI completely as user interaction might still be required. In certain scenarios you will be prompted to confirm that you really do want to delete the Old Windows Installation files, that includes the warning that deleting those files will not allow you to roll back to an older version of Windows anymore. This also includes the files if you upgrades from Windows 7/8.1 to Windows 10.

As I saw more potential for this method of utilizing the Disk Cleanup tool, I decided to write a proper module that does simplifies the job creation process beyond just cleaning up Previous Windows Installation / Upgrade files. Today I have released the module that does contains the following functions:

  • Get-VolumeCachesKey
  • Get-VolumeCachesStateFlags
  • Remove-WindowsUpgradeFiles
  • Set-VolumeCachesStateFlags

To install the module on your system you can run the following code:

Install-Module DiskCleanup -Verbose


To remove  the Previous Windows Installation / Upgrade files run the following command:

Remove-WindowsUpgradeFiles -Verbose -Confirm:$false


This will both create the job with number 1337 and then execute that job, and the Disk Cleanup Windows will appear on your screen. This process can take a few minutes depending on the speed of your system. The function will wait until all Disk Cleanup windows have been closed and then show a report of the amount of space saved.

Use the Get-VolumeCachesStateFlags cmdlet it is possible to view what settings have been configured:

It is also possible to setup a custom job using the Set-VolumeCachesStateFlags cmdlet, the mandatory parameter -StateFlags will accept any number of Switch parameters. These parameters are dynamically generated based on the available Keys in the registry path:

HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Temporary Setup Files


The module is available at the following online repositories:

I will actively maintain this module, so feel free to leave a comment or feature request in the comments or send in a pull request on GitHub.

All the links mentioned in this article are available below:

Links in this Article
PowerShell Gallery – DiskCleanup
TechNet Script Gallery – DiskCleanup
GitHub – JaapBrasser – DiskCleanup
Sysinternals – Process Monitor


TwitterLinkedInFacebookGoogle+RedditWordPressEmailTumblrPinterestHacker NewsShare

Fix DirectAccess Windows Internal Database – PowerShell Module

I ran into an odd problem with one of the Windows systems at a customer that was running with a very high CPU load. The system is running Windows Server 2012R2 with the DirectAccess role enabled. Upon further investigation it seemed that the SQL Server process that is running the Windows Internal Database for DirectAccess was to blame here:


I did some digging around on the web and found this blog post by Richard Hicks that described the exact problem I was experiencing on the DirectAccess servers:
DirectAccess SQL Server High CPU Usage – Richard Hicks/

In his blog post Richard used the GUI to manually create an additional index to reduce the CPU load on the DirectAccess server. Because I was having this issue on multiple servers I decided to create a PowerShell module based on his instructions. I have finalized the PowerShell module and made it publicly available: FixDaDatabase

The module comes with three cmdlets:

  • Get-DaDatabaseIndexStatus
  • Add-DaDatabaseIndex
  • Remove-DaDatabaseIndex

To get started with the module either download the module from GitHub, the TechNet Script Gallery or the PowerShell Gallery. In order to install the module directly from the PowerShell gallery run the following command:

Install-Module -Name FixDaDatabase -Verbose


First we run Get-DaDatabaseIndexStatus to establish if an Index is already present on the system:



Since the additional Index is not available the Add-DaDatabaseIndex cmdlet can be used to create the Index:



To verify the results of this cmdlet the Get-DaDatabaseIndexStatus cmdlet can be used:

Get-DaDatabaseIndexStatus -Verbose


After creating the additional Index the CPU load of the system dropped down significantly within a minute:


The module is available at the following locations:

If you have any questions or suggestions for this module feel free to leave a comment below or submit a pull request on GitHub.

All the links mentioned in this article are available below:

Links in this Article
PowerShell Gallery – FixDaDatabase
TechNet Script Gallery – FixDaDatabase
GitHub – JaapBrasser – FixDaDatabase
DirectAccess SQL Server High CPU Usage – Richard Hicks
Direct Access: Windows Internal Database (SQL) High CPU Usage – Thomas Vuylsteke

Troubleshooting ADFS: Enabling additional logging

I ran into some issues with one of the ADFS setups at one of my clients and I decided to run some troubleshooting. In order to gather more data on what is happening in your ADFS environment additional logging can be configured. My first step in this process was to check the enabled logging on the system:


After confirming that SuccessAudits and FailureAudits were not configured I added those to the logging results for troubleshooting purposes:

Set-AdfsProperties -LogLevel ((Get-AdfsProperties).LogLevel+'SuccessAudits','FailureAudits')


To ensure the audit results are visible in the event logs we need to ensure that ‘Application Generated’ auditing is enabled, to verify and configure this the following commands can be used:

# Verify 
. $env:\systemroot\system32\AUDITPOL.exe /GET /SUBCATEGORY:"Application Generated"  
# Configure
. $env:\systemroot\system32\AUDITPOL.exe /SET /SUBCATEGORY:"Application Generated" /FAILURE:ENABLE /SUCCESS:ENABLE

Now when an ADFS request is processed there will be logging available in the Application Log and it is easier to pinpoint and troubleshoot issues with your ADFS configuration.
For further analysis, I would recommend the ADFS Diagnostics Module created by the ADFS team, it is available here:
ADFS Diagnostics Module
There are a number of useful cmdlets available in this module that can aid in troubleshooting your ADFS configuration. The Test-AdfsServerHealth cmdlet is particularly useful for finding common misconfigurations:



Additionally the Get-AdfsServerTrace cmdlet simplifies tracing a user request for troubleshooting purposes, for example using the following cmdlet:

Get-AdfsServerTrace -ActivityId 00000000-0000-0000-8000-0080000000d4

In order to fully disable logging again the following code can be executed:

. $env:\systemroot\system32\AUDITPOL.exe /SET /SUBCATEGORY:"Application Generated" /FAILURE:DISABLE /SUCCESS:DISABLE
Set-AdfsProperties -LogLevel ((Get-AdfsProperties).LogLevel| Where-Object {$_ -notmatch 'Audits'})

For more information on this subject and to view the links available in this article:

ADFS Logging additional Links
Under the hood tour of Azure AD Connect Health: AD FS Diagnostics Module
ADFS Diagnostics Module

Working with type accelerators in PowerShell

Type accelerators are a great way in PowerShell to access .Net classes without having to write their full names. In essence they are aliases for .Net classes. If you have worked with PowerShell then you probably have used a type accelerator without knowing.

To get the list of available type accelerators the following command can be executed:


Depending on your version of PowerShell this will generate an output similar to this:

2016-02-26 (2)

Using the Get-TypeAccelerator function we can also display the available Type Accelerators in an easier to view way:


It is useful for quickly defining objects without the complete notation of the class, for example compare the following two examples:

[System.Management.Automation.PSObject]@{'Property'='PowerShell Object'}
[pscustomobject]@{'Property'='PowerShell Object'}

Two type accelerators I use a lot are the [adsi] and [adsisearcher] Type Accelerators, this allows me to access and manipulate Active Dirclectory objects without relying on additional PowerShell modules. Here are some examples of querying Active Directory:


This allows for very short lines of code and used appropriately this can improve the readability of your code. Another few examples of type accelerators are the following:

[regex]::Replace('Type','e','e Accelerator')
[void] (Get-Process)

For more information on the different type and how to use them to define objects, queries or to access data you can view its article on MSDN. For example by executing the following code:

Start-Process -FilePath "http://social.msdn.microsoft.com/Search/en-US?query=$([psobject].Assembly.GetType("System.Management.Automation.TypeAccelerators")::Get.wmisearcher.ToString())"

There are a number of ways to use Type Accelerators in PowerShell, do you already use them and if so what are some of your favorite uses of them. Feel free to discuss them below in the comments section.

PowerShell Fundamentals session at Experts Live on Tour

Earlier this week I was asked to speak at a community event, Experts Live on Tour (Dutch). Experts Live on Tour is series a free community events that cover a number of technical topics where attendees are led through the content by experts from the industry.

During the event we had an enthusiastic group of around 30 IT professionals and I walked through the the fundamentals of PowerShell. It was an engaging crowd so there was a lot of interaction between me and the audience. During the day I walked the crowd through the following topics:

  • PowerShell Fundamentals
  • PowerShell variables and objects
  • PowerShell loops, conditions and flow control
  • PowerShell tips from the field

During the day I mentioned a number of learning resources to, some of the topics I mentioned are listed below:

I have posted the assignments, slides and supporting documentation to GitHub, to view the files click here:

Yesterday a review sheet has been sent out to all attendees, I would love to hear back from you what you liked and disliked about the session. If you did not attend this event but would like to in the future, please let me or the friendly people at Experts Live know. There have been some questions if we have any plans for hosting an event for advanced scripters as well, if you are interested in this make sure that you make this known!

For more information about the topics in this article please visit the links below:

Links in this article
How to learn PowerShell
PowerShell Fundamentals – Course materials – GitHub
Experts Live on Tour