This repository has been archived by the owner on Aug 14, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 49
/
Win10_VirtualDesktop_Optimize.ps1
267 lines (222 loc) · 11.9 KB
/
Win10_VirtualDesktop_Optimize.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
[Cmdletbinding()]
Param
(
[Parameter()]
[ValidateSet('1909','2004')]
$WindowsVersion = 2004
)
#Requires -RunAsAdministrator
<#
- TITLE: Microsoft Windows 10 Virtual Desktop Optimization Script
- AUTHORED BY: Robert M. Smith and Tim Muessig (Microsoft)
- AUTHORED DATE: 11/19/2019
- LAST UPDATED: 6/18/2020
- PURPOSE: To automatically apply settings referenced in the following white papers:
https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds_vdi-recommendations-1909
- Important: Every setting in this script and input files are possible recommendations only,
and NOT requirements in any way. Please evaluate every setting for applicability
to your specific environment. These scripts have been tested on plain Hyper-V
VMs. Please test thoroughly in your environment before implementation
- DEPENDENCIES 1. On the target machine, run PowerShell elevated (as administrator)
2. Within PowerShell, set exectuion policy to enable the running of scripts.
Ex. Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
3. LGPO.EXE (available at https://www.microsoft.com/en-us/download/details.aspx?id=55319)
4. LGPO database files available in the respective folders (ex. \1909, or \2004)
5. This PowerShell script
6. The text input files containing all the apps, services, traces, etc. that you...
may be interested in disabling. Please review these input files to customize...
to your environment/requirements
- REFERENCES:
https://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/remove-item?view=powershell-6
https://blogs.technet.microsoft.com/secguide/2016/01/21/lgpo-exe-local-group-policy-object-utility-v1-0/
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/set-service?view=powershell-6
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/remove-item?view=powershell-6
https://msdn.microsoft.com/en-us/library/cc422938.aspx
#>
<# Categories of cleanup items:
This script is dependent on three elements:
LGPO Settings folder, applied with the LGPO.exe Microsoft app
The UWP app input file contains the list of almost all the UWP application packages that can be removed with PowerShell interactively.
The Store and a few others, such as Wallet, were left off intentionally. Though it is possible to remove the Store app,
it is nearly impossible to get it back. Please review the lists below and comment out or remove references to packages that you do not want to remove.
#>
$StartTime = Get-Date
$CurrentLocation = Get-Location
Try
{
Set-Location (Join-Path $PSScriptRoot $WindowsVersion)-ErrorAction Stop
}
Catch
{
Write-Warning "Invalid Path $(Join-Path $PSScriptRoot $WindowsVersion) - Exiting script!"
Break
}
#region Disable, then remove, Windows Media Player including payload
Try
{
Write-Verbose "Disabling Windows Media Player Feature"
Disable-WindowsOptionalFeature -Online -FeatureName WindowsMediaPlayer -NoRestart | Out-Null
Get-WindowsPackage -Online -PackageName "*Windows-mediaplayer*" | ForEach-Object {
Write-Verbose "Removeing $($_.PackageName)"
Remove-WindowsPackage -PackageName $_.PackageName -Online -ErrorAction SilentlyContinue -NoRestart | Out-Null
}
}
Catch { }
#endregion
#region Begin Clean APPX Packages
If (Test-Path .\ConfigurationFiles\AppxPackages.json)
{
$AppxPackage = Get-Content .\ConfigurationFiles\AppxPackages.json | ConvertFrom-Json
$AppxPackage = $AppxPackage | Where-Object { $_.VDIState -eq 'Disabled' }
}
If ($AppxPackage.Count -gt 0)
{
Foreach ($Item in $AppxPackage)
{
$Package = "*$($Item.AppxPackage)*"
Write-Verbose "Attempting to remove $($Item.AppxPackage) - $($Item.Description)"
Get-AppxPackage -Name $Package | Remove-AppxPackage -ErrorAction SilentlyContinue | Out-Null
#Write-Verbose "`t`tAttempting to remove [All Users] $($Item.AppxPackage) - $($Item.Description)"
#Get-AppxPackage -AllUsers -Name $Package | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue
Write-Verbose "`t`tRemoving Provisioned Package $($item.AppxPackage)"
Get-AppxProvisionedPackage -Online | Where-Object { $_.PackageName -like $Package } | Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | Out-Null
}
}
#endregion
#region Disable Scheduled Tasks
# This section is for disabling scheduled tasks. If you find a task that should not be disabled
# change its "VDIState" from Disabled to Enabled, or remove it from the json completely.
If (Test-Path .\ConfigurationFiles\ScheduledTasks.json)
{
$SchTasksList = Get-Content .\ConfigurationFiles\ScheduledTasks.json | ConvertFrom-Json
$SchTasksList = $SchTasksList | Where-Object { $_.VDIState -eq 'Disabled' }
}
If ($SchTasksList.count -gt 0)
{
#$EnabledScheduledTasks = Get-ScheduledTask | Where-Object { $_.State -ne "Disabled" }
Foreach ($Item in $SchTasksList)
{
#$Task = (($Item -split ":")[0]).Trim()
Write-Verbose "Disabling Scheduled Task $($Item.ScheduledTask)"
Disable-ScheduledTask -TaskName $Item.ScheduledTask -ErrorAction SilentlyContinue
#$EnabledScheduledTasks | Where-Object { $_.TaskName -like "*$Task*" } #| Disable-ScheduledTask
}
}
#endregion
#region Customize Default User Profile
# Apply appearance customizations to default user registry hive, then close hive file
If (Test-Path .\ConfigurationFiles\DefaultUserSettings.txt)
{
$DefaultUserSettings = Get-Content .\ConfigurationFiles\DefaultUserSettings.txt
}
If ($DefaultUserSettings.count -gt 0)
{
Write-Verbose "Processing Default User Settings registry keys"
Foreach ($Item in $DefaultUserSettings)
{
Start-Process C:\Windows\System32\Reg.exe -ArgumentList "$Item" -Wait
}
}
#endregion
#region Disable Windows Traces
If (Test-Path .\ConfigurationFiles\Autologgers.Json)
{
$DisableAutologgers = Get-Content .\ConfigurationFiles\Autologgers.Json | ConvertFrom-Json
}
If ($DisableAutologgers.count -gt 0)
{
$DisableAutologgers = $DisableAutologgers | Where-Object { $_.Disabled -eq 'True' }
Foreach ($Item in $DisableAutologgers)
{
Write-Verbose "Adding $($Item.KeyName)"
New-ItemProperty -Path "$($Item.KeyName)" -Name "Start" -PropertyType "DWORD" -Value "0" -Force | Out-Null
}
}
#endregion
#region Local Group Policy Settings
# - This code does not:
# * set a lock screen image.
# * change the "Root Certificates Update" policy.
# * change the "Enable Windows NTP Client" setting.
# * set the "Select when Quality Updates are received" policy
if (Test-Path (Join-Path $PSScriptRoot "LGPO\LGPO.exe"))
{
Write-Verbose "Importing Local Group Policy Items"
Start-Process (Join-Path $PSScriptRoot "LGPO\LGPO.exe") -ArgumentList "/g .\LGPO" -Wait
}
#endregion
#region Disable Services
If (Test-Path .\ConfigurationFiles\Services.json)
{
$ServicesToDisable = Get-Content .\ConfigurationFiles\Services.json | ConvertFrom-Json
}
If ($ServicesToDisable.count -gt 0)
{
$ServicesToDisable = $ServicesToDisable | Where-Object { $_.VDIState -eq 'Disabled' }
Foreach ($Item in $ServicesToDisable)
{
Write-Verbose "Stopping $($Item.Name) - $($Item.Description)"
Stop-Service $Item.Name -Force -ErrorAction SilentlyContinue
Write-Verbose "`t`tDisabling $($Item.Name)"
Set-Service $Item.Name -StartupType Disabled
}
}
#endregion
#region Network Optimization
# LanManWorkstation optimizations
Write-Verbose "Configuring LanManWorlstation Optimizations"
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\LanmanWorkstation\Parameters\" -Name "DisableBandwidthThrottling" -PropertyType "DWORD" -Value "1" -Force | Out-Null
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\LanmanWorkstation\Parameters\" -Name "FileInfoCacheEntriesMax" -PropertyType "DWORD" -Value "1024" -Force | Out-Null
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\LanmanWorkstation\Parameters\" -Name "DirectoryCacheEntriesMax" -PropertyType "DWORD" -Value "1024" -Force | Out-Null
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\LanmanWorkstation\Parameters\" -Name "FileNotFoundCacheEntriesMax" -PropertyType "DWORD" -Value "1024" -Force | Out-Null
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\LanmanWorkstation\Parameters\" -Name "DormantFileLimit" -PropertyType "DWORD" -Value "256" -Force | Out-Null
# NIC Advanced Properties performance settings for network biased environments
Write-Verbose "Configuring Network Adapter Buffer Size"
Set-NetAdapterAdvancedProperty -DisplayName "Send Buffer Size" -DisplayValue 4MB
<# Note that the above setting is for a Microsoft Hyper-V VM. You can adjust these values in your environment...
by querying in PowerShell using Get-NetAdapterAdvancedProperty, and then adjusting values using the...
Set-NetAdapterAdvancedProperty command.
#>
#endregion
#region
# ADDITIONAL DISK CLEANUP
# Delete not in-use files in locations C:\Windows\Temp and %temp%
# Also sweep and delete *.tmp, *.etl, *.evtx, *.log, *.dmp, thumbcache*.db (not in use==not needed)
# 5/18/20: Removing Disk Cleanup and moving some of those tasks to the following manual cleanup
Write-Verbose "Removing .tmp, .etl, .evtx, thumbcache*.db, *.log files not in use"
Get-ChildItem -Path c:\ -Include *.tmp, *.dmp, *.etl, *.evtx, thumbcache*.db, *.log -File -Recurse -Force -ErrorAction SilentlyContinue | Remove-Item -ErrorAction SilentlyContinue
# Delete "RetailDemo" content (if it exits)
Write-Verbose "Removing Retail Demo content (if it exists)"
Get-ChildItem -Path $env:ProgramData\Microsoft\Windows\RetailDemo\* -Recurse -Force -ErrorAction SilentlyContinue | Remove-Item -Recurse -ErrorAction SilentlyContinue
# Delete not in-use anything in the C:\Windows\Temp folder
Write-Verbose "Removing all files not in use in $env:windir\TEMP"
Remove-Item -Path $env:windir\Temp\* -Recurse -Force -ErrorAction SilentlyContinue
# Clear out Windows Error Reporting (WER) report archive folders
Write-Verbose "Cleaning up WER report archive"
Remove-Item -Path $env:ProgramData\Microsoft\Windows\WER\Temp\* -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path $env:ProgramData\Microsoft\Windows\WER\ReportArchive\* -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path $env:ProgramData\Microsoft\Windows\WER\ReportQueue\* -Recurse -Force -ErrorAction SilentlyContinue
# Delete not in-use anything in your %temp% folder
Write-Verbose "Removing files not in use in $env:TEMP directory"
Remove-Item -Path $env:TEMP\* -Recurse -Force -ErrorAction SilentlyContinue
# Clear out ALL visible Recycle Bins
Write-Verbose "Clearing out ALL Recycle Bins"
Clear-RecycleBin -Force -ErrorAction SilentlyContinue
# Clear out BranchCache cache
Write-Verbose "Clearing BranchCache cache"
Clear-BCCache -Force -ErrorAction SilentlyContinue
#endregion
Set-Location $CurrentLocation
$EndTime = Get-Date
$ScriptRunTime = New-TimeSpan -Start $StartTime -End $EndTime
Write-Host "Total Run Time: $($ScriptRunTime.Hours) Hours $($ScriptRunTime.Minutes) Minutes $($ScriptRunTime.Seconds) Seconds" -ForegroundColor Cyan
Add-Type -AssemblyName PresentationFramework
$Answer = [System.Windows.MessageBox]::Show("Reboot to make changes effective?", "Restart Computer", "YesNo", "Question")
Switch ($Answer)
{
"Yes" { Write-Warning "Restarting Computer in 15 Seconds"; Start-sleep -seconds 15; Restart-Computer -Force }
"No" { Write-Warning "A reboot is required for all changed to take effect" }
Default { Write-Warning "A reboot is required for all changed to take effect" }
}
######################## END OF SCRIPT ########################