├── README.md
├── SPBestWarmUp.ps1
├── SPBestWarmUp.xml
└── doc
├── 1.jpg
├── 2.jpg
├── 3.jpg
└── download.png
/README.md:
--------------------------------------------------------------------------------
1 | ## Description
2 | Tired of waiting for SharePoint pages to load? Want something easy to support? That works on all versions? This warmup script is for you!
3 |
4 | I used several different warmup scripts. All worked OK but each seemed to lack features so I decided to create a new one. Hope you find it useful too.
5 |
6 | [](https://github.com/spjeff/spbestwarmup/releases/download/v2.4.22/SPBestWarmUp.zip)
7 |
8 | ## Key Features
9 | * SharePoint 2010, 2013, and 2016
10 | * Custom page URLs
11 | * Detect SP Web Application URLs
12 | * Detect Host Named Site Collection URLs
13 | * Detects Service Application URLs
14 | * Detects Project Server PWA
15 | * Download full page resources (JS, images) not just HTML
16 | * Download with `Invoke-WebRequest`
17 | * Great for ECM websites to populate blob cache
18 | * Warm up Central Admin - home, health rules, web apps for a faster admin experience!
19 | * Warm up Central Admin - all Manage Service Application pages.
20 | * Display W3WP total #MB before and after
21 | * Excellent blog post by [@hd_ka](https://twitter.com/hd_ka) at [http://blog.greenbrain.de/2014/10/fire-up-those-caches.html](http://blog.greenbrain.de/2014/10/fire-up-those-caches.html)
22 |
23 | ## Quick Start
24 | * Download `SPBestWarmUp.ps1`
25 | * Copy `SPBestWarmUp.ps1` to one SharePoint web front end (WFE)
26 | * (Optionnally) Run the following powershell command to avoid error on the next command : Set-ExecutionPolicy -ExecutionPolicy ByPass
27 | * Run `SPBestWarmUp.ps1 -f` to install farm wide. Creates Task Scheduler job on every machine.
28 | * Run `SPBestWarmUp.ps1 -i` to install locally. Creates Task Scheduler job on the local machine.
29 | * Run `SPBestWarmUp.ps1 -u` to uninstall farm wide. Deletes any Task Scheduler job named "SPBestWarmup"
30 | * Sit back and enjoy!
31 |
32 | ## Screenshots
33 |
34 | * Install farm wide
35 | 
36 |
37 | * Manual run
38 | 
39 |
40 | * Manual run with custom URL parameter
41 | 
42 |
43 | ## Admin Tip
44 | * After reboot run this command to manually trigger the job and warm up IIS
45 | `SCHTASKS /RUN /TN "SPBestWarmUp"`
46 |
47 | ## Custom URLs
48 | * Use the `-url` paramter to add custom URLs from the command line.
49 | * Rename Central Admin site title and edit lines `331-345` to add custom URLs within the script. Good for lifecycle (dev, test, prod).
50 |
51 | ## Permission
52 | * Running this with a different service account than farm might require you to first grant PowerShell access. This ensures the service account has access to run `Get-SPWebApplication` and `Get-SPServer` for detecting URLs to load. [http://technet.microsoft.com/en-us/magazine/gg490648.aspx
53 | ](http://technet.microsoft.com/en-us/magazine/gg490648.aspx)
54 |
55 | ## Contact
56 | Please drop a line to [@spjeff](https://twitter.com/spjeff) or [spjeff@spjeff.com](mailto:spjeff@spjeff.com)
57 | Thanks! =)
58 |
59 | 
60 |
61 |
62 | ## License
63 |
64 | The MIT License (MIT)
65 |
66 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
67 |
68 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
69 |
70 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
71 |
--------------------------------------------------------------------------------
/SPBestWarmUp.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Warm up SharePoint IIS W3WP memory cache by loading pages from WebRequest
4 |
5 | .DESCRIPTION
6 | Loads the full page so resources like CSS, JS, and images are included. Please modify lines 350-368 to suit your portal content design (popular URLs, custom pages, etc.)
7 |
8 | Comments and suggestions always welcome! Please, use the issues panel at the project page.
9 |
10 | .PARAMETER url
11 | A collection of url that will be added to the list of websites the script will fetch.
12 |
13 | .PARAMETER install
14 | Typing "SPBestWarmUp.ps1 -install" will create a local machine Task Scheduler job under credentials of the current user. Job runs every 60 minutes on the hour to help automatically populate cache. Keeps cache full even after IIS daily recycle, WSP deployment, reboot, or other system events.
15 |
16 | .PARAMETER installfarm
17 | Typing "SPBestWarmUp.ps1 -installfarm" will create a Task Scheduler job on all machines in the farm.
18 |
19 | .PARAMETER uninstall
20 | Typing "SPBestWarmUp.ps1 -uninstall" will remove Task Scheduler job from all machines in the farm.
21 |
22 | .PARAMETER user
23 | Typing "SPBestWarmUp.ps1 -user" provides the user name that will be used for the execution of the Task Scheduler job. If this parameter is missing it is assumed that the Task Scheduler job will be run with the current user.
24 |
25 | .PARAMETER allsites
26 | Typing "SPBestWarmUp.ps1 -allsites" will load every site and web URL. If the parameter skipsubwebs is used, only the root web of each site collection will be processed.
27 |
28 | .PARAMETER transcript
29 | Typing "SPBestWarmUp.ps1 -transcript" will generate a full PowerShell text transcript of the script exeuction. Helpful for debug.
30 |
31 | .PARAMETER skiplog
32 | Typing "SPBestWarmUp.ps1 -skiplog" will avoid writing to the EventLog
33 |
34 | .PARAMETER skipsubwebs
35 | Typing "SPBestWarmUp.ps1 -skipsubwebs" will skip the subwebs of each site collection and only process the root web of the site collection.
36 |
37 | .PARAMETER skipadmincheck
38 | Typing "SPBestWarmUp.ps1 -skipadmincheck" will skip checking of the current user is a local administrator. Local administrator rights are necessary for the installation of the Windows Task Scheduler but not necessary for simply running the warmup script.
39 |
40 | .EXAMPLE
41 | .\SPBestWarmUp.ps1 -url "http://domainA.tld","http://domainB.tld"
42 |
43 | .EXAMPLE
44 | .\SPBestWarmUp.ps1 -i
45 | .\SPBestWarmUp.ps1 -install
46 |
47 | .EXAMPLE
48 | .\SPBestWarmUp.ps1 -f
49 | .\SPBestWarmUp.ps1 -installfarm
50 |
51 | .EXAMPLE
52 | .\SPBestWarmUp.ps1 -f -user "Contoso\JaneDoe"
53 | .\SPBestWarmUp.ps1 -installfarm -user "Contoso\JaneDoe"
54 |
55 | .EXAMPLE
56 | .\SPBestWarmUp.ps1 -u
57 | .\SPBestWarmUp.ps1 -uninstall
58 |
59 | .NOTES
60 | File Name: SPBestWarmUp.ps1
61 | Author : Jeff Jones - @spjeff
62 | Author : Hagen Deike - @hd_ka
63 | Author : Lars Fernhomberg
64 | Author : Charles Crossan - @crossan007
65 | Author : Leon Lennaerts
66 | Author : Dan Rullo
67 | Modified : 2023-12-09
68 |
69 | .LINK
70 | https://github.com/spjeff/spbestwarmup
71 | #>
72 |
73 |
74 | [CmdletBinding()]
75 | param (
76 | [Parameter(Mandatory = $False, Position = 0, ValueFromPipeline = $false, HelpMessage = 'A collection of URLs that will be fetched too')]
77 | [Alias("url")]
78 | [ValidateNotNullOrEmpty()]
79 | [ValidatePattern("https?:\/\/\D+")]
80 | [string[]]$cmdurl,
81 |
82 | [Parameter(Mandatory = $False, Position = 1, ValueFromPipeline = $false, HelpMessage = 'Use -install -i parameter to add script to Windows Task Scheduler on local machine')]
83 | [Alias("i")]
84 | [switch]$install,
85 |
86 | [Parameter(Mandatory = $False, Position = 2, ValueFromPipeline = $false, HelpMessage = 'Use -installfarm -f parameter to add script to Windows Task Scheduler on all farm machines')]
87 | [Alias("f")]
88 | [switch]$installfarm,
89 |
90 | [Parameter(Mandatory = $False, Position = 3, ValueFromPipeline = $false, HelpMessage = 'Use -uninstall -u parameter to remove Windows Task Scheduler job')]
91 | [Alias("u")]
92 | [switch]$uninstall,
93 |
94 | [Parameter(Mandatory = $False, Position = 4, ValueFromPipeline = $false, HelpMessage = 'Use -user to provide the login of the user that will be used to run the script in the Windows Task Scheduler job')]
95 | [string]$user,
96 |
97 | [Parameter(Mandatory = $False, Position = 5, ValueFromPipeline = $false, HelpMessage = 'Use -skiplog -sl parameter to avoid writing to Event Log')]
98 | [Alias("sl")]
99 | [switch]$skiplog,
100 |
101 | [Parameter(Mandatory = $False, Position = 6, ValueFromPipeline = $false, HelpMessage = 'Use -allsites -all parameter to load every site and web (if skipsubwebs parameter is also given, only the root web will be processed)')]
102 | [Alias("all")]
103 | [switch]$allsites,
104 |
105 | [Parameter(Mandatory = $False, Position = 7, ValueFromPipeline = $false, HelpMessage = 'Use -skipsubwebs -sw parameter to skip subwebs of each site collection and to process only the root web')]
106 | [Alias("sw")]
107 | [switch]$skipsubwebs,
108 |
109 | [Parameter(Mandatory = $False, Position = 8, ValueFromPipeline = $false, HelpMessage = 'Use -skipadmincheck -sac parameter to skip checking if the current user is an administrator')]
110 | [Alias("sac")]
111 | [switch]$skipadmincheck,
112 |
113 | [Parameter(Mandatory = $False, Position = 9, ValueFromPipeline = $false, HelpMessage = 'Use -skipserviceapps -ssa parameter to skip warming up of Service Application Endpoints URLs')]
114 | [Alias("ssa")]
115 | [switch]$skipserviceapps,
116 |
117 | [Parameter(Mandatory = $False, Position = 10, ValueFromPipeline = $false, HelpMessage = 'Use -skipprogress -sp parameter to skip display of progres bar. Faster execution for background scheduling.')]
118 | [Alias("sp")]
119 | [switch]$skipprogress,
120 |
121 | [Parameter(Mandatory = $False, Position = 11, ValueFromPipeline = $false, HelpMessage = 'Use -transcript -t parameter to generate full PowerShell transcript. Helpful for debug.')]
122 | [Alias("t")]
123 | [switch]$transcript
124 | )
125 |
126 | Function Installer() {
127 | # Add to Task Scheduler
128 | Write-Output " Installing to Task Scheduler..."
129 | if (!$user) {
130 | $user = $ENV:USERDOMAIN + "\" + $ENV:USERNAME
131 | }
132 | Write-Output " User for Task Scheduler job: $user"
133 |
134 | try {
135 | # Attempt to detect password from IIS Pool (if current user is local admin and farm account)
136 | $appPools = Get-WMIObject -Namespace "root/MicrosoftIISv2" -Class "IIsApplicationPoolSetting" -ErrorAction SilentlyContinue | Select-Object WAMUserName, WAMUserPass
137 | foreach ($pool in $appPools) {
138 | if ($pool.WAMUserName -like $user) {
139 | $pass = $pool.WAMUserPass
140 | if ($pass) {
141 | break
142 | }
143 | }
144 | }
145 | }
146 | catch {
147 | # Manual input if auto detect failed
148 | if (!$pass) {
149 | $pass = Read-Host "Enter password for $user "
150 | }
151 | }
152 | # Task Scheduler command
153 | $suffix += " -skipadmincheck" #We do not need administrative rights on local machines to check the farm
154 | if ($allsites) { $suffix += " -allsites" }
155 | if ($skipsubwebs) { $suffix += " -skipsubwebs" }
156 | if ($skiplog) { $suffix += " -skiplog" }
157 | if ($skipprogress) { $suffix += " -skipprogress" }
158 | $cmd = '-ExecutionPolicy Bypass -File "' + $cmdpath + '"' + $suffix
159 |
160 | # Target machines
161 | $machines = @()
162 | if ($installfarm -or $uninstall) {
163 | # Create farm wide on remote machines
164 | foreach ($srv in (Get-SPServer | Where-Object { $_.Role -ne "Invalid" })) {
165 | $machines += $srv.Address
166 | }
167 | }
168 | else {
169 | # Create local on current machine
170 | $machines += "localhost"
171 | }
172 | $machines | ForEach-Object {
173 | try {
174 | if ($uninstall) {
175 | # Delete task
176 | WriteLog "SCHTASKS DELETE on $_"
177 | schtasks /s $_ /delete /tn "SPBestWarmUp" /f
178 | WriteLog " [OK]" Green
179 | }
180 | else {
181 | $xmlCmdPath = $cmdpath.Replace(".ps1", ".xml")
182 | # Ensure that XML file is present
183 | if (!(Test-Path $xmlCmdPath)) {
184 | Write-Warning """$($xmlCmdPath)"" is missing. Cannot create timer job without missing file."
185 | $xmlTemplate = @"
186 |
187 |
188 |
189 |
190 |
191 | PT1H
192 | P1D
193 | false
194 |
195 | 2017-01-25T01:00:00
196 | true
197 |
198 | 1
199 |
200 |
201 |
202 | true
203 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-IIS-IISReset'] and EventID=3201]]</Select></Query></QueryList>
204 | PT1M
205 |
206 |
207 | true
208 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5074]]</Select></Query></QueryList>
209 | PT1M
210 |
211 |
212 | true
213 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5075]]</Select></Query></QueryList>
214 | PT1M
215 |
216 |
217 | true
218 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5076]]</Select></Query></QueryList>
219 | PT1M
220 |
221 |
222 | true
223 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5077]]</Select></Query></QueryList>
224 | PT1M
225 |
226 |
227 | true
228 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5078]]</Select></Query></QueryList>
229 | PT1M
230 |
231 |
232 | true
233 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5079]]</Select></Query></QueryList>
234 | PT1M
235 |
236 |
237 | true
238 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5080]]</Select></Query></QueryList>
239 |
240 |
241 | true
242 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5081]]</Select></Query></QueryList>
243 | PT1M
244 |
245 |
246 | true
247 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5117]]</Select></Query></QueryList>
248 | PT1M
249 |
250 |
251 | true
252 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5186]]</Select></Query></QueryList>
253 | PT1M
254 |
255 |
256 | true
257 | PT5M
258 |
259 |
260 |
261 |
262 |
263 | Password
264 | HighestAvailable
265 |
266 |
267 |
268 | IgnoreNew
269 | true
270 | true
271 | true
272 | false
273 | false
274 |
275 | true
276 | false
277 |
278 | true
279 | true
280 | false
281 | false
282 | false
283 | P3D
284 | 7
285 |
286 |
287 |
288 | PowerShell.exe
289 |
290 |
291 |
292 |
293 |
294 | "@
295 | $xmlTemplate | Out-File $xmlCmdPath -Force
296 | }
297 |
298 | # Update xml file
299 | Write-Host "xmlCmdPath - $xmlCmdPath"
300 | $xml = [xml](Get-Content $xmlCmdPath)
301 | $xml.Task.Principals.Principal.UserId = $user
302 | $xml.Task.Actions.Exec.Arguments = $cmd
303 | $xml.Task.Actions.Exec.WorkingDirectory = (Split-Path ($xmlCmdPath)).ToString()
304 | $xml.Save($xmlCmdPath)
305 |
306 | # Copy local file to remote UNC path machine
307 | Write-Output "SCHTASKS CREATE on $_"
308 | if ($_ -ne "localhost" -and $_ -ne $ENV:COMPUTERNAME) {
309 | $dest = $cmdpath
310 | $drive = $dest.substring(0, 1)
311 | $match = Get-WMIObject -Class Win32_LogicalDisk | Where-Object { $_.DeviceID -eq ($drive + ":") -and $_.DriveType -eq 3 }
312 | if ($match) {
313 | $dest = "\\" + $_ + "\" + $drive + "$" + $dest.substring(2, $dest.length - 2)
314 | $xmlDest = $dest.Replace(".ps1", ".xml")
315 | mkdir (Split-Path $dest) -ErrorAction SilentlyContinue | Out-Null
316 | Write-Output $dest
317 | Copy-Item $cmdpath $dest -Confirm:$false
318 | Copy-Item $xmlCmdPath $xmlDest -Confirm:$false
319 | }
320 | }
321 | # Create task
322 | WriteLog "SCHTASKS CREATE on $_"
323 | schtasks /s $_ /create /tn "SPBestWarmUp" /ru $user /rp $pass /xml $xmlCmdPath
324 | WriteLog " [OK]" Green
325 | }
326 | }
327 | catch {
328 | $ErrorMessage = $_.Exception.Message
329 | $FailedItem = $_.Exception.ItemName
330 | WriteLog " [ERROR] $ErrorMessage $FailedItem" Yellow
331 | }
332 | }
333 | }
334 |
335 | Function WarmUp() {
336 | # Load plugin
337 | Add-PSSnapIn Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
338 |
339 | # Warm up CMD parameter URLs
340 | $cmdurl | ForEach-Object { NavigateTo $_ }
341 |
342 | # Warm up SharePoint web applications
343 | Write-Output "Opening Web Applications..."
344 |
345 | # Accessing the Alternate URls to warm up all "extended webs" (i.e. multiple IIS websites exists for one SharePoint webapp)
346 | $was = Get-SPWebApplication -IncludeCentralAdministration
347 | foreach ($wa in $was) {
348 | foreach ($alt in $wa.AlternateUrls) {
349 | $url = $alt.PublicUrl
350 | if (!$url.EndsWith("/")) {
351 | $url = $url + "/"
352 | }
353 |
354 | # SharePoint Core
355 | NavigateTo $url
356 | NavigateTo $url"_api/web"
357 | NavigateTo $url"_api/_trust"
358 | NavigateTo $url"_layouts/viewlsts.aspx"
359 | NavigateTo $url"_layouts/settings.aspx"
360 | NavigateTo $url"_vti_bin/UserProfileService.asmx"
361 | NavigateTo $url"_vti_bin/sts/spsecuritytokenservice.svc"
362 | NavigateTo $url"_api/search/query?querytext='warmup'"
363 |
364 | # SharePoint 2016
365 | NavigateTo $url"_layouts/15/fonts/shellicons.eot"
366 | NavigateTo $url"_layouts/15/jsgrid.js"
367 | NavigateTo $url"_layouts/15/sp.js"
368 | NavigateTo $url"_layouts/15/sp.ribbon.js"
369 | NavigateTo $url"_layouts/15/core.js"
370 | NavigateTo $url"_layouts/15/init.js"
371 | NavigateTo $url"_layouts/15/cui.js"
372 | NavigateTo $url"_layouts/15/inplview.js"
373 | NavigateTo $url"_layouts/15/suitenav.js"
374 | }
375 |
376 | # Warm Up Individual Site Collections and Sites
377 | if ($allsites) {
378 | $sites = (Get-SPSite -WebApplication $wa -Limit ALL)
379 | foreach ($site in $sites) {
380 | if ($skipsubwebs) {
381 | $url = $site.RootWeb.Url
382 | NavigateTo $url
383 | }
384 | else {
385 | $webs = (Get-SPWeb -Site $site -Limit ALL)
386 | foreach ($web in $webs) {
387 | $url = $web.Url
388 | NavigateTo $url
389 | }
390 | }
391 | }
392 | }
393 |
394 | # Central Admin
395 | if ($wa.IsAdministrationWebApplication) {
396 | $url = $wa.Url
397 | # Specific pages
398 | NavigateTo $url"Lists/HealthReports/AllItems.aspx"
399 | NavigateTo $url"_admin/FarmServers.aspx"
400 | NavigateTo $url"_admin/Server.aspx"
401 | NavigateTo $url"_admin/WebApplicationList.aspx"
402 | NavigateTo $url"_admin/ServiceApplications.aspx"
403 |
404 | # Quick launch top links
405 | NavigateTo $url"applications.aspx"
406 | NavigateTo $url"systemsettings.aspx"
407 | NavigateTo $url"monitoring.aspx"
408 | NavigateTo $url"backups.aspx"
409 | NavigateTo $url"security.aspx"
410 | NavigateTo $url"security.aspx"
411 | NavigateTo $url"upgradeandmigration.aspx"
412 | NavigateTo $url"apps.aspx"
413 | NavigateTo $url"office365configuration.aspx"
414 | NavigateTo $url"generalapplicationsettings.aspx"
415 |
416 | # Manage Service Application
417 | $sa = Get-SPServiceApplication
418 | $links = $sa | ForEach-Object { $_.ManageLink.Url } | Select-Object -Unique
419 | foreach ($link in $links) {
420 | $ml = $link.TrimStart('/')
421 | NavigateTo "$url$ml"
422 | }
423 | }
424 | }
425 |
426 | # Warm up Service Applications
427 | if (!$skipserviceapps) {
428 | Get-SPServiceApplication | ForEach-Object {
429 | $_.EndPoints | ForEach-Object {
430 | $_.ListenUris | ForEach-Object {
431 | $uri = $_.AbsoluteUri -Replace "/https$", $null -Replace "/http$", $null -Replace "/secure$", $null -Replace "/optimized$", $null
432 | NavigateTo $uri
433 | }
434 | }
435 | }
436 | }
437 |
438 | # Warm up Project Server
439 | Write-Output "Opening Project Server PWAs..."
440 | if ((Get-Command Get-SPProjectWebInstance -ErrorAction SilentlyContinue).Count -gt 0) {
441 | Get-SPProjectWebInstance | ForEach-Object {
442 | # Thanks to Eugene Pavlikov for the snippet
443 | $url = ($_.Url).AbsoluteUri + "/"
444 |
445 | NavigateTo $url
446 | NavigateTo ($url + "_layouts/viewlsts.aspx")
447 | NavigateTo ($url + "_vti_bin/UserProfileService.asmx")
448 | NavigateTo ($url + "_vti_bin/sts/spsecuritytokenservice.svc")
449 | NavigateTo ($url + "Projects.aspx")
450 | NavigateTo ($url + "Approvals.aspx")
451 | NavigateTo ($url + "Tasks.aspx")
452 | NavigateTo ($url + "Resources.aspx")
453 | NavigateTo ($url + "ProjectBICenter/Pages/Default.aspx")
454 | NavigateTo ($url + "_layouts/15/pwa/Admin/Admin.aspx")
455 | }
456 | }
457 |
458 | # Warm up Topology
459 | NavigateTo "http://localhost:32843/Topology/topology.svc"
460 |
461 | # Custom URLs - Add your own below
462 | # NavigateTo "http://portal/popularPage.aspx"
463 | # NavigateTo "http://portal/popularPage2.aspx"
464 | # NavigateTo "http://portal/popularPage3.aspx
465 |
466 | # Warm up Host Name Site Collections (HNSC)
467 | Write-Output "Opening Host Name Site Collections (HNSC)..."
468 | $hnsc = Get-SPSite -Limit All | Where-Object { $_.HostHeaderIsSiteName -eq $true } | Select-Object Url
469 | foreach ($sc in $hnsc) {
470 | NavigateTo $sc.Url
471 | }
472 |
473 | # Warm up Office Online Server (OOS)
474 | $remoteuis = "m,o,oh,op,p,we,wv,x".Split(",")
475 | $services = "diskcache/DiskCache.svc,dss/DocumentSessionService.svc,ecs/ExcelService.asmx,farmstatemanager/FarmStateManager.svc,metb/BroadcastStateService.svc,pptc/Viewing.svc,ppte/Editing.svch,wdss/WordDocumentSessionService.svc,wess/WordSaveService.svc,wvc/Conversion.svc".Split(",")
476 |
477 | # Loop per WOPI
478 | $wopis = Get-SPWOPIBinding | Select-Object ServerName -Unique
479 | foreach ($w in $wopis.ServerName) {
480 | foreach ($r in $remoteuis) {
481 | NavigateTo "http://$w/$r/RemoteUIs.ashx"
482 | NavigateTo "https://$w/$r/RemoteUIs.ashx"
483 | }
484 | foreach ($s in $services) {
485 | NavigateTo ("http://$w" + ":809/$s")
486 | NavigateTo ("https://$w" + ":810/$s")
487 | }
488 | }
489 | }
490 |
491 | Function NavigateTo([string] $url) {
492 | if ($url.ToUpper().StartsWith("HTTP") -and !$url.EndsWith("/ProfileService.svc", "CurrentCultureIgnoreCase")) {
493 | WriteLog " $url"
494 | # WebRequest command line
495 | try {
496 | $wr = Invoke-WebRequest -Uri $url -UseBasicParsing -UseDefaultCredentials -TimeoutSec 120
497 | FetchResources $url $wr.Images
498 | FetchResources $url $wr.Scripts
499 | Write-Host "."
500 | }
501 | catch {
502 | $httpCode = $_.Exception.Response.StatusCode.Value__
503 | if ($httpCode) {
504 | WriteLog " [$httpCode]" Yellow
505 | }
506 | else {
507 | Write-Host " "
508 | }
509 | }
510 | }
511 | }
512 |
513 | Function FetchResources($baseUrl, $resources) {
514 | # Download additional HTTP files
515 | [uri]$uri = $baseUrl
516 | $rootUrl = $uri.Scheme + "://" + $uri.Authority
517 |
518 | # Loop
519 | $counter = 0
520 | foreach ($res in $resources) {
521 | # Support both abosolute and relative URLs
522 | $resUrl = $res.src
523 | if ($resUrl.ToUpper().Contains("HTTP")) {
524 | $fetchUrl = $res.src
525 | }
526 | else {
527 | if (!$resUrl.StartsWith("/")) {
528 | $resUrl = "/" + $resUrl
529 | }
530 | $fetchUrl = $rootUrl + $resUrl
531 | }
532 |
533 | # Progress
534 | if (!$skipprogress) {
535 | Write-Progress -Activity "Opening " -Status $fetchUrl -PercentComplete (($counter / $resources.Count) * 100)
536 | $counter++
537 | }
538 |
539 | # Execute
540 | Invoke-WebRequest -UseDefaultCredentials -UseBasicParsing -Uri $fetchUrl -TimeoutSec 120 | Out-Null
541 | Write-Host "." -NoNewLine
542 | }
543 | if (!$skipprogress) {
544 | Write-Progress -Activity "Completed" -Completed
545 | }
546 | }
547 |
548 | Function ShowW3WP() {
549 | # Total memory used by IIS worker processes
550 | $mb = [Math]::Round((Get-Process W3WP -ErrorAction SilentlyContinue | Select-Object workingset64 | Measure-Object workingset64 -Sum).Sum / 1MB)
551 | WriteLog "Total W3WP = $mb MB" "Green"
552 | }
553 |
554 | Function CreateLog() {
555 | # EventLog - create source if missing
556 | if (!(Get-EventLog -LogName Application -Source "SPBestWarmUp" -Newest 1 -ErrorAction SilentlyContinue)) {
557 | New-EventLog -LogName Application -Source "SPBestWarmUp" -ErrorAction SilentlyContinue | Out-Null
558 | }
559 | }
560 |
561 | Function WriteLog($text, $color) {
562 | $global:msg += "`n$text"
563 | if ($color) {
564 | Write-Host $text -Fore $color
565 | }
566 | else {
567 | Write-Output $text
568 | }
569 | }
570 |
571 | Function SaveLog($id, $txt, $exception) {
572 | # EventLog
573 | if (!$skiplog) {
574 | if (!$exception) {
575 | # Success
576 | $global:msg += $txt
577 | Write-EventLog -LogName Application -Source "SPBestWarmUp" -EntryType Information -EventId $id -Message $global:msg
578 | }
579 | else {
580 | # Error
581 | $global:msg += "ERROR`n"
582 | $global:msg += $exception.Message + "`n" + $exception.ItemName
583 | Write-EventLog -LogName Application -Source "SPBestWarmUp" -EntryType Warning -EventId $id -Message $global:msg
584 | }
585 | }
586 | }
587 |
588 | # Main
589 |
590 | # Transcript
591 | if ($transcript) {
592 | $startTime = (Get-Date)
593 | $datestamp = $startTime.ToString("yyyy-MM-dd-hh-mm-ss")
594 | Start-Transcript "SPBestWarmup-$datestamp.log"
595 | }
596 |
597 | # Log
598 | $global:msg = ""
599 | CreateLog
600 | $cmdpath = (Resolve-Path .\).Path
601 | $cmdpath += "\SPBestWarmUp.ps1"
602 | $ver = $PSVersionTable.PSVersion
603 | WriteLog "SPBestWarmUp v2.4.22 (last updated 2023-12-09)`n------`n"
604 | WriteLog "Path: $cmdpath"
605 | WriteLog "PowerShell Version: $ver"
606 |
607 | # Suppress progress bar display
608 | if ($skipprogress) {
609 | $ProgressPreference = 'SilentlyContinue'
610 | }
611 |
612 | # Check Permission Level
613 | if (!$skipadmincheck -and !([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
614 | Write-Warning "You do not have elevated Administrator rights to run this script.`nPlease re-run as Administrator."
615 | break
616 | }
617 | else {
618 | try {
619 | # SharePoint cmdlets
620 | Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue | Out-Null
621 |
622 | # Task Scheduler
623 | $tasks = schtasks /query /fo csv | ConvertFrom-Csv
624 | $spb = $tasks | Where-Object { $_.TaskName -eq "\SPBestWarmUp" }
625 | if (!$spb -and !$install -and !$installfarm) {
626 | Write-Warning "Tip: to install on Task Scheduler run the command ""SPBestWarmUp.ps1 -install"""
627 | }
628 | if ($install -or $installfarm -or $uninstall) {
629 | Installer
630 | SaveLog 2 "Installed to Task Scheduler"
631 | break
632 | }
633 | if ($uninstall) {
634 | break
635 | }
636 |
637 | # Core
638 | ShowW3WP
639 | WarmUp
640 | ShowW3WP
641 |
642 | # Log
643 | SaveLog 1 "Operation completed successfully"
644 | }
645 | catch {
646 | SaveLog 101 "ERROR" $_.Exception
647 | }
648 |
649 | # Transcript
650 | if ($transcript) {
651 | Stop-Transcript
652 | }
653 | }
654 |
--------------------------------------------------------------------------------
/SPBestWarmUp.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | PT1H
7 | P1D
8 | false
9 |
10 | 2017-01-25T01:00:00
11 | true
12 |
13 | 1
14 |
15 |
16 |
17 | true
18 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-IIS-IISReset'] and EventID=3201]]</Select></Query></QueryList>
19 | PT1M
20 |
21 |
22 | true
23 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5074]]</Select></Query></QueryList>
24 | PT1M
25 |
26 |
27 | true
28 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5075]]</Select></Query></QueryList>
29 | PT1M
30 |
31 |
32 | true
33 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5076]]</Select></Query></QueryList>
34 | PT1M
35 |
36 |
37 | true
38 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5077]]</Select></Query></QueryList>
39 | PT1M
40 |
41 |
42 | true
43 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5078]]</Select></Query></QueryList>
44 | PT1M
45 |
46 |
47 | true
48 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5079]]</Select></Query></QueryList>
49 | PT1M
50 |
51 |
52 | true
53 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5080]]</Select></Query></QueryList>
54 |
55 |
56 | true
57 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5081]]</Select></Query></QueryList>
58 | PT1M
59 |
60 |
61 | true
62 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5117]]</Select></Query></QueryList>
63 | PT1M
64 |
65 |
66 | true
67 | <QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-WAS'] and EventID=5186]]</Select></Query></QueryList>
68 | PT1M
69 |
70 |
71 | true
72 | PT5M
73 |
74 |
75 |
76 |
77 |
78 | Password
79 | HighestAvailable
80 |
81 |
82 |
83 | IgnoreNew
84 | true
85 | true
86 | true
87 | false
88 | false
89 |
90 | true
91 | false
92 |
93 | true
94 | true
95 | false
96 | false
97 | false
98 | P3D
99 | 7
100 |
101 |
102 |
103 | PowerShell.exe
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/doc/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spjeff/spbestwarmup/ef6f4a13f6fbe1794e8ef9bfc2ec08691767ce21/doc/1.jpg
--------------------------------------------------------------------------------
/doc/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spjeff/spbestwarmup/ef6f4a13f6fbe1794e8ef9bfc2ec08691767ce21/doc/2.jpg
--------------------------------------------------------------------------------
/doc/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spjeff/spbestwarmup/ef6f4a13f6fbe1794e8ef9bfc2ec08691767ce21/doc/3.jpg
--------------------------------------------------------------------------------
/doc/download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spjeff/spbestwarmup/ef6f4a13f6fbe1794e8ef9bfc2ec08691767ce21/doc/download.png
--------------------------------------------------------------------------------