From c4a4fe7cadf8b83108fc94b7d5f146afaccf942b Mon Sep 17 00:00:00 2001 From: iserrano76 Date: Wed, 31 Jan 2024 19:14:18 +0100 Subject: [PATCH 1/3] Change from Write-SimpleLogFile to OutputOverrides --- .../AVTester/Start-SleepWithProgress.ps1 | 55 -------- .../AVTester/Test-ExchAVExclusions.ps1 | 132 ++++++++++-------- Diagnostics/AVTester/Write-SimpleLogFile.ps1 | 91 ------------ docs/Diagnostics/Test-ExchAVExclusions.md | 5 +- 4 files changed, 76 insertions(+), 207 deletions(-) delete mode 100644 Diagnostics/AVTester/Start-SleepWithProgress.ps1 delete mode 100644 Diagnostics/AVTester/Write-SimpleLogFile.ps1 diff --git a/Diagnostics/AVTester/Start-SleepWithProgress.ps1 b/Diagnostics/AVTester/Start-SleepWithProgress.ps1 deleted file mode 100644 index 8790ee787f..0000000000 --- a/Diagnostics/AVTester/Start-SleepWithProgress.ps1 +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -<# -.NOTES - Name: Start-SleepWithProgress.ps1 - Requires: NA - Major Release History: - 06/22/2021 - Initial Release - -.SYNOPSIS -Sleep with a progress bar managing the bar and the countdown. - -.DESCRIPTION -Sleeps X amount of time showing a progress bar. - -.PARAMETER SleepTime -Amount of time to sleep. - -.PARAMETER Message -Message to display on the progress bar. - -.OUTPUTS -Progress bar to screen - -.EXAMPLE -Start-SleepWithProgress -SleepTime 60 -Message "Waiting on Process to complete" - -Creates a Progress bar with the message "Waiting on Process to complete" -Counts down 60 seconds and updates the Progress bar during the process. - -#> -function Start-SleepWithProgress { - [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Start-Sleep does not use -WhatIf')] - param( - [Parameter(Mandatory = $true)] - [int]$SleepTime, - - [string]$Message = "Sleeping" - - ) - - # Loop Number of seconds you want to sleep - for ($i = 0; $i -le $SleepTime; $i++) { - $timeLeft = ($SleepTime - $i) - - # Progress bar showing progress of the sleep - Write-Progress -Activity $Message -CurrentOperation "$timeLeft More Seconds" -PercentComplete (($i / $SleepTime) * 100) -Status " " - - # Sleep 1 second - Start-Sleep 1 - } - - Write-Progress -Completed -Activity $Message -Status " " -} diff --git a/Diagnostics/AVTester/Test-ExchAVExclusions.ps1 b/Diagnostics/AVTester/Test-ExchAVExclusions.ps1 index 1643a9489c..7be51d23f7 100644 --- a/Diagnostics/AVTester/Test-ExchAVExclusions.ps1 +++ b/Diagnostics/AVTester/Test-ExchAVExclusions.ps1 @@ -37,9 +37,6 @@ Generally should not be needed unless all folders pass without -Recuse but AV is .PARAMETER WaitingTimeForAVAnalysisInMinutes Set the waiting time for AV to analyze the EICAR files. Default is 5 minutes. -.PARAMETER OpenLog -Open the log file after the script finishes. - .PARAMETER SkipVersionCheck Skip script version verification. @@ -48,10 +45,10 @@ Just update script version to latest one. .OUTPUTS Log file: -$PSScriptRoot\ExchAvExclusions.log +$PSScriptRoot\Test-ExchAvExclusions-#DataTime#.txt List of Scanned Folders: -$PSScriptRoot\BadExclusions.txt +$PSScriptRoot\BadExclusions-#DataTime#.txt .EXAMPLE .\Test-ExchAVExclusions.ps1 @@ -73,9 +70,6 @@ param ( [Parameter(ParameterSetName = "Test")] [switch]$Recurse, - [Parameter(ParameterSetName = "Test")] - [switch]$OpenLog, - [Parameter(ParameterSetName = "Test")] [switch]$SkipVersionCheck, @@ -87,7 +81,34 @@ param ( . $PSScriptRoot\..\..\Shared\Confirm-ExchangeShell.ps1 . $PSScriptRoot\..\..\Shared\Get-ExchAVExclusions.ps1 . $PSScriptRoot\..\..\Shared\ScriptUpdateFunctions\Test-ScriptVersion.ps1 -. $PSScriptRoot\Write-SimpleLogFile.ps1 +. $PSScriptRoot\..\..\Shared\LoggerFunctions.ps1 +. $PSScriptRoot\..\..\Shared\OutputOverrides\Write-Host.ps1 +. $PSScriptRoot\..\..\Shared\OutputOverrides\Write-Warning.ps1 +. $PSScriptRoot\..\..\Shared\OutputOverrides\Write-Verbose.ps1 +. $PSScriptRoot\..\..\Shared\OutputOverrides\Write-Progress.ps1 + +function Write-DebugLog ($message) { + if (![string]::IsNullOrEmpty($message)) { + $Script:DebugLogger = $Script:DebugLogger | Write-LoggerInstance $message + } +} + +function Write-HostLog ($message) { + if (![string]::IsNullOrEmpty($message)) { + $Script:WarningLogger = $Script:DebugLogger | Write-LoggerInstance $message + $Script:HostLogger = $Script:HostLogger | Write-LoggerInstance $message + } +} + +$LogFileName = "Test-ExchAvExclusions" +$dateTime = (Get-Date).ToString("yyyyMMddhhmmss") +$Script:DebugLogger = Get-NewLoggerInstance -LogName "$LogFileName-Debug-$dateTime" -LogDirectory $PSScriptRoot -AppendDateTimeToFileName $false -ErrorAction SilentlyContinue +$Script:HostLogger = Get-NewLoggerInstance -LogName "$LogFileName-Results-$dateTime" -LogDirectory $PSScriptRoot -AppendDateTimeToFileName $false -ErrorAction SilentlyContinue + +SetWriteHostAction ${Function:Write-HostLog} +SetWriteProgressAction ${Function:Write-DebugLog} +SetWriteVerboseAction ${Function:Write-DebugLog} +SetWriteWarningAction ${Function:Write-HostLog} $BuildVersion = "" @@ -108,15 +129,9 @@ if ((-not($SkipVersionCheck)) -and return } -# Log file name -$LogFileName = Join-Path $PSScriptRoot ExchAvExclusions.log - -# Open log file if switched -if ($OpenLog) { Write-SimpleLogFile -OpenLog -String " " -LogFile $LogFileName } - # Confirm that we are an administrator if (-not (Confirm-Administrator)) { - Write-Error "Please run as Administrator" + Write-Host "[ERROR]: Please run as Administrator" -ForegroundColor Red exit } @@ -124,20 +139,20 @@ $serverExchangeInstallDirectory = Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Exch # Check Exchange registry key if (-not $serverExchangeInstallDirectory ) { - Write-Warning "Failed to find the Exchange installation Path registry key" + Write-Host "[ERROR]: Failed to find the Exchange installation Path registry key" -ForegroundColor Red exit } # Check the installation path if (-not ( Test-Path $($serverExchangeInstallDirectory.MsiInstallPath) -PathType Container) ) { - Write-Warning "Failed to find the Exchange installation Path" + Write-Host "[ERROR]: Failed to find the Exchange installation Path" -ForegroundColor Red exit } # Check Exchange is 2013, 2016 or 2019 if ( -not ( $($serverExchangeInstallDirectory.MsiProductMajor) -eq 15 -and ` ($($serverExchangeInstallDirectory.MsiProductMinor) -eq 0 -or $($serverExchangeInstallDirectory.MsiProductMinor) -eq 1 -or $($serverExchangeInstallDirectory.MsiProductMinor) -eq 2 ) ) ) { - Write-Warning "This script is designed for Exchange 2013, 2016 or 2019" + Write-Host "[ERROR]: This script is designed for Exchange 2013, 2016 or 2019" -ForegroundColor Red exit } @@ -146,20 +161,20 @@ $ExchangePath = $serverExchangeInstallDirectory.MsiInstallPath # Check Exchange Shell and Exchange installation $exchangeShell = Confirm-ExchangeShell if (-not($exchangeShell.ShellLoaded)) { - Write-Warning "Failed to load Exchange Shell Module..." + Write-Host "Failed to load Exchange Shell Module..." -ForegroundColor Red exit } -Write-SimpleLogFile -String ("###########################################################################################") -LogFile $LogFileName -Write-SimpleLogFile -String ("Starting AV Exclusions analysis at $((Get-Date).ToString())") -LogFile $LogFileName -Write-SimpleLogFile -String ("###########################################################################################") -LogFile $LogFileName -Write-SimpleLogFile -String ("You can find a detailed log on: $LogFileName") -LogFile $LogFileName -OutHost +Write-Host "###########################################################################################" +Write-Host "Starting AV Exclusions analysis at $((Get-Date).ToString())" +Write-Host "###########################################################################################" +Write-Host "You can find a detailed log on: $LogFileName-Debug#DateTime#.txt" # Create the Array List $BaseFolders = Get-ExchAVExclusionsPaths -ExchangePath $ExchangePath -MsiProductMinor ([byte]$serverExchangeInstallDirectory.MsiProductMinor) if ( $BaseFolders.count -eq 0 ) { - Write-Warning "We do not detect folders to analyze" + Write-Host "We do not detect folders to analyze" -ForegroundColor Red exit } @@ -176,13 +191,13 @@ foreach ($path in $BaseFolders) { $FolderList.Add($path.ToLower()) $nonExistentFolder.Add($path.ToLower()) New-Item -Path (Split-Path $path) -Name $path.split('\')[-1] -ItemType Directory -Force | Out-Null - Write-SimpleLogFile -string ("Created folder: " + $path) -LogFile $LogFileName + Write-Debug "Created folder: $path" } # Resolve path only returns a bool so we have to manually throw to catch if (!(Resolve-Path -Path $path -ErrorAction SilentlyContinue)) { $nonExistentFolder.Add($path.ToLower()) New-Item -Path (Split-Path $path) -Name $path.split('\')[-1] -ItemType Directory -Force | Out-Null - Write-SimpleLogFile -string ("Created folder: " + $path) -LogFile $LogFileName + Write-Verbose "Created folder: $path" } # If -recurse then we need to find all SubFolders and Add them to the list to be tested @@ -196,13 +211,13 @@ foreach ($path in $BaseFolders) { } # Just Add the root folder $FolderList.Add($path.ToLower()) - } catch { Write-SimpleLogFile -string ("[ERROR] - Failed to resolve folder " + $path) -LogFile $LogFileName } + } catch { Write-Verbose "[ERROR] - Failed to resolve folder $path" -ForegroundColor Red } } # Remove any Duplicates $FolderList = $FolderList | Select-Object -Unique -Write-SimpleLogFile -String "Creating EICAR Files" -LogFile $LogFileName -OutHost +Write-Host "Creating EICAR Files" # Create the EICAR file in each path $eicarFileName = "eicar" @@ -215,7 +230,7 @@ $eicarFullFileName = "$eicarFileName.$eicarFileExt" foreach ($Folder in $FolderList) { [string] $FilePath = (Join-Path $Folder $eicarFullFileName) - Write-SimpleLogFile -String ("Creating $eicarFullFileName file " + $FilePath) -LogFile $LogFileName + Write-Verbose "Creating $eicarFullFileName file $FilePath" if (!(Test-Path -Path $FilePath)) { @@ -230,7 +245,7 @@ foreach ($Folder in $FolderList) { Write-Warning "$Folder $eicarFullFileName file couldn't be created. Either permissions or AV prevented file creation." } } else { - Write-SimpleLogFile -string ("[WARNING] - $eicarFullFileName already exists!: " + $FilePath) -LogFile $LogFileName -OutHost + Write-Warning "$eicarFullFileName already exists!: $FilePath" } } @@ -243,7 +258,7 @@ $extensionsList = Get-ExchAVExclusionsExtensions -MsiProductMinor ([byte]$server if ($randomFolder) { foreach ($extension in $extensionsList) { $filepath = Join-Path $randomFolder "$eicarFileName.$extension" - Write-SimpleLogFile -String ("Creating $eicarFileName.$extension file " + $FilePath) -LogFile $LogFileName + Write-Verbose "Creating $eicarFileName.$extension file $FilePath" if (!(Test-Path -Path $FilePath)) { @@ -256,22 +271,22 @@ if ($randomFolder) { Write-Warning "$randomFolder $eicarFileName.$extension file couldn't be created. Either permissions or AV prevented file creation." } } else { - Write-SimpleLogFile -string ("[WARNING] - $randomFolder $eicarFileName.$extension already exists!: ") -LogFile $LogFileName -OutHost + Write-Warning "$randomFolder $eicarFileName.$extension already exists!: " } } } else { Write-Warning "We cannot create a folder in root path to test extension exclusions." } -Write-SimpleLogFile -String "EICAR Files Created" -LogFile $LogFileName -OutHost +Write-Host "EICAR Files Created" -Write-SimpleLogFile -String "Accessing EICAR Files" -LogFile $LogFileName -OutHost +Write-Host "Accessing EICAR Files" # Try to open each EICAR file to force detection in paths $i = 0 foreach ($Folder in $FolderList) { $FilePath = (Join-Path $Folder $eicarFullFileName) if (Test-Path $FilePath -PathType Leaf) { - Write-SimpleLogFile -String ("Opening $eicarFullFileName file " + $FilePath) -LogFile $LogFileName + Write-Verbose "Opening $eicarFullFileName file $FilePath" Start-Process -FilePath more -ArgumentList """$FilePath""" -ErrorAction SilentlyContinue -WindowStyle Hidden | Out-Null } $i++ @@ -282,13 +297,13 @@ $i = 0 foreach ($extension in $extensionsList) { $FilePath = Join-Path $randomFolder "$eicarFileName.$extension" if (Test-Path $FilePath -PathType Leaf) { - Write-SimpleLogFile -String ("Opening $eicarFileName.$extension file " + $FilePath) -LogFile $LogFileName + Write-Verbose "Opening $eicarFileName.$extension file $FilePath" Start-Process -FilePath more -ArgumentList """$FilePath""" -ErrorAction SilentlyContinue -WindowStyle Hidden | Out-Null } $i++ } -Write-SimpleLogFile -String "Access EICAR Files Finished" -LogFile $LogFileName -OutHost +Write-Host "Access EICAR Files Finished" $StartDate = Get-Date [int]$initialDiff = (New-TimeSpan -End $StartDate.AddMinutes($WaitingTimeForAVAnalysisInMinutes) -Start $StartDate).TotalSeconds @@ -297,7 +312,7 @@ $firstExecution = $true $SuspiciousProcessList = New-Object Collections.Generic.List[string] $SuspiciousW3wpProcessList = New-Object Collections.Generic.List[string] -Write-SimpleLogFile -String "Analyzing Exchange Processes" -LogFile $LogFileName -OutHost +Write-Host "Analyzing Exchange Processes" while ($currentDiff -gt 0) { if ($firstExecution) { # Test Exchange Processes for unexpected modules @@ -329,11 +344,12 @@ while ($currentDiff -gt 0) { $ModuleAllowList.add("prxyqry.DLL") # cSpell:enable - Write-SimpleLogFile -string ("Allow List Module Count: " + $ModuleAllowList.count) -LogFile $LogFileName + Write-Verbose "Allow List Module Count: $($ModuleAllowList.count)" # Gather each process and work thru their module list to remove any known modules. foreach ($process in $ServerProcess) { + Write-Verbose "Checking $($process.path) - PID: $($process.Id)" Write-Progress -Activity "Checking Exchange Processes" -CurrentOperation "$currentDiff More Seconds" -PercentComplete ((($initialDiff - $currentDiff) / $initialDiff) * 100) -Status " " [int]$currentDiff = (New-TimeSpan -End $StartDate.AddMinutes($WaitingTimeForAVAnalysisInMinutes) -Start (Get-Date)).TotalSeconds @@ -341,12 +357,15 @@ while ($currentDiff -gt 0) { [array]$ProcessModules = $process.modules # Remove Microsoft modules + Write-Verbose "Removing Microsoft Modules" $ProcessModules = $ProcessModules | Where-Object { $_.FileVersionInfo.CompanyName -ne "Microsoft Corporation." -and $_.FileVersionInfo.CompanyName -ne "Microsoft" -and $_.FileVersionInfo.CompanyName -ne "Microsoft Corporation" } # Remove Oracle modules on FIPS + Write-Verbose "Removing Oracle Modules" $ProcessModules = $ProcessModules | Where-Object { (-not($_.FileName -like "*\FIP-FS\Bin\*" -and $_.FileVersionInfo.CompanyName -eq "Oracle Corporation")) } # Clear out modules from the allow list + Write-Verbose "Removing Allow Modules" foreach ($module in $ModuleAllowList) { $ProcessModules = $ProcessModules | Where-Object { $_.ModuleName -ne $module -and $_.ModuleName -ne $($module.Replace(".dll", ".ni.dll")) } } @@ -354,7 +373,7 @@ while ($currentDiff -gt 0) { if ($ProcessModules.count -gt 0) { foreach ($module in $ProcessModules) { $OutString = ("PROCESS: $($process.ProcessName) PID($($process.Id)) UNEXPECTED MODULE: $($module.ModuleName) COMPANY: $($module.Company)`n`tPATH: $($module.FileName)") - Write-SimpleLogFile -string "[FAIL] - $OutString" -LogFile $LogFileName -OutHost + Write-Host "[FAIL] - $OutString" -ForegroundColor Red if ($process.MainModule.ModuleName -eq "W3wp.exe") { $SuspiciousW3wpProcessList += $OutString } else { @@ -370,12 +389,12 @@ while ($currentDiff -gt 0) { [int]$currentDiff = (New-TimeSpan -End $StartDate.AddMinutes($WaitingTimeForAVAnalysisInMinutes) -Start (Get-Date)).TotalSeconds } } -Write-SimpleLogFile -String "Analyzed Exchange Processes" -LogFile $LogFileName -OutHost +Write-Host "Analyzed Exchange Processes" # Create a list of folders that are probably being scanned by AV $BadFolderList = New-Object Collections.Generic.List[string] -Write-SimpleLogFile -string "Testing for EICAR files" -LogFile $LogFileName -OutHost +Write-Host "Testing for EICAR files" # Test each location for the EICAR file foreach ($Folder in $FolderList) { @@ -387,22 +406,22 @@ foreach ($Folder in $FolderList) { #Get content to confirm that the file is not blocked by AV $output = Get-Content $FilePath -ErrorAction SilentlyContinue if ($output -eq $eicar) { - Write-SimpleLogFile -String ("Removing " + $FilePath) -LogFile $LogFileName + Write-Verbose "Removing $FilePath" Remove-Item $FilePath -Confirm:$false -Force } else { - Write-SimpleLogFile -String ("[FAIL] - Possible AV Scanning on Path: " + $Folder) -LogFile $LogFileName -OutHost + Write-Host "[FAIL] - Possible AV Scanning on Path: $Folder" -ForegroundColor Red $BadFolderList.Add($Folder) } } # If the file doesn't exist Add that to the bad folder list -- means the folder is being scanned else { - Write-SimpleLogFile -String ("[FAIL] - Possible AV Scanning on Path: " + $Folder) -LogFile $LogFileName -OutHost + Write-Host "[FAIL] - Possible AV Scanning on Path: $Folder" -ForegroundColor Red $BadFolderList.Add($Folder) } if ($nonExistentFolder -contains $Folder) { Remove-Item $Folder -Confirm:$false -Force -Recurse - Write-SimpleLogFile -string ("Removed folder: " + $Folder) -LogFile $LogFileName + Write-Verbose "Removed folder: $Folder" } } @@ -417,24 +436,24 @@ foreach ($extension in $extensionsList) { #Get content to confirm that the file is not blocked by AV $output = Get-Content $FilePath -ErrorAction SilentlyContinue if ($output -eq $eicar) { - Write-SimpleLogFile -String ("Removing " + $FilePath) -LogFile $LogFileName + Write-Verbose "Removing $FilePath" Remove-Item $FilePath -Confirm:$false -Force } else { - Write-SimpleLogFile -String ("[FAIL] - Possible AV Scanning on Extension: " + $extension) -LogFile $LogFileName -OutHost + Write-Host "[FAIL] - Possible AV Scanning on Extension: $extension" -ForegroundColor Red $BadExtensionList.Add($extension) } } # If the file doesn't exist Add that to the bad extension list -- means the extension is being scanned else { - Write-SimpleLogFile -String ("[FAIL] - Possible AV Scanning on Extension: " + $extension) -LogFile $LogFileName -OutHost + Write-Host "[FAIL] - Possible AV Scanning on Extension: $extension" -ForegroundColor Red $BadExtensionList.Add($extension) } } #Delete Random Folder -Remove-Item $randomFolder +Remove-Item $randomFolder -Confirm:$false -Force -Recurse -$OutputPath = Join-Path $PSScriptRoot BadExclusions.txt +$OutputPath = Join-Path $PSScriptRoot BadExclusions-$dateTime.txt "###########################################################################################" | Out-File $OutputPath "Exclusions analysis at $((Get-Date).ToString())" | Out-File $OutputPath -Append "###########################################################################################" | Out-File $OutputPath -Append @@ -442,7 +461,7 @@ $OutputPath = Join-Path $PSScriptRoot BadExclusions.txt # Report what we found if ($BadFolderList.count -gt 0 -or $BadExtensionList.Count -gt 0 -or $SuspiciousProcessList.count -gt 0 -or $SuspiciousW3wpProcessList.count -gt 0) { - Write-SimpleLogFile -String "Possible AV Scanning found" -LogFile $LogFileName + Write-Host "Possible AV Scanning found" -ForegroundColor Red if ($BadFolderList.count -gt 0 ) { "`n[Missing Folder Exclusions]" | Out-File $OutputPath -Append $BadFolderList | Out-File $OutputPath -Append @@ -459,10 +478,9 @@ if ($BadFolderList.count -gt 0 -or $BadExtensionList.Count -gt 0 -or $Suspicious Write-Warning ("Found $($SuspiciousProcessList.count) UnExpected modules loaded into Exchange Processes ") } if ($SuspiciousW3wpProcessList.count -gt 0 ) { - $SuspiciousW3wpProcessListString = "`n[WARNING] - W3wp.exe is not present in the recommended Exclusion list but we found 3rd Party modules on it and could affect Exchange performance or functionality." + $SuspiciousW3wpProcessListString = "`nW3wp.exe is not present in the recommended Exclusion list but we found 3rd Party modules on it and could affect Exchange performance or functionality." $SuspiciousW3wpProcessListString | Out-File $OutputPath -Append Write-Warning $SuspiciousW3wpProcessListString - Write-SimpleLogFile -string $SuspiciousW3wpProcessListString -LogFile $LogFileName "`n[Non-Default Modules Loaded on W3wp.exe]" | Out-File $OutputPath -Append $SuspiciousW3wpProcessList | Out-File $OutputPath -Append Write-Warning ("Found $($SuspiciousW3wpProcessList.count) UnExpected modules loaded into W3wp.exe ") @@ -471,7 +489,5 @@ if ($BadFolderList.count -gt 0 -or $BadExtensionList.Count -gt 0 -or $Suspicious } else { $CorrectExclusionsString = "`nAll EICAR files found; File Exclusions, Extensions Exclusions and Processes Exclusions (Did not find Non-Default modules loaded) appear to be set properly" $CorrectExclusionsString | Out-File $OutputPath -Append - Write-SimpleLogFile -String $CorrectExclusionsString -LogFile $LogFileName -OutHost + Write-Host $CorrectExclusionsString } - -Write-SimpleLogFile -string "Testing for AV loaded in processes" -LogFile $LogFileName -OutHost diff --git a/Diagnostics/AVTester/Write-SimpleLogFile.ps1 b/Diagnostics/AVTester/Write-SimpleLogFile.ps1 deleted file mode 100644 index a5f546ff6b..0000000000 --- a/Diagnostics/AVTester/Write-SimpleLogFile.ps1 +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -<# -.NOTES - Name: Write-SimpleLogFile.ps1 - Requires: NA - Major Release History: - 06/22/2021 - Initial Release - -.SYNOPSIS -Supports writing a basic log file to LocalAppData - -.DESCRIPTION -Supports basic log file generation for other scripts. -Places the log file into the requested Folder. - -Supports out putting to the host as well as the log files. - -.PARAMETER String -String to be written into the log file. - -.PARAMETER Path -String with the Path where the log file will be written. - -.PARAMETER FileName -Name of the log file. - -.PARAMETER OutHost -Switch that will write the output to the host as well as the log file. - -.PARAMETER OpenLog -Opens the log file in notepad. - -.OUTPUTS -Log file specified in the FileName parameter. -Writes the file in to the Path specified in the Path parameter. - -.EXAMPLE -Write-SimpleLogFile -String "Start ProcessA" -FileName MyLogFile.log -Path "C:\temp" - -Writes "[Date] - Start ProcessA" to C:\temp\MyLogFile.log - -.EXAMPLE -Write-SimpleLogFile -String "Start ProcessB" -FileName MyLogFile.log -OutHost -Path "C:\temp" - -Writes "[Date] - Start ProcessB" to C:\temp\MyLogFile and to the Host - -#> -function Write-SimpleLogFile { - [CmdletBinding()] - param - ( - [Parameter(Mandatory = $true)] - [string]$String, - - [parameter(Mandatory)] - [ValidateScript({ - $filePath = Split-Path -Path $_ -Parent - if ($filePath -eq "") { $filePath = "." } - if ((Test-Path -Path $filePath -PathType Container) -and ((Test-Path -Path $_ -PathType Leaf) -or -not ((Test-Path -Path $_ -PathType Container)))) { $true } - else { throw "Path $_ is not valid" } - })] - [string]$LogFile, - - [switch]$OutHost, - - [switch]$OpenLog - - ) - - begin { - if ($OpenLog) { - Notepad.exe $LogFile - exit - } - } - process { - - # Get the current date - [string]$date = Get-Date -Format G - - # Build output string - [string]$logString = ( "[" + $date + "] - " + $string) - - # Write everything to our log file and the screen - $logString | Out-File -FilePath $LogFile -Append -Confirm:$false - if ($OutHost) { Write-Host $logString } - else { Write-Verbose $logString } - } -} diff --git a/docs/Diagnostics/Test-ExchAVExclusions.md b/docs/Diagnostics/Test-ExchAVExclusions.md index b588705f2e..b1ab97d1c5 100644 --- a/docs/Diagnostics/Test-ExchAVExclusions.md +++ b/docs/Diagnostics/Test-ExchAVExclusions.md @@ -54,7 +54,6 @@ Parameter | Description | ----------|-------------| WaitingTimeForAVAnalysisInMinutes | Set the waiting time for AV to analyze the EICAR files. Default is 5 minutes. Recurse | Places an EICAR file in all SubFolders as well as the root. -OpenLog | Opens the script log file. SkipVersionCheck | Skip script version verification. ScriptUpdateOnly | Just update script version to latest one. @@ -62,7 +61,7 @@ ScriptUpdateOnly | Just update script version to latest one. ## Outputs Log file: -$PSScriptRoot\ExchAvExclusions.log +$PSScriptRoot\Test-ExchAvExclusions-#DateTime#.txt List of Folders, extensions Scanned by AV and List of Non-Default Processes: -$PSScriptRoot\BadExclusions.txt +$PSScriptRoot\BadExclusions-#DateTime#.txt From 916f4d57e5bdedb4c06358fee04020a44b126d6d Mon Sep 17 00:00:00 2001 From: iserrano76 Date: Wed, 31 Jan 2024 19:47:11 +0100 Subject: [PATCH 2/3] include the datetime format in output --- Diagnostics/AVTester/Test-ExchAVExclusions.ps1 | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Diagnostics/AVTester/Test-ExchAVExclusions.ps1 b/Diagnostics/AVTester/Test-ExchAVExclusions.ps1 index 7be51d23f7..b552b69326 100644 --- a/Diagnostics/AVTester/Test-ExchAVExclusions.ps1 +++ b/Diagnostics/AVTester/Test-ExchAVExclusions.ps1 @@ -101,9 +101,10 @@ function Write-HostLog ($message) { } $LogFileName = "Test-ExchAvExclusions" -$dateTime = (Get-Date).ToString("yyyyMMddhhmmss") -$Script:DebugLogger = Get-NewLoggerInstance -LogName "$LogFileName-Debug-$dateTime" -LogDirectory $PSScriptRoot -AppendDateTimeToFileName $false -ErrorAction SilentlyContinue -$Script:HostLogger = Get-NewLoggerInstance -LogName "$LogFileName-Results-$dateTime" -LogDirectory $PSScriptRoot -AppendDateTimeToFileName $false -ErrorAction SilentlyContinue +$StartDate = Get-Date +$StartDateFormatted = ($StartDate).ToString("yyyyMMddhhmmss") +$Script:DebugLogger = Get-NewLoggerInstance -LogName "$LogFileName-Debug-$StartDateFormatted" -LogDirectory $PSScriptRoot -AppendDateTimeToFileName $false -ErrorAction SilentlyContinue +$Script:HostLogger = Get-NewLoggerInstance -LogName "$LogFileName-Results-$StartDateFormatted" -LogDirectory $PSScriptRoot -AppendDateTimeToFileName $false -ErrorAction SilentlyContinue SetWriteHostAction ${Function:Write-HostLog} SetWriteProgressAction ${Function:Write-DebugLog} @@ -166,9 +167,10 @@ if (-not($exchangeShell.ShellLoaded)) { } Write-Host "###########################################################################################" -Write-Host "Starting AV Exclusions analysis at $((Get-Date).ToString())" +Write-Host "Starting AV Exclusions analysis at $(($StartDate).ToString())" Write-Host "###########################################################################################" -Write-Host "You can find a detailed log on: $LogFileName-Debug#DateTime#.txt" +Write-Host "You can find a simple log on: $LogFileName-Results-$StartDateFormatted.txt" +Write-Host "And a detailed log on: $LogFileName-Debug-$StartDateFormatted.txt" # Create the Array List $BaseFolders = Get-ExchAVExclusionsPaths -ExchangePath $ExchangePath -MsiProductMinor ([byte]$serverExchangeInstallDirectory.MsiProductMinor) @@ -305,7 +307,6 @@ foreach ($extension in $extensionsList) { Write-Host "Access EICAR Files Finished" -$StartDate = Get-Date [int]$initialDiff = (New-TimeSpan -End $StartDate.AddMinutes($WaitingTimeForAVAnalysisInMinutes) -Start $StartDate).TotalSeconds $currentDiff = $initialDiff $firstExecution = $true @@ -453,7 +454,7 @@ foreach ($extension in $extensionsList) { #Delete Random Folder Remove-Item $randomFolder -Confirm:$false -Force -Recurse -$OutputPath = Join-Path $PSScriptRoot BadExclusions-$dateTime.txt +$OutputPath = Join-Path $PSScriptRoot BadExclusions-$StartDateFormatted.txt "###########################################################################################" | Out-File $OutputPath "Exclusions analysis at $((Get-Date).ToString())" | Out-File $OutputPath -Append "###########################################################################################" | Out-File $OutputPath -Append From c625c6d76d8a184604d7a91e153b05bb7dd1ecda Mon Sep 17 00:00:00 2001 From: iserrano76 Date: Thu, 8 Feb 2024 09:03:03 +0100 Subject: [PATCH 3/3] Fix DebugLooger and Write-Debug --- Diagnostics/AVTester/Test-ExchAVExclusions.ps1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Diagnostics/AVTester/Test-ExchAVExclusions.ps1 b/Diagnostics/AVTester/Test-ExchAVExclusions.ps1 index b552b69326..9337d24156 100644 --- a/Diagnostics/AVTester/Test-ExchAVExclusions.ps1 +++ b/Diagnostics/AVTester/Test-ExchAVExclusions.ps1 @@ -95,7 +95,7 @@ function Write-DebugLog ($message) { function Write-HostLog ($message) { if (![string]::IsNullOrEmpty($message)) { - $Script:WarningLogger = $Script:DebugLogger | Write-LoggerInstance $message + $Script:DebugLogger = $Script:DebugLogger | Write-LoggerInstance $message $Script:HostLogger = $Script:HostLogger | Write-LoggerInstance $message } } @@ -193,8 +193,9 @@ foreach ($path in $BaseFolders) { $FolderList.Add($path.ToLower()) $nonExistentFolder.Add($path.ToLower()) New-Item -Path (Split-Path $path) -Name $path.split('\')[-1] -ItemType Directory -Force | Out-Null - Write-Debug "Created folder: $path" + Write-Verbose "Created folder: $path" } + # Resolve path only returns a bool so we have to manually throw to catch if (!(Resolve-Path -Path $path -ErrorAction SilentlyContinue)) { $nonExistentFolder.Add($path.ToLower())