@@ -278,7 +278,7 @@ param(
278
278
# ##Internal params
279
279
# Version
280
280
$Vers = " 5.1.0"
281
- $VersDate = " 2025-02-02 "
281
+ $VersDate = " 2025-02-03 "
282
282
$TwoMonthsFromRelease = [datetime ]::ParseExact(" $VersDate " , ' yyyy-MM-dd' , $null ).AddMonths(2 )
283
283
$NowDate = Get-Date
284
284
# Get script path
@@ -812,7 +812,9 @@ function Export-PlansAndDeadlocks {
812
812
[Parameter (Position = 5 , Mandatory = $false )]
813
813
[string ] $FPrefix = ' ' ,
814
814
[Parameter (Position = 6 , Mandatory = $false )]
815
- [switch ] $DebugInfo
815
+ [switch ] $DebugInfo ,
816
+ [Parameter (Position = 7 , Mandatory = $false )]
817
+ [switch ] $FileNameFromColumn
816
818
)
817
819
try {
818
820
# if ($DebugInfo) {
@@ -824,11 +826,20 @@ function Export-PlansAndDeadlocks {
824
826
foreach ($row in $DataTable ) {
825
827
$i += 1
826
828
$FileName = " -- N/A --"
827
- if ($DataTable.Rows [$RowNum ][$XMLColName ] -ne [System.DBNull ]::Value){
828
- $FileName = $FPrefix + ' _' + $i + ' .' + $OutputType
829
+ if (($DataTable.Rows [$RowNum ][$XMLColName ] -ne [System.DBNull ]::Value) -and
830
+ (($DataTable.Rows [$RowNum ][$FNameColName ] -like " Deadlock*" ) -or
831
+ ($XMLColName -ne " deadlock_graph" )) ) {
832
+ if ($FileNameFromColumn ) {
833
+ $FileName = $DataTable.Rows [$RowNum ][$FNameColName ]
834
+ }
835
+ else {
836
+ $FileName = $FPrefix + ' _' + $i + ' .' + $OutputType
837
+ }
829
838
$DataTable.Rows [$RowNum ][$XMLColName ] | Format-XML | Set-Content - Path " $FileDir \$FileName " - Force
830
839
}
831
- $DataTable.Rows [$RowNum ][$FNameColName ] = $FileName
840
+ if ($FileNameFromColumn -eq $false ) {
841
+ $DataTable.Rows [$RowNum ][$FNameColName ] = $FileName
842
+ }
832
843
$RowNum += 1
833
844
}
834
845
@@ -841,6 +852,35 @@ function Export-PlansAndDeadlocks {
841
852
}
842
853
}
843
854
855
+ function Add-QueryName {
856
+ param (
857
+ [Parameter (Position = 0 , Mandatory = $true )]
858
+ [System.Data.DataTable ] $DataTable ,
859
+ [Parameter (Position = 1 , Mandatory = $true )]
860
+ [string ] $QueryNameColName ,
861
+ [Parameter (Position = 2 , Mandatory = $true )]
862
+ [string ] $QueryTextColName ,
863
+ [Parameter (Position = 3 , Mandatory = $true )]
864
+ [string ] $QPrefix
865
+ )
866
+ try {
867
+ $RowNum = 0
868
+ $i = 0
869
+ foreach ($row in $DataTable ) {
870
+ if ($DataTable.Rows [$RowNum ][$QueryTextColName ] -ne [System.DBNull ]::Value) {
871
+ $i += 1
872
+ $QueryName = $QPrefix + " _" + $i + " .query"
873
+ }
874
+ else { $QueryName = " -- N/A --" }
875
+ $DataTable.Rows [$RowNum ][$QueryNameColName ] = $QueryName
876
+ $RowNum += 1
877
+ }
878
+ }
879
+ catch {
880
+ Write-Host " Error adding query names: $_ " - ForegroundColor Red
881
+ }
882
+ }
883
+
844
884
function Convert-TableToExcel {
845
885
param (
846
886
[Parameter (Position = 0 , Mandatory = $true )]
@@ -1298,7 +1338,7 @@ if ([string]::IsNullOrEmpty($ServerName)) {
1298
1338
if (! ([string ]$AdvOptions = Read-Host - Prompt " Show advanced options?(empty defaults to N)[Y/N]" )) {
1299
1339
$AdvOptions = " N"
1300
1340
}
1301
- if ($AdvOptions -eq " Y" ){
1341
+ if ($AdvOptions -eq " Y" ) {
1302
1342
# #Get top N queries from cache
1303
1343
[int ]$CacheTop = Read-Host - Prompt " Number of top resource intensive queries to return?(empty defaults to 10)"
1304
1344
@@ -1837,10 +1877,10 @@ $Query = "SELECT CAST(DATEDIFF(HH, [sqlserver_start_time], GETDATE()) / 24.00 AS
1837
1877
$Query = $Query + " `n FROM [sys].[dm_os_sys_info];"
1838
1878
Invoke-PSBlitzQuery - QueryIn $Query - StepNameIn " Uptime check" - ConnStringIn $ConnString - CmdTimeoutIn 100
1839
1879
if ($global :StepOutcome -eq " Success" ) {
1840
- if ($global :PSBlitzSet.Tables [0 ].Rows[0 ][" uptime_days" ] -lt 7.00 ){
1880
+ if ($global :PSBlitzSet.Tables [0 ].Rows[0 ][" uptime_days" ] -lt 7.00 ) {
1841
1881
[string ]$DaysUp = $global :PSBlitzSet.Tables [0 ].Rows[0 ][" uptime_days" ]
1842
- Write-Host " Warning: Instance uptime is less than 7 days - $DaysUp " - Fore Red
1843
- Write-Host " ->Diagnostics data might not be reliable with less than 7 days of uptime." - Fore Red
1882
+ Write-Host " Warning: Instance uptime is less than 7 days - $DaysUp " - Fore Red
1883
+ Write-Host " ->Diagnostics data might not be reliable with less than 7 days of uptime." - Fore Red
1844
1884
}
1845
1885
Invoke-ClearVariables PSBlitzSet
1846
1886
}
@@ -2034,20 +2074,8 @@ $htmlTable4
2034
2074
2035
2075
$htmlTable2 = Convert-TableToHtml $TempTabTbl - DebugInfo:$DebugInfo
2036
2076
2037
- # Add query name
2038
- $RowNum = 0
2039
- $i = 0
2040
- foreach ($row in $TempDBSessTbl ) {
2041
- if ($TempDBSessTbl.Rows [$RowNum ][" query_text" ] -ne [System.DBNull ]::Value) {
2042
- $i += 1
2043
- $QueryName = " TempDB_" + $i + " .query"
2044
-
2045
- }
2046
- else { $QueryName = " " }
2047
- $TempDBSessTbl.Rows [$RowNum ][" query" ] = $QueryName
2048
- $RowNum += 1
2049
- }
2050
-
2077
+ Add-QueryName $TempDBSessTbl " query" " query_text" " TempDB"
2078
+
2051
2079
$htmlTable3 = Convert-TableToHtml $TempDBSessTbl - ExclCols " query_text" - DebugInfo:$DebugInfo - AnchorFromHere - AnchorIDs " TempDB"
2052
2080
2053
2081
$htmlTable4 = Convert-QueryTableToHtml $TempDBSessTbl - DebugInfo:$DebugInfo - Cols " query" , " query_text" - AnchorToHere - AnchorID " TempDB"
@@ -2160,26 +2188,9 @@ $htmlTable2
2160
2188
Write-Host " ->No open transactions found."
2161
2189
}
2162
2190
else {
2163
- # #Exporting execution plans to file
2164
- # Set counter used for row retrieval
2165
- [int ]$RowNum = 0
2166
- $i = 0
2167
- # loop through each row
2168
- if ($DebugInfo ) {
2169
- Write-Host " ->Exporting execution plans" - fore yellow
2170
- }
2171
- foreach ($row in $AcTranTbl ) {
2172
- $i += 1
2173
- if ($AcTranTbl.Rows [$RowNum ][" current_plan" ] -ne [System.DBNull ]::Value) {
2174
- [string ]$SQLPlanFile = $AcTranTbl.Rows [$RowNum ][" current_plan_file" ]
2175
- $AcTranTbl.Rows [$RowNum ][" current_plan" ] | Format-XML | Set-Content - Path $PlanOutDir \$ ($SQLPlanFile ) - Force
2176
- }
2177
- if ($AcTranTbl.Rows [$RowNum ][" most_recent_plan" ] -ne [System.DBNull ]::Value) {
2178
- [string ]$SQLPlanFile = $AcTranTbl.Rows [$RowNum ][" most_recent_plan_file" ]
2179
- $AcTranTbl.Rows [$RowNum ][" most_recent_plan" ] | Format-XML | Set-Content - Path $PlanOutDir \$ ($SQLPlanFile ) - Force
2180
- }
2181
- $RowNum += 1
2182
- }
2191
+
2192
+ Export-PlansAndDeadlocks $AcTranTbl $PlanOutDir " current_plan" " current_plan_file" - DebugInfo:$DebugInfo - FileNameFromColumn
2193
+ Export-PlansAndDeadlocks $AcTranTbl $PlanOutDir " most_recent_plan" " most_recent_plan_file" - DebugInfo:$DebugInfo - FileNameFromColumn
2183
2194
if ($ToHTML -eq " Y" ) {
2184
2195
2185
2196
$tableName = " Open transaction info"
@@ -2825,25 +2836,8 @@ $JumpToTop
2825
2836
if ($DebugInfo ) {
2826
2837
Write-Host " ->Exporting execution plans for $SortOrder " - fore yellow
2827
2838
}
2828
- <# Set counter used for row retrieval
2829
- $RowNum = 0
2830
- #Setting $i to 0
2831
- $i = 0
2832
- foreach ($row in $BlitzCacheTbl) {
2833
- #Increment file name counter
2834
- $i += 1
2835
- $SQLPlanFile = "-- N/A --"
2836
- #Get only the column storing the execution plan data that's not NULL and write it to a file
2837
- if ($BlitzCacheTbl.Rows[$RowNum]["Query Plan"] -ne [System.DBNull]::Value) {
2838
- $SQLPlanFile = $FileSOrder + "_" + $i + ".sqlplan"
2839
- $BlitzCacheTbl.Rows[$RowNum]["Query Plan"] | Format-XML | Set-Content -Path "$PlanOutDir\$SQLPlanFile" -Force
2840
- }
2841
- $BlitzCacheTbl.Rows[$RowNum]["SQLPlan File"] = $SQLPlanFile
2842
- #Increment row retrieval counter
2843
- $RowNum += 1
2844
- }
2845
- #>
2846
- Export-PlansAndDeadlocks $BlitzCacheTbl $PlanOutDir " Query Plan" " SQLPlan File" - FPrefix $FileSOrder - DebugInfo:$DebugInfo
2839
+
2840
+ Export-PlansAndDeadlocks $BlitzCacheTbl $PlanOutDir " Query Plan" " SQLPlan File" - FPrefix $FileSOrder - DebugInfo:$DebugInfo
2847
2841
2848
2842
# #Add database names to array
2849
2843
if (([string ]::IsNullOrEmpty($CheckDB )) -and ($IsAzureSQLDB -eq $false )) {
@@ -2899,19 +2893,8 @@ $JumpToTop
2899
2893
2900
2894
if ($ToHTML -eq " Y" ) {
2901
2895
$SheetName = $SheetName -replace " Top Queries - " , " "
2902
-
2903
- $RowNum = 0
2904
- $i = 0
2905
- foreach ($row in $BlitzCacheTbl ) {
2906
- if ($BlitzCacheTbl.Rows [$RowNum ][" Query Text" ] -ne [System.DBNull ]::Value) {
2907
- $i += 1
2908
- $QueryName = $FileSOrder + " _" + $i + " .query"
2909
- }
2910
- else { $QueryName = " " }
2911
- $BlitzCacheTbl.Rows [$RowNum ][" Query" ] = $QueryName
2912
- $RowNum += 1
2913
- }
2914
-
2896
+
2897
+ Add-QueryName $BlitzCacheTbl " Query" " Query Text" $FileSOrder
2915
2898
2916
2899
$htmlTable1 = Convert-TableToHtml $BlitzCacheTbl - NoCaseChange - ExclCols " Query Text" , " Query Plan" - DebugInfo:$DebugInfo - AnchorFromHere - AnchorIDs $FileSOrder
2917
2900
@@ -3286,39 +3269,11 @@ ELSE IF ( (SELECT PARSENAME(CONVERT(NVARCHAR(128), SERVERPROPERTY ('PRODUCTVERSI
3286
3269
Write-Host " ->Exporting execution plans" - fore yellow
3287
3270
}
3288
3271
3289
- # Set counter used for row retrieval
3290
- <# $RowNum = 0
3291
- #Setting $i to 0
3292
- $i = 0
3293
- foreach ($row in $BlitzQSTbl) {
3294
- #Increment file name counter
3295
- $i += 1
3296
- $SQLPlanFile = "-- N/A --"
3297
- #Get only the column storing the execution plan data that's not NULL and write it to a file
3298
- if ($BlitzQSTbl.Rows[$RowNum]["query_plan_xml"] -ne [System.DBNull]::Value) {
3299
- $SQLPlanFile = "QueryStore_" + $i + ".sqlplan"
3300
- $BlitzQSTbl.Rows[$RowNum]["query_plan_xml"] | Format-XML | Set-Content -Path "$PlanOutDir\$SQLPlanFile" -Force
3301
- }
3302
- $BlitzQSTbl.Rows[$RowNum]["SQLPlan File"] = $SQLPlanFile
3303
- #Increment row retrieval counter
3304
- $RowNum += 1
3305
- }
3306
- #>
3307
3272
Export-PlansAndDeadlocks $BlitzQSTbl $PlanOutDir " query_plan_xml" " SQLPlan File" - FPrefix " QueryStore" - DebugInfo:$DebugInfo
3308
3273
3309
3274
if ($ToHTML -eq " Y" ) {
3310
3275
3311
- $RowNum = 0
3312
- $i = 0
3313
- foreach ($row in $BlitzQSTbl ) {
3314
- if ($BlitzQSTbl.Rows [$RowNum ][" query_sql_text" ] -ne [System.DBNull ]::Value) {
3315
- $i += 1
3316
- $QueryName = " QueryStore_" + $i + " .query"
3317
- }
3318
- else { $QueryName = " " }
3319
- $BlitzQSTbl.Rows [$RowNum ][" Query" ] = $QueryName
3320
- $RowNum += 1
3321
- }
3276
+ Add-QueryName $BlitzQSTbl " Query" " query_sql_text" " QueryStore"
3322
3277
3323
3278
$htmlTable1 = Convert-TableToHtml $BlitzQSTbl - ExclCols " query_sql_text" , " query_plan_xml" - CSSClass " QueryStoreTab sortable" - AnchorFromHere - AnchorIDs " QueryStore" - DebugInfo:$DebugInfo
3324
3279
@@ -3452,28 +3407,11 @@ ELSE IF ( (SELECT PARSENAME(CONVERT(NVARCHAR(128), SERVERPROPERTY ('PRODUCTVERSI
3452
3407
$BlitzIxTbl = $global :PSBlitzSet.Tables [0 ]
3453
3408
if (" 0" , " 4" -Contains $Mode ) {
3454
3409
# Export sample execution plans for missing indexes (SQL Server 2019 only)
3455
- # Since we're already looping through the result set here, might as well add and
3456
- # populate the plan file name column as well
3457
3410
if ($DebugInfo ) {
3458
3411
Write-Host " ->Exporting missing index sample execution plans (if any)" - fore yellow
3459
3412
}
3460
3413
3461
- <# $RowNum = 0
3462
- $i = 0
3463
- foreach ($row in $BlitzIxTbl) {
3464
- if ($BlitzIxTbl.Rows[$RowNum]["Finding"] -like "*Missing Index") {
3465
- $SQLPlanFile = "--N/A--"
3466
- $i += 1
3467
- if ($BlitzIxTbl.Rows[$RowNum]["Sample Query Plan"] -ne [System.DBNull]::Value) {
3468
- $SQLPlanFile = "MissingIndex_$i.sqlplan"
3469
- $BlitzIxTbl.Rows[$RowNum]["Sample Query Plan"] | Format-XML | Set-Content -Path "$PlanOutDir\$SQLPlanFile" -Force
3470
- }
3471
- $BlitzIxTbl.Rows[$RowNum]["Sample Plan File"] = $SQLPlanFile
3472
- }
3473
- $RowNum += 1
3474
- }
3475
- #>
3476
- Export-PlansAndDeadlocks $BlitzIxTbl $PlanOutDir " Sample Query Plan" " Sample Plan File" - FPrefix " MissingIndex" - DebugInfo:$DebugInfo
3414
+ Export-PlansAndDeadlocks $BlitzIxTbl $PlanOutDir " Sample Query Plan" " Sample Plan File" - FPrefix " MissingIndex" - DebugInfo:$DebugInfo
3477
3415
}
3478
3416
if ($ToHTML -eq " Y" ) {
3479
3417
@@ -3615,55 +3553,18 @@ ELSE IF ( (SELECT PARSENAME(CONVERT(NVARCHAR(128), SERVERPROPERTY ('PRODUCTVERSI
3615
3553
}
3616
3554
else {
3617
3555
# #Exporting deadlock graphs to file
3618
- # Set counter used for row retrieval
3619
- [int ]$RowNum = 0
3620
- # Setting $i to 0
3621
- # $i = 1
3622
3556
if ($DebugInfo ) {
3623
3557
Write-Host " ->Exporting deadlock graphs (if any)" - fore yellow
3624
3558
}
3625
- foreach ($row in $TblLockDtl ) {
3626
- <#
3627
- Get only the column storing the deadlock graph data that's not NULL, limit to one export per event by filtering for VICTIM, and write it to a file
3628
- #>
3629
- if (($TblLockDtl.Rows [$RowNum ][" deadlock_graph" ] -ne [System.DBNull ]::Value) -and ($TblLockDtl.Rows [$RowNum ][" deadlock_group" ] -like " *VICTIM*" )) {
3630
- # format the event date to append to file name
3631
- # [string]$DLDate =
3632
- [string ]$DLFile = $TblLockDtl.Rows [$RowNum ][" deadlock_graph_file" ]
3633
- # write .xdl file
3634
- $TblLockDtl.Rows [$RowNum ][" deadlock_graph" ] | Format-XML | Set-Content - Path " $XDLOutDir \$DLFile " - Force
3635
- # $TblLockDtl.Rows[$RowNum]["deadlock_graph_file"] = $DLFile
3636
- $i += 1
3637
- }
3638
- # Increment row retrieval counter
3639
- $RowNum += 1
3640
- }
3559
+
3560
+ Export-PlansAndDeadlocks $TblLockDtl $XDLOutDir " deadlock_graph" " deadlock_graph_file" - DebugInfo:$DebugInfo - FileNameFromColumn
3641
3561
3642
3562
# #Exporting execution plans to file
3643
3563
if ($DebugInfo ) {
3644
3564
Write-Host " ->Exporting execution plans related to deadlocks." - fore yellow
3645
3565
}
3646
- # Set counter used for row retrieval
3647
- $RowNum = 0
3648
- # Setting $i to 0
3649
- $i = 0
3650
3566
3651
- foreach ($row in $TblLockPlans ) {
3652
- # Increment file name counter
3653
- $i += 1
3654
- $SQLPlanFile = " -- N/A --"
3655
- $QueryName = " -- N/A --"
3656
- # Get only the column storing the execution plan data that's not NULL and write it to a file
3657
- if ($TblLockPlans.Rows [$RowNum ][" query_plan" ] -ne [System.DBNull ]::Value) {
3658
- $SQLPlanFile = " Deadlock_" + $i + " .sqlplan"
3659
- $QueryName = " DeadlockPlan_" + $i + " .query"
3660
- $TblLockPlans.Rows [$RowNum ][" query_plan" ] | Format-XML | Set-Content - Path " $PlanOutDir \$SQLPlanFile " - Force
3661
- }
3662
- $TblLockPlans.Rows [$RowNum ][" sqlplan_file" ] = $SQLPlanFile
3663
- $TblLockPlans.Rows [$RowNum ][" query" ] = $QueryName
3664
- # Increment row retrieval counter
3665
- $RowNum += 1
3666
- }
3567
+ Export-PlansAndDeadlocks $TblLockPlans $PlanOutDir " query_plan" " sqlplan_file" - FPrefix " DeadlockPlan" - DebugInfo:$DebugInfo
3667
3568
3668
3569
if ($ToHTML -eq " Y" ) {
3669
3570
@@ -3681,6 +3582,8 @@ ELSE IF ( (SELECT PARSENAME(CONVERT(NVARCHAR(128), SERVERPROPERTY ('PRODUCTVERSI
3681
3582
3682
3583
$htmlTable3 = Convert-QueryTableToHtml $TblLockDtl - Cols " query" , " query_text" - AnchorToHere - AnchorID " DeadlockDtlTable" - DebugInfo:$DebugInfo
3683
3584
3585
+ Add-QueryName $TblLockPlans " query" " query_text" " DeadlockPlan"
3586
+
3684
3587
$htmlTable4 = Convert-TableToHtml $TblLockPlans - AnchorFromHere - ExclCols " query_text" , " query_plan" - AnchorIDs " DeadlockPlan" - DebugInfo:$DebugInfo
3685
3588
3686
3589
$htmlTable5 = Convert-QueryTableToHtml $TblLockPlans - Cols " query" , " query_text" - AnchorToHere - AnchorID " DeadlockPlan" - DebugInfo:$DebugInfo
@@ -4116,19 +4019,8 @@ finally {
4116
4019
if ($DebugInfo ) {
4117
4020
Write-Host " ->Exporting execution plans" - fore yellow
4118
4021
}
4119
- $RowNum = 0
4120
- $i = 0
4121
- foreach ($row in $BlitzWhoAggTbl ) {
4122
- $i += 1
4123
- $SQLPlanFile = " -- N/A --"
4124
- if ($BlitzWhoAggTbl.Rows [$RowNum ][" query_plan" ] -ne [System.DBNull ]::Value) {
4125
-
4126
- $SQLPlanFile = " RunningNow_" + $i + " .sqlplan"
4127
- $BlitzWhoAggTbl.Rows [$RowNum ][" query_plan" ] | Format-XML | Set-Content - Path " $PlanOutDir \$SQLPlanFile " - Force
4128
- }
4129
- $BlitzWhoAggTbl.Rows [$RowNum ][" sqlplan_file" ] = $SQLPlanFile
4130
- $RowNum += 1
4131
- }
4022
+
4023
+ Export-PlansAndDeadlocks $BlitzWhoAggTbl $PlanOutDir " query_plan" " sqlplan_file" - FPrefix " RunningNow" - DebugInfo:$DebugInfo
4132
4024
4133
4025
# Get capture time-frame
4134
4026
$BtilzWhoStartTime = $BlitzWhoTbl | Sort-Object - Property " CheckDate" | Select-Object - ExpandProperty " CheckDate" - First 1
@@ -4161,29 +4053,15 @@ finally {
4161
4053
Save-HtmlFile $html " BlitzWho.html" $HTMLOutDir $DebugInfo
4162
4054
Invoke-ClearVariables html, htmlTable
4163
4055
4164
- # $BlitzWhoAggTbl.Columns.Add("Query", [string]) | Out-Null
4165
- $RowNum = 0
4166
- $i = 0
4167
-
4168
- foreach ($row in $BlitzWhoAggTbl ) {
4169
- $i += 1
4170
- if ($BlitzWhoAggTbl.Rows [$RowNum ][" query_text" ] -ne [System.DBNull ]::Value) {
4171
- $QueryName = " RunningNow_" + $i + " .query"
4172
- }
4173
- else { $QueryName = " -- N/A --" }
4174
- $BlitzWhoAggTbl.Rows [$RowNum ][" Query" ] = $QueryName
4175
- $RowNum += 1
4176
- }
4177
4056
$HtmlTabName = " Aggregated Session Activity"
4178
4057
if (! ([string ]::IsNullOrEmpty($CheckDB ))) {
4179
4058
$HtmlTabName += " for $CheckDB "
4180
4059
}
4181
4060
elseif ($IsAzureSQLDB ) {
4182
4061
$HtmlTabName += " for $ASDBName "
4183
4062
}
4184
-
4063
+ Add-QueryName $BlitzWhoAggTbl " Query " " query_text " " RunningNow "
4185
4064
$htmlTable = Convert-TableToHtml $BlitzWhoAggTbl - CSSClass " ActiveSessionsTab sortable" - AnchorFromHere - AnchorIDs " RunningNow" - ExclCols " query_text" , " query_plan" - DebugInfo:$DebugInfo
4186
-
4187
4065
$htmlTable1 = Convert-QueryTableToHtml $BlitzWhoAggTbl - Cols " query" , " query_text" - AnchorToHere - AnchorID " RunningNow" - DebugInfo:$DebugInfo
4188
4066
4189
4067
$html = $HTMLPre + @"
0 commit comments