Guest User

Start-WindowsCleanup

a guest
Jun 16th, 2020
52
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Function Start-WindowsCleanup
  2. {
  3. <#
  4. .SYNOPSIS
  5. Cleans-up a system clutter and reclaims disk space.
  6.  
  7. .DESCRIPTION
  8. Cleans-up multiple areas of the Windows file system for both the current running user and the global system.
  9. Sets the StateFlags property on the VolumeCache subkeys in the registry and runs the Windows Disk Clean-up utility in advanced mode as a .NET process.
  10. Removes the StateFlags property on the VolumeCache subkeys once the Windows Disk Clean-up utility has completed.
  11. Cleans-up the WinSxS Component Store by removing superseded component files and resetting the image base.
  12. Logs all clean-up actions to a transcript that is saved in the C:\Windows\Temp directory.
  13.  
  14. .PARAMETER Include
  15. Includes user-specific directories, outside of temporary and logging directories, in the clean-up process. The acceptable values for this parameter are: Downloads, RestorePoints, EventLogs, DuplicateDrivers, Chrome, Firefox, IE and Edge.
  16.  
  17. Downloads = Removes all content from all download folders and directories.
  18. RestorePoints = Removes all system restore points.
  19. EventLogs = Removes all event logs and event tracing log files.
  20. DuplicateDrivers = Outputs a Gridview list of any outdated and duplicate drivers for selective removal.
  21. Chrome = Removes all cache, cookie, history and logging directories for the Google Chrome web browser.
  22. Firefox = Removes all cache, cookie, history and logging directories for the Mozilla Firefox web browser.
  23. IE = Removes all cache, cookie, history and logging directories for the Internet Explorer web browser.
  24. Edge = Removes all cache, cookie, history and logging directories for the Microsoft Edge web browser.
  25.  
  26. More than one parameter value may be entered at a time. If, for example, you want to also remove all Restore Points, Event Logs and all content from the Chrome, Firefox and Internet Explorer user and system profile directories, the following values would be passed with the parameter:
  27. -Include 'RestorePoints', 'EventLogs', 'Chrome', 'Firefox', 'IE'
  28.  
  29. .PARAMETER GUI
  30. Outputs a Gridview GUI list of all of the values in the -Include parameter allowing for the selection of items to include in the removal process as opposed to manually entering them.
  31.  
  32. This switch can be used in place of the -Include parameter.
  33.  
  34. .PARAMETER Additional
  35. Removes any user-specific file, folder or directory passed to the parameter when the function is called. This can be a single object or an array of multiple objects.
  36.  
  37. .PARAMETER ComponentCleanup
  38. Removes all superseded components in the component store.
  39.  
  40. .PARAMETER ResetBase
  41. Removes all superseded components in the component store and also resets the image base, further reducing the size of the component store.
  42.  
  43. By default the ResetBase feature is disabled for Windows 10 builds 18362 and above unless the -Force switch is used.
  44.  
  45. .PARAMETER Force
  46. This switch is only processed when the Additional parameter or ResetBase switch is used.
  47.  
  48. When used with the Additional parameter, any objects that contain access control list permissions will be force removed.
  49. When used with ResetBase switch, the ComponentCleanup with Image Base Reset will run on Windows 10 builds 18362 and above.
  50.  
  51. .EXAMPLE
  52. PS C:\> Start-WindowsCleanup
  53.  
  54. This command will clean-up all distribution, logging, temporary content, icon cache databases and thumbnail cache databases.
  55.  
  56. .EXAMPLE
  57. PS C:\> Start-WindowsCleanup -Include Downloads -ComponentCleanup
  58.  
  59. This command will clean-up all distribution, logging, temporary content, icon cache databases and thumbnail cache databases, remove any downloaded items and perform a clean-up of the Component Store.
  60.  
  61. .EXAMPLE
  62. PS C:\> Start-WindowsCleanup -Include 'RestorePoints', 'EventLogs', 'DuplicateDrivers'
  63.  
  64. This command will clean-up all distribution, logging, temporary content, icon cache databases and thumbnail cache databases, remove all system restore points and output a Gridview list of any outdated and duplicate drivers for selective removal.
  65.  
  66. .EXAMPLE
  67. PS C:\> Start-WindowsCleanup -Include 'Downloads', 'RestorePoints', 'EventLogs', 'Chrome', 'FireFox', 'Edge' -Additional 'C:\My Notes', 'C:\Executable', 'D:\MapData' -Force
  68.  
  69. This command will perform six primary clean-up tasks:
  70. 1 - Remove all distribution, logging, temporary content, icon cache databases and thumbnail cache databases.
  71. 2 = Remove any downloaded content.
  72. 3 - Remove all system restore points.
  73. 4 - Remove all event logs and event tracing log files.
  74. 5 - Remove all cache, cookies, logging and temporary files and saved history for Google Chrome, Mozilla FireFox and Microsoft Edge.
  75. 6 - Remove all additionally added objects by bypassing access control list permissions.
  76.  
  77. .EXAMPLE
  78. PS C:\> Start-WindowsCleanup -GUI -ResetBase -Force
  79.  
  80. This command will remove distribution, logging, temporary content, icon cache databases and thumbnail cache databases, output a Gridview GUI list allowing for the selection of additional items to include in the clean-up process, clean-up the Component Store and perform an image base reset even if the Windows 10 build is 18362+ due to the -Force switch being used.
  81.  
  82. .NOTES
  83. The integer value for the StateFlags registry property is randomly created each time the function is run and is not set to a static value.
  84. On Windows 10 builds 18362 and above, the ResetBase switch and 'Update Cleanup' are excluded from the cleanup process due to a current bug in these builds preventing future updates from installing if previous updates have been removed.
  85. On Windows 10 builds 18362 and above, the excluded ResetBase feature can be invoked if used with the Force switch.
  86. When removing outdated and duplicate drivers, ensure the current device driver is functioning properly as you will not be able to roll back the driver for that specific device.
  87. If the removal of outdated and duplicate drivers has been included in the removal process, realize it can take some time for the list of drivers installed on the system to be compiled so just be patient.
  88. #>
  89.  
  90. [CmdletBinding(DefaultParameterSetName = 'Include',
  91. ConfirmImpact = 'High',
  92. SupportsShouldProcess = $true)]
  93. Param
  94. (
  95. [Parameter(ParameterSetName = 'Include',
  96. Mandatory = $true,
  97. Position = 0,
  98. HelpMessage = 'Includes the clean-up of Downloads, Restore Points, Event Logs, Google Chrome, Mozilla Firefox, Internet Explorer and Microsoft Edge.')]
  99. [ValidateSet('Downloads', 'RestorePoints', 'EventLogs', 'DuplicateDrivers', 'Chrome', 'Firefox', 'IE', 'Edge')]
  100. [String[]]$Include,
  101. [Parameter(ParameterSetName = 'GUI',
  102. Mandatory = $true,
  103. Position = 0,
  104. HelpMessage = 'Outputs a Gridview GUI list of all of the values in the -Include parameter allowing for the selection of items to include in the removal process as opposed to manually entering them.')]
  105. [Switch]$GUI,
  106. [Parameter(HelpMessage = 'Removes any user-specific file, folder or directory passed to the parameter when the function is called. This can be a single object or an array of multiple objects.')]
  107. [String[]]$Additional,
  108. [Parameter(HelpMessage = 'Removes all superseded components in the component store.')]
  109. [Switch]$ComponentCleanup,
  110. [Parameter(HelpMessage = 'Removes all superseded components in the component store and also resets the image base, further reducing the size of the component store.')]
  111. [Switch]$ResetBase,
  112. [Parameter(HelpMessage = 'This switch is only processed when the Additional parameter or ResetBase switch is used.')]
  113. [Switch]$Force
  114. )
  115.  
  116. Begin
  117. {
  118. # Check to make sure we are running with administrator permissions.
  119. If (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Warning "This script requires elevated access. Please relaunch Start-WindowsCleanup with administrator permissions."; Exit }
  120.  
  121. # Create helper functions to aid in the clean-up process.
  122. Function Remove-Items
  123. {
  124. [CmdletBinding()]
  125. Param
  126. (
  127. [Parameter(Mandatory = $true,
  128. ValueFromPipeline = $true,
  129. ValueFromPipelineByPropertyName = $true)]
  130. [Alias('FullName', 'PSPath')]
  131. [String[]]$Path,
  132. [Switch]$Force
  133. )
  134.  
  135. Process
  136. {
  137. ForEach ($Item In $Path)
  138. {
  139. $Item = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Item)
  140. If ($PSBoundParameters.Additional)
  141. {
  142. If ($Force.IsPresent)
  143. {
  144. If ($null -eq $Item) { Continue }
  145. $Retries = 5
  146. If ((Get-Item -Path $Item -Force -ErrorAction SilentlyContinue) -is [IO.DirectoryInfo]) { $TAKEOWN = ('TAKEOWN.EXE /F "{0}" /A /R /D Y' -f $Item) }
  147. Else { $TAKEOWN = ('TAKEOWN.EXE /F "{0}" /A' -f $Item) }
  148. Do
  149. {
  150. $RET = $TAKEOWNRET = $ICACLSRET = $ATTRIBRET = $REMRET = $null
  151. Write-Verbose ('Performing the operation "{0}"' -f $TAKEOWN) -Verbose
  152. $TAKEOWNRET = Invoke-Expression $TAKEOWN
  153. $ICACLS = ('ICACLS.EXE "{0}" /INHERITANCE:E /GRANT *S-1-5-32-544:F /T /Q /C /L' -f $Item)
  154. Write-Verbose ('Performing the operation "{0}"' -f $ICACLS) -Verbose
  155. $ICACLSRET = Invoke-Expression $ICACLS
  156. $ATTRIB = ('ATTRIB.EXE -A "{0}" /S /D /L' -f $Item)
  157. Write-Verbose ('Performing the operation "{0}"' -f $ATTRIB) -Verbose
  158. $ATTRIBRET = Invoke-Expression $ATTRIB
  159. Try { Remove-Item -Path $Item -Recurse -Force -Verbose }
  160. Catch { $REMRET = $PSItem.Exception.Message }
  161. $RET = ($TAKEOWNRET + $ICACLSRET + $ATTRIBRET + $REMRET) | Select-String -Pattern 'Access is denied'
  162. }
  163. While ($null -ne $RET -or (--$Retries -le 0))
  164. }
  165. Else
  166. {
  167. Try { Remove-Item -Path $Item -Recurse -Force -Verbose -ErrorAction SilentlyContinue }
  168. Catch [UnauthorizedAccessException], [Management.Automation.ItemNotFoundException] { }
  169. }
  170. }
  171. Else
  172. {
  173. Try
  174. {
  175. If ((Get-Item -Path $Item -Force -ErrorAction SilentlyContinue) -is [IO.DirectoryInfo]) { Get-ChildItem -Path $Item -Recurse -Force -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -Verbose -ErrorAction SilentlyContinue }
  176. Else { Remove-Item -Path $Item -Recurse -Force -Verbose -ErrorAction SilentlyContinue }
  177. }
  178. Catch [UnauthorizedAccessException], [Management.Automation.ItemNotFoundException] { }
  179. }
  180. }
  181. }
  182. }
  183.  
  184. Function Stop-Running
  185. {
  186. [CmdletBinding()]
  187. Param
  188. (
  189. [Parameter(Mandatory = $true,
  190. ValueFromPipeline = $true)]
  191. [String[]]$Name
  192. )
  193.  
  194. Process
  195. {
  196. ForEach ($Object In $Name)
  197. {
  198. $Running = Get-Process | Where-Object -Property Name -Like *$Object*
  199. If (!$Running) { $Running = Get-Service | Where-Object -Property Name -EQ $Object }
  200. $Running | ForEach-Object -Process {
  201. If ($PSItem -is [Diagnostics.Process])
  202. {
  203. If ($PSItem.Name -eq 'explorer')
  204. {
  205. While ((Get-Process -Name explorer).HasExited -eq $false) { Stop-Process -Name explorer -Force -Verbose }
  206. }
  207. Else
  208. {
  209. $Retries = 5
  210. While ($Retries -gt 0 -and ((Get-Process -Name $PSItem.Name -ErrorAction SilentlyContinue).Responding -eq $true))
  211. {
  212. Stop-Process -Name $PSItem.Name -Force -Verbose -ErrorAction SilentlyContinue
  213. Start-Sleep 1
  214. If ((Get-Process -Name $PSItem.Name -ErrorAction SilentlyContinue).Responding -eq $true) { Start-Sleep 5 }
  215. $Retries--
  216. }
  217. }
  218. }
  219. ElseIf ($PSItem -is [ServiceProcess.ServiceController])
  220. {
  221. If ((Get-Service -Name $PSItem.Name -ErrorAction SilentlyContinue).Status -ne 'Stopped')
  222. {
  223. $Retries = 5
  224. While ($Retries -gt 0 -and ((Get-Service -Name $PSItem.Name -ErrorAction SilentlyContinue).Status -ne 'Stopped'))
  225. {
  226. Stop-Service -Name $PSItem.Name -Force -Verbose -ErrorAction SilentlyContinue
  227. Start-Sleep 1
  228. If ((Get-Service -Name $PSItem.Name -ErrorAction SilentlyContinue).Status -eq 'Running') { Start-Sleep 5 }
  229. $Retries--
  230. }
  231. }
  232. }
  233. Else { $null }
  234. }
  235. }
  236. }
  237. }
  238.  
  239. # Assign the local and global paths to their own variables for easier path building.
  240. $GlobalAppData = $Env:APPDATA
  241. $LocalAppData = $Env:LOCALAPPDATA
  242. $RootAppData = "$(Split-Path -Path $LocalAppData)\*"
  243.  
  244. # Generate the StateFlags integer string and set it to its registry property name.
  245. $StateFlags = [Convert]::ToString($(Get-Random -Minimum 1 -Maximum 9999))
  246. $PropertyName = "StateFlags{0:D4}" -f $StateFlags
  247.  
  248. # Assign the name of the transcript log using Unix time.
  249. $Transcript = Join-Path -Path $Env:SystemRoot\Temp -ChildPath "Start-WindowsCleanup_$(Get-Date -Date (Get-Date).ToUniversalTime() -UFormat %s -Millisecond 0).log"
  250.  
  251. # Exclude downloads folders by default.
  252. $ExcludedList = [Collections.Generic.List[String]]@('DownloadsFolder')
  253.  
  254. # If the -Force switch is enabled without the required -Additional parameter or -ResetBase switch, disable it.
  255. If (!$Additional -or !$ResetBase.IsPresent -and $Force.IsPresent) { $Force = $false }
  256.  
  257. # If both the -ComponentCleanup and -ResetBase switches are used, disable ResetBase and only run a Component Store clean-up.
  258. If ($ComponentCleanup.IsPresent -and $ResetBase.IsPresent) { $ResetBase = $false }
  259.  
  260. # If the running system is Windows 10 build 18362 or greater, disable the ResetBase features unless the -Force switch is used.
  261. If ((Get-CimInstance -ClassName Win32_OperatingSystem).BuildNumber -ge 18362 -and $PSBoundParameters.ResetBase -and !$Force.IsPresent) { $ResetBase = $false }
  262.  
  263. # If the ResetBase parameter set name is present, assign the name of the log that will be used for the PowerShell job using Unix time.
  264. If ($PSBoundParameters.ComponentCleanup -or $PSBoundParameters.ResetBase) { $DISMLog = Join-Path -Path $Env:TEMP -ChildPath "DismCleanupImage_$(Get-Date -Date (Get-Date).ToUniversalTime() -UFormat %s -Millisecond 0).log" }
  265.  
  266. # If the running system is Windows 10 build 18362 or greater, disable the cleanup of updates.
  267. If ((Get-CimInstance -ClassName Win32_OperatingSystem).BuildNumber -ge 18362) { $ExcludedList.Add('Update Cleanup') }
  268.  
  269. # Assign the path testing results for the icon and thumbnail caches to their own variables.
  270. $IconCache = @($LocalAppData, (Join-Path -Path $LocalAppData -ChildPath 'Microsoft\Windows\Explorer')) | Test-Path -Filter iconcache*.db
  271. $ThumbnailCache = (Join-Path -Path $LocalAppData -ChildPath 'Microsoft\Windows\Explorer') | Test-Path -Filter thumbcache_*.db
  272.  
  273. # Assign the pre-cleanup storage state to a variable.
  274. $PreClean = (Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object -Property DriveType -EQ 3 | Select-Object -Property @{ Name = 'Drive'; Expression = { ($PSItem.DeviceID) } },
  275. @{ Name = 'Size (GB)'; Expression = { '{0:N1}' -f ($PSItem.Size / 1GB) } },
  276. @{ Name = 'FreeSpace (GB)'; Expression = { '{0:N1}' -f ($PSItem.Freespace / 1GB) } },
  277. @{ Name = 'PercentFree'; Expression = { '{0:P1}' -f ($PSItem.FreeSpace / $PSItem.Size) } } | Format-Table -AutoSize | Out-String).Trim()
  278. }
  279. Process
  280. {
  281. If (!$PSCmdlet.ShouldProcess($Env:COMPUTERNAME, 'Start-WindowsCleanup')) { Break }
  282.  
  283. Clear-Host
  284.  
  285. Start-Transcript -Path $Transcript
  286.  
  287. If ($PSBoundParameters.ComponentCleanup -or $PSBoundParameters.ResetBase)
  288. {
  289. If ($PSCmdlet.ShouldProcess($Env:COMPUTERNAME, 'Remove all superseded components in the component store'))
  290. {
  291. If ($PSBoundParameters.ComponentCleanup)
  292. {
  293. # Start a PowerShell Dism job to clean-up the Component Store.
  294. Write-Verbose "Removing all superseded components in the component store." -Verbose
  295. $DISMJob = Start-Job -ScriptBlock { Param ($DISMLog) Dism.exe /Online /Cleanup-Image /StartComponentCleanup | Out-File -FilePath $DISMLog } -ArgumentList $DISMLog -ErrorAction SilentlyContinue
  296. }
  297. ElseIf ($PSBoundParameters.ResetBase)
  298. {
  299. # Start a PowerShell Dism job to clean-up the Component Store and reset the image base.
  300. Write-Verbose "Removing all superseded components in the component store and resetting the image base." -Verbose
  301. $DISMJob = Start-Job -ScriptBlock { Param ($DISMLog) Dism.exe /Online /Cleanup-Image /StartComponentCleanup /ResetBase | Out-File -FilePath $DISMLog } -ArgumentList $DISMLog -ErrorAction SilentlyContinue
  302. }
  303.  
  304. Do
  305. {
  306. Start-Sleep 5
  307. Get-Content -Path $DISMLog -Tail 3 | Select-String -Pattern '%' | Select-Object -Last 1
  308. }
  309. While ((Get-Job -Id $DISMJob.Id).State -eq 'Running')
  310.  
  311. If ((Get-Job -Id $DISMJob.Id).State -eq 'Completed') { $DISMJob | Remove-Job -ErrorAction SilentlyContinue }
  312.  
  313. $DISMLog | Remove-Items
  314. }
  315. }
  316.  
  317. # The list of initial items that will be cleaned-up.
  318. $RemovalList = [Collections.Generic.List[Object]]@(
  319. (Join-Path -Path $Env:TEMP -ChildPath "\*"),
  320. (Join-Path -Path $RootAppData -ChildPath "Temp\*"),
  321. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Windows\WER\*"),
  322. (Join-Path -Path $RootAppData -ChildPath "Microsoft\Windows\WER\*"),
  323. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Terminal Server Client\Cache\*"),
  324. (Join-Path -Path $RootAppData -ChildPath "Microsoft\Terminal Server Client\Cache\*"),
  325. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Terminal Server Client\Cache\*"),
  326. (Join-Path -Path $Env:SystemRoot -ChildPath "debug\WIA\*.log"),
  327. (Join-Path -Path $Env:SystemRoot -ChildPath "drivers\*"),
  328. (Join-Path -Path $Env:SystemRoot -ChildPath "INF\*.log*"),
  329. (Join-Path -Path $Env:SystemRoot -ChildPath "Logs\CBS\*Persist*"),
  330. (Join-Path -Path $Env:SystemRoot -ChildPath "Logs\DISM\*"),
  331. (Join-Path -Path $Env:SystemRoot -ChildPath "Logs\dosvc\*.*"),
  332. (Join-Path -Path $Env:SystemRoot -ChildPath "Logs\MeasuredBoot\*.log"),
  333. (Join-Path -Path $Env:SystemRoot -ChildPath "Logs\NetSetup\*.*"),
  334. (Join-Path -Path $Env:SystemRoot -ChildPath "Logs\SIH\*.*"),
  335. (Join-Path -Path $Env:SystemRoot -ChildPath "Logs\WindowsBackup\*.etl"),
  336. (Join-Path -Path $Env:SystemRoot -ChildPath "minidump\*"),
  337. (Join-Path -Path $Env:SystemRoot -ChildPath "Panther\UnattendGC\*.log"),
  338. (Join-Path -Path $Env:SystemRoot -ChildPath "Prefetch\*"),
  339. (Join-Path -Path $Env:SystemRoot -ChildPath "security\logs\*.*"),
  340. (Join-Path -Path $Env:SystemRoot -ChildPath "Temp\*"),
  341. (Join-Path -Path $Env:SystemRoot -ChildPath "WinSxS\ManifestCache\*"),
  342. (Join-Path -Path $Env:SystemRoot -ChildPath "*.log"),
  343. (Join-Path -Path $Env:SystemRoot -ChildPath "*.dmp"),
  344. (Join-Path -Path $Env:SystemDrive -ChildPath "*.dmp"),
  345. (Join-Path -Path $Env:SystemDrive -ChildPath "File*.chk"),
  346. (Join-Path -Path $Env:SystemDrive -ChildPath "Found.*\*.chk"),
  347. (Join-Path -Path $Env:SystemDrive -ChildPath "LiveKernelReports\*.dmp"),
  348. (Join-Path -Path $Env:SystemDrive -ChildPath "swsetup\*"),
  349. (Join-Path -Path $Env:SystemDrive -ChildPath "swtools\*"),
  350. (Join-Path -Path $Env:SystemDrive -ChildPath "Windows.old"),
  351. (Join-Path -Path $Env:HOMEDRIVE -ChildPath "Config.Msi"),
  352. (Join-Path -Path $Env:HOMEDRIVE -ChildPath "inetpub\logs\LogFiles\*"),
  353. (Join-Path -Path $Env:HOMEDRIVE -ChildPath "Intel\*"),
  354. (Join-Path -Path $Env:HOMEDRIVE -ChildPath "PerfLogs\*")
  355. )
  356.  
  357. Switch ($PSCmdlet.ParameterSetName)
  358. {
  359. 'GUI'
  360. {
  361. # If the GUI parameter set name is present, create an output Gridview list allowing for the selection of items to include in the removal process.
  362. $IncludeList = [Ordered]@{
  363. Downloads = 'Removes all content from all download folders and directories.'
  364. RestorePoints = 'Removes all system restore points.'
  365. EventLogs = 'Removes all event logs and event tracing log files.'
  366. DuplicateDrivers = 'Outputs a Gridview list of any outdated and duplicate drivers for selective removal.'
  367. Chrome = 'Removes all cache, cookie, history and logging directories for the Google Chrome web browser.'
  368. Firefox = 'Removes all cache, cookie, history and logging directories for the Mozilla Firefox web browser.'
  369. IE = 'Removes all cache, cookie, history and logging directories for the Internet Explorer web browser.'
  370. Edge = 'Removes all cache, cookie, history and logging directories for the Microsoft Edge web browser.'
  371. }
  372. $IncludeList = $IncludeList.Keys | Select-Object -Property @{ Label = 'Name'; Expression = { $PSItem } }, @{ Label = 'Description'; Expression = { $IncludeList[$PSItem] } } | Out-GridView -Title "Select items to include in the clean-up process." -PassThru
  373. If ($IncludeList) { $IncludeList = $IncludeList.GetEnumerator().Name }
  374. Break
  375. }
  376. Default { $IncludeList = $Include; Break }
  377. }
  378.  
  379. Switch ($IncludeList)
  380. {
  381. 'Downloads'
  382. {
  383. # Before adding downloads content to the removal list, verify the parameter value was not issued by accident.
  384. Add-Type -AssemblyName PresentationFramework
  385. $Verify = [Windows.MessageBox]::Show('Are you sure you want to remove all downloads?', 'Verify Removal', 'YesNo', 'Question')
  386. Switch ($Verify)
  387. {
  388. Yes { [Void]$ExcludedList.Remove('DownloadsFolder'); Break }
  389. No { Break }
  390. Default { Break }
  391. }
  392.  
  393. # If verified, add all download folders and directories to the removal list.
  394. If ($ExcludedList -notcontains 'DownloadsFolder')
  395. {
  396. $RemovalList.Add((
  397. (Join-Path -Path $RootAppData -ChildPath "Downloads\*"),
  398. (Join-Path -Path $LocalAppData -ChildPath "Downloads\*"),
  399. (Join-Path -Path $Env:SystemDrive -ChildPath "Users\Administrator\Downloads\*"),
  400. (Join-Path -Path (Get-ItemPropertyValue -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" -Name "{374DE290-123F-4565-9164-39C4925E467B}" -ErrorAction SilentlyContinue) -ChildPath "\*")
  401. ))
  402. }
  403. }
  404. 'RestorePoints'
  405. {
  406. # Delete all system shadow copies if the -Include parameter with the 'RestorePoints' value is used.
  407. If (Get-WmiObject -Class Win32_ShadowCopy)
  408. {
  409. Get-WmiObject -Class Win32_ShadowCopy | ForEach-Object -Process {
  410. Write-Verbose ('Performing the operation "Delete ShadowCopy" on target "{0}"' -f $PSItem.ID) -Verbose
  411. $PSItem.Delete()
  412. }
  413. }
  414. }
  415. 'EventLogs'
  416. {
  417. # Delete all event logs and event tracer log files if the -Include parameter with the 'EventLogs' value is used.
  418. Get-WinEvent -ListLog * | Where-Object { $PSItem.IsEnabled -eq $true -and $PSItem.RecordCount -gt 0 } | ForEach-Object -Process {
  419. Write-Verbose ('Performing the operation "ClearLog" on target "{0}"' -f $PSItem.LogName) -Verbose
  420. [Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession.ClearLog($PSItem.LogName)
  421. } 2> $null
  422. }
  423. 'DuplicateDrivers'
  424. {
  425. # Delete all outdated and duplicate drivers if the -Include parameter with the 'DuplicateDrivers' value is used.
  426. Write-Verbose "Compiling a list of any outdated and duplicate system drivers." -Verbose
  427. $AllDrivers = Get-WindowsDriver -Online -All | Where-Object -Property Driver -Like oem*inf | Select-Object -Property @{ Name = 'OriginalFileName'; Expression = { $PSItem.OriginalFileName | Split-Path -Leaf } }, Driver, ClassDescription, ProviderName, Date, Version
  428. $DuplicateDrivers = $AllDrivers | Group-Object -Property OriginalFileName | Where-Object -Property Count -GT 1 | ForEach-Object -Process { $PSItem.Group | Sort-Object -Property Date -Descending | Select-Object -Skip 1 }
  429. If ($DuplicateDrivers)
  430. {
  431. $DuplicateDrivers | Out-GridView -Title 'Remove Duplicate Drivers' -PassThru | ForEach-Object -Process {
  432. $Driver = $PSItem.Driver.Trim()
  433. Write-Verbose ('Performing the action "Delete Driver" on target {0}' -f $Driver) -Verbose
  434. Start-Process -FilePath PNPUTIL -ArgumentList ('/Delete-Driver {0} /Force' -f $Driver) -WindowStyle Hidden -Wait
  435. }
  436. }
  437. }
  438. 'Chrome'
  439. {
  440. # Add all Google Chrome cache, cookie, history and logging directories if the -Include parameter with the 'Chrome' value is used.
  441. 'chrome' | Stop-Running
  442. $RemovalList.Add((
  443. (Join-Path -Path $RootAppData -ChildPath "Google\Chrome\User Data\Default\Cache*\*"),
  444. (Join-Path -Path $LocalAppData -ChildPath "Google\Chrome\User Data\Default\Cache*\*"),
  445. (Join-Path -Path $RootAppData -ChildPath "Google\Chrome\User Data\Default\Cookies\*"),
  446. (Join-Path -Path $LocalAppData -ChildPath "Google\Chrome\User Data\Default\Cookies\*"),
  447. (Join-Path -Path $RootAppData -ChildPath "Google\Chrome\User Data\Default\Media Cache\*"),
  448. (Join-Path -Path $LocalAppData -ChildPath "Google\Chrome\User Data\Default\Media Cache\*"),
  449. (Join-Path -Path $RootAppData -ChildPath "Google\Chrome\User Data\Default\Cookies-Journal\*"),
  450. (Join-Path -Path $LocalAppData -ChildPath "Google\Chrome\User Data\Default\Cookies-Journal\*")
  451. ))
  452. }
  453. 'Firefox'
  454. {
  455. # Add all Mozilla Firefox cache, cookie, history and logging directories if the -Include parameter with the 'Firefox' value is used.
  456. 'firefox' | Stop-Running
  457. $RemovalList.Add((
  458. (Join-Path -Path $RootAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\Cache*\*"),
  459. (Join-Path -Path $LocalAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\Cache*\*"),
  460. (Join-Path -Path $GlobalAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\Cache*\*"),
  461. (Join-Path -Path $RootAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\jumpListCache\*"),
  462. (Join-Path -Path $LocalAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\jumpListCache\*"),
  463. (Join-Path -Path $GlobalAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\jumpListCache\*"),
  464. (Join-Path -Path $RootAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\thumbnails\*"),
  465. (Join-Path -Path $LocalAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\thumbnails\*"),
  466. (Join-Path -Path $GlobalAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\*sqlite*"),
  467. (Join-Path -Path $RootAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\*.log"),
  468. (Join-Path -Path $LocalAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\*.log"),
  469. (Join-Path -Path $GlobalAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\*.log"),
  470. (Join-Path -Path $RootAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\storage\*"),
  471. (Join-Path -Path $LocalAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\storage\*"),
  472. (Join-Path -Path $GlobalAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\storage\*"),
  473. (Join-Path -Path $RootAppData -ChildPath "Mozilla\Firefox\Crash Reports\*"),
  474. (Join-Path -Path $LocalAppData -ChildPath "Mozilla\Firefox\Crash Reports\*"),
  475. (Join-Path -Path $GlobalAppData -ChildPath "Mozilla\Firefox\Crash Reports\*"),
  476. (Join-Path -Path $RootAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\startupCache\*"),
  477. (Join-Path -Path $LocalAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\startupCache\*"),
  478. (Join-Path -Path $GlobalAppData -ChildPath "Mozilla\Firefox\Profiles\*.default\datareporting\*")
  479. ))
  480. }
  481. 'IE'
  482. {
  483. # Add all Internet Explorer cache, cookie, history and logging directories if the -Include parameter with the 'IE' value is used.
  484. 'iexplore' | Stop-Running
  485. $RemovalList.Add((
  486. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Internet Explorer\*.log"),
  487. (Join-Path -Path $RootAppData -ChildPath "Microsoft\Internet Explorer\*.log"),
  488. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Internet Explorer\*.txt"),
  489. (Join-Path -Path $RootAppData -ChildPath "Microsoft\Internet Explorer\*.txt"),
  490. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Internet Explorer\CacheStorage\*.*"),
  491. (Join-Path -Path $RootAppData -ChildPath "Microsoft\Internet Explorer\CacheStorage\*.*"),
  492. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Windows\INetCache\*"),
  493. (Join-Path -Path $RootAppData -ChildPath "Microsoft\Windows\INetCache\*"),
  494. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Windows\Temporary Internet Files\*"),
  495. (Join-Path -Path $RootAppData -ChildPath "Microsoft\Windows\Temporary Internet Files\*"),
  496. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Windows\IECompatCache\*"),
  497. (Join-Path -Path $RootAppData -ChildPath "Microsoft\Windows\IECompatCache\*"),
  498. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Windows\IECompatUaCache\*"),
  499. (Join-Path -Path $RootAppData -ChildPath "Microsoft\Windows\IECompatUaCache\*"),
  500. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Windows\IEDownloadHistory\*"),
  501. (Join-Path -Path $RootAppData -ChildPath "Microsoft\Windows\IEDownloadHistory\*"),
  502. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Windows\INetCookies\*"),
  503. (Join-Path -Path $RootAppData -ChildPath "Microsoft\Windows\INetCookies\*")
  504. ))
  505. }
  506. 'Edge'
  507. {
  508. # Add Microsoft Edge HTML and Microsoft Edge Chromium cache, cookie, history and logging directories if the -Include parameter with the 'Edge' value is used.
  509. 'msedge', 'MicrosoftEdge*' | Stop-Running
  510. If (Get-AppxPackage -Name Microsoft.MicrosoftEdge | Select-Object -ExpandProperty PackageFamilyName)
  511. {
  512. $EdgePackageName = Get-AppxPackage -Name Microsoft.MicrosoftEdge | Select-Object -ExpandProperty PackageFamilyName
  513. $RemovalList.Add((
  514. (Join-Path -Path $RootAppData -ChildPath "Packages\$EdgePackageName\AC\#!00*"),
  515. (Join-Path -Path $LocalAppData -ChildPath "Packages\$EdgePackageName\AC\#!00*"),
  516. (Join-Path -Path $RootAppData -ChildPath "Packages\$EdgePackageName\AC\Temp\*"),
  517. (Join-Path -Path $LocalAppData -ChildPath "Packages\$EdgePackageName\AC\Temp\*"),
  518. (Join-Path -Path $RootAppData -ChildPath "Packages\$EdgePackageName\AC\Microsoft\Cryptnet*Cache\*"),
  519. (Join-Path -Path $LocalAppData -ChildPath "Packages\$EdgePackageName\AC\Microsoft\Cryptnet*Cache\*"),
  520. (Join-Path -Path $RootAppData -ChildPath "Packages\$EdgePackageName\AC\MicrosoftEdge\Cookies\*"),
  521. (Join-Path -Path $LocalAppData -ChildPath "Packages\$EdgePackageName\AC\MicrosoftEdge\Cookies\*"),
  522. (Join-Path -Path $RootAppData -ChildPath "Packages\$EdgePackageName\AC\MicrosoftEdge\UrlBlock\*.tmp"),
  523. (Join-Path -Path $LocalAppData -ChildPath "Packages\$EdgePackageName\AC\MicrosoftEdge\UrlBlock\*.tmp"),
  524. (Join-Path -Path $RootAppData -ChildPath "Packages\$EdgePackageName\AC\MicrosoftEdge\User\Default\ImageStore\*"),
  525. (Join-Path -Path $LocalAppData -ChildPath "Packages\$EdgePackageName\AC\MicrosoftEdge\User\Default\ImageStore\*"),
  526. (Join-Path -Path $RootAppData -ChildPath "Packages\$EdgePackageName\AC\MicrosoftEdge\User\Default\Recovery\Active\*.dat"),
  527. (Join-Path -Path $LocalAppData -ChildPath "Packages\$EdgePackageName\AC\MicrosoftEdge\User\Default\Recovery\Active\*.dat"),
  528. (Join-Path -Path $RootAppData -ChildPath "Packages\$EdgePackageName\AC\MicrosoftEdge\User\Default\DataStore\Data\nouser1\*\DBStore\LogFiles\*"),
  529. (Join-Path -Path $LocalAppData -ChildPath "Packages\$EdgePackageName\AC\MicrosoftEdge\User\Default\DataStore\Data\nouser1\*\DBStore\LogFiles\*"),
  530. (Join-Path -Path $RootAppData -ChildPath "Packages\$EdgePackageName\AC\MicrosoftEdge\User\Default\DataStore\Data\nouser1\*\Favorites\*.ico"),
  531. (Join-Path -Path $LocalAppData -ChildPath "Packages\$EdgePackageName\AC\MicrosoftEdge\User\Default\DataStore\Data\nouser1\*\Favorites\*.ico"),
  532. (Join-Path -Path $RootAppData -ChildPath "Packages\$EdgePackageName\AppData\User\Default\Indexed DB\*"),
  533. (Join-Path -Path $LocalAppData -ChildPath "Packages\$EdgePackageName\AppData\User\Default\Indexed DB\*"),
  534. (Join-Path -Path $RootAppData -ChildPath "Packages\$EdgePackageName\TempState\*"),
  535. (Join-Path -Path $LocalAppData -ChildPath "Packages\$EdgePackageName\TempState\*"),
  536. (Join-Path -Path $RootAppData -ChildPath "Packages\$EdgePackageName\LocalState\Favicons\PushNotificationGrouping\*"),
  537. (Join-Path -Path $LocalAppData -ChildPath "Packages\$EdgePackageName\LocalState\Favicons\PushNotificationGrouping\*")
  538. ))
  539. }
  540.  
  541. If ((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\msedge.exe" -ErrorAction Ignore) -or @((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*" -ErrorAction Ignore | Where-Object -Property DisplayName -EQ 'Microsoft Edge'), (Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" -ErrorAction Ignore | Where-Object -Property DisplayName -EQ 'Microsoft Edge')))
  542. {
  543. $RemovalList.Add((
  544. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Cache\*"),
  545. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Code Cache\js\*"),
  546. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Code Cache\wasm\*"),
  547. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Cookies\*"),
  548. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\CrashPad\*.pma"),
  549. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\CrashPad\metadata"),
  550. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\data_reduction_proxy_leveldb\*"),
  551. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Extension State\*"),
  552. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Feature Engagement Package\AvailabilityDB\*"),
  553. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Feature Engagement Package\EventDB\*"),
  554. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\File System\000\*"),
  555. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\File System\Origins\*"),
  556. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\IndexedDB\*"),
  557. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Service Worker\CacheStorage\*"),
  558. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Service Worker\Database\*"),
  559. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Service Worker\ScriptCache\*"),
  560. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Current Tabs"),
  561. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Last Tabs"),
  562. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\History"),
  563. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\History Provider Cache"),
  564. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\History-journal"),
  565. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Network Action Predictor"),
  566. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Top Sites"),
  567. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Visited Links"),
  568. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Login Data"),
  569. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\*\*.log"),
  570. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\*\*log*"),
  571. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\*\MANIFEST-*"),
  572. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Shortcuts"),
  573. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\QuotaManager"),
  574. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Web Data"),
  575. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Current Session"),
  576. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Last Session"),
  577. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Session Storage\*"),
  578. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Site Characteristics Database\*"),
  579. (Join-Path -Path $LocalAppData -ChildPath "Microsoft\Edge\User Data\Profile *\Sync Data\LevelDB\*"),
  580. (Join-Path -Path $Env:ProgramData -ChildPath "Microsoft\EdgeUpdate\Log\*"),
  581. (Join-Path -Path ${Env:ProgramFiles(x86)} -ChildPath "Microsoft\Edge\Application\SetupMetrics\*.pma"),
  582. (Join-Path -Path ${Env:ProgramFiles(x86)} -ChildPath "Microsoft\EdgeUpdate\Download\*")
  583. ))
  584. }
  585. }
  586. }
  587.  
  588. If ($ExcludedList -notcontains 'Update Cleanup')
  589. {
  590. # If 'Update Cleanup' has not been excluded, add the 'SoftwareDistribution\Downloads' directory and log files.
  591. 'wuauserv' | Stop-Running
  592. $RemovalList.Add((
  593. (Join-Path -Path $Env:SystemRoot -ChildPath "SoftwareDistribution\Download\*"),
  594. (Join-Path -Path $Env:SystemRoot -ChildPath "SoftwareDistribution\DataStore\Logs\*.*"),
  595. (Join-Path -Path $Env:SystemRoot -ChildPath "Logs\WindowsUpdate\*.*"),
  596. (Join-Path -Path $Env:ProgramData -ChildPath "USOShared\Logs\*.*")
  597. ))
  598. }
  599.  
  600. # Remove all content from each path added to the array list.
  601. $RemovalList | Remove-Items
  602.  
  603. If ($RemovalList -match 'SoftwareDistribution')
  604. {
  605. # Restart the Windows Update Service if it was originally running since the 'SoftwareDistribution\Downloads' directory has been cleared.
  606. Start-Service -Name wuauserv -Verbose -ErrorAction SilentlyContinue
  607. }
  608.  
  609. If ($PSBoundParameters.Additional)
  610. {
  611. # Remove any additional files, folders or directories that were passed with the -Additional parameter.
  612. $Additional | Remove-Items -Force:$Force
  613. }
  614.  
  615. # Remove any junk folders from the Windows directory.
  616. Get-ChildItem -Path $Env:SystemRoot -Directory -Force -ErrorAction SilentlyContinue | Where-Object { ($PSItem.Name -match "^\{\w{8}-\w{4}-\w{4}-\w{4}-\w{12}\}$") -and ($PSItem.Name -notmatch "win|prog|res|rec|driv") } | Remove-Items
  617.  
  618. # Remove any junk folders from the root directory.
  619. Get-ChildItem -Path $Env:SystemDrive -Directory -Force -ErrorAction SilentlyContinue | Where-Object { ($PSItem.Name -notmatch "win|prog|res|rec|driv") -and ($PSItem.Name -match "^[a-z0-9]{15,}$") -and ((("$($PSItem.Name)" -replace '[0-9]', '').Length * .9) -lt ("$($PSItem.Name)" -replace '[^0-9]', '').Length) } | Remove-Items
  620.  
  621. # Remove all Recycle Bin items from all system drives. This method is more thorough than using its shell object or the Clear-RecycleBin cmdlet.
  622. Get-PSDrive -PSProvider FileSystem | ForEach-Object -Process {
  623. $RecycleBin = Join-Path -Path $PSItem.Root -ChildPath '$Recycle.Bin\'
  624. If (Test-Path -Path $RecycleBin) { Get-ChildItem -Path (Join-Path -Path $RecycleBin -ChildPath '*\$I*') -Recurse -Force -ErrorAction SilentlyContinue | ForEach-Object -Process { $($PSItem.FullName.Replace('$I', '$R')), $($PSItem.FullName) | Remove-Items } }
  625. }
  626.  
  627. If ($IconCache -or $ThumbnailCache)
  628. {
  629. # Disable the AutoRestartShell so Explorer does not automatically restart.
  630. Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name AutoRestartShell -Value 0 -Force -Verbose -ErrorAction SilentlyContinue
  631.  
  632. # Stop the Explorer process.
  633. 'explorer' | Stop-Running
  634.  
  635. Start-Sleep 3
  636.  
  637. If ($IconCache)
  638. {
  639. # Refresh the icon cache.
  640. Invoke-Expression -Command ('IE4UINIT.EXE -SHOW')
  641.  
  642. # Delete the icon cache databases.
  643. @($LocalAppData, (Join-Path -Path $LocalAppData -ChildPath 'Microsoft\Windows\Explorer')) | Get-ChildItem -Filter iconcache*.db -Force -ErrorAction SilentlyContinue | Remove-Items
  644. }
  645.  
  646. If ($ThumbnailCache)
  647. {
  648. # Delete the thumbnail cache databases.
  649. (Join-Path -Path $LocalAppData -ChildPath 'Microsoft\Windows\Explorer') | Get-ChildItem -Filter thumbcache_*.db -Force -ErrorAction SilentlyContinue | Remove-Items
  650. }
  651.  
  652. Start-Sleep 3
  653.  
  654. # Re-enable the AutoRestartShell.
  655. Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name AutoRestartShell -Value 1 -Force -Verbose -ErrorAction SilentlyContinue
  656.  
  657. # Start the Explorer process.
  658. Start-Process -FilePath explorer -Wait
  659. }
  660.  
  661. # Clear the recent document history for WordPad
  662. Remove-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Applets\Wordpad\Recent File List" -Recurse -Force -ErrorAction SilentlyContinue
  663.  
  664. # Remove the last accessed registry key.
  665. Remove-ItemProperty -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit -Name LastKey -Force -Verbose -ErrorAction SilentlyContinue
  666.  
  667. # Add the StateFlags property name to the registry.
  668. Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches -Exclude $ExcludedList -ErrorAction SilentlyContinue | Set-ItemProperty -Name $PropertyName -Value 2 -Force -ErrorAction SilentlyContinue
  669.  
  670. # Start the Microsoft Windows Disk Clean-up utility in advanced mode as a .NET process.
  671. $ProcessInfo = New-Object -TypeName Diagnostics.ProcessStartInfo
  672. $ProcessInfo.FileName = '{0}' -f "$Env:SystemRoot\System32\cleanmgr.exe"
  673. $ProcessInfo.Arguments = '/SAGERUN:{0}' -f $StateFlags
  674. $ProcessInfo.CreateNoWindow = $true
  675. $Process = New-Object -TypeName Diagnostics.Process
  676. $Process.StartInfo = $ProcessInfo
  677. Write-Verbose "Running the Windows Disk Clean-up utility in advanced mode as a .NET process." -Verbose
  678. [Void]$Process.Start()
  679. $Process.WaitForExit()
  680. If ($null -ne $Process) { $Process.Dispose() }
  681.  
  682. # Remove the StateFlags property name from the registry.
  683. Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches -Exclude $ExcludedList -ErrorAction SilentlyContinue | Remove-ItemProperty -Name $PropertyName -Force -ErrorAction SilentlyContinue
  684.  
  685. # Restart the Windows Explorer process.
  686. 'explorer' | Stop-Running
  687. }
  688. End
  689. {
  690. # Assign the post-cleanup storage state to a variable.
  691. $PostClean = (Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object -Property DriveType -EQ 3 | Select-Object -Property @{ Name = 'Drive'; Expression = { ($PSItem.DeviceID) } },
  692. @{ Name = 'Size (GB)'; Expression = { '{0:N1}' -f ($PSItem.Size / 1GB) } },
  693. @{ Name = 'FreeSpace (GB)'; Expression = { '{0:N1}' -f ($PSItem.Freespace / 1GB) } },
  694. @{ Name = 'PercentFree'; Expression = { '{0:P1}' -f ($PSItem.FreeSpace / $PSItem.Size) } } | Format-Table -AutoSize | Out-String).Trim()
  695.  
  696. # Display the disk space reclaimed by the clean-up process.
  697. @(("`n`n`tBefore Clean-up:`n{0}" -f $PreClean), ("`n`n`tAfter Clean-up:`n{0}`n" -f $PostClean)) | Write-Output
  698.  
  699. # Stop the transcript.
  700. Stop-Transcript -ErrorAction Ignore
  701. Write-Output ''
  702. }
  703. }
RAW Paste Data