<commit_before>[CmdletBinding(DefaultParameterSetName = 'OptOut')]
Param(
    [Parameter(ParameterSetName = 'OptOut')]
    [ValidateSet(
        'DotNet',
        'Office365',
        'PowerShell',
        'WindowsComponents',
        'WindowsDefender',
        'WindowsPower',
        'WindowsRestore',
        'WindowsSecurity',
        'WindowsSettingsComputer',
        'WindowsSettingsUser',
        'WindowsUpdate'
    )]
    [String[]]$ExcludeTasks,

    [Parameter(ParameterSetName = 'OptIn', Mandatory = $true)]
    [ValidateSet(
        'DotNet',
        'Office365',
        'PowerShell',
        'WindowsComponents',
        'WindowsDefender',
        'WindowsPower',
        'WindowsRestore',
        'WindowsSecurity',
        'WindowsSettingsComputer',
        'WindowsSettingsUser',
        'WindowsUpdate'
    )]
    [String[]]$IncludeTasks
)

Function Optimize-DotNet {
    [CmdletBinding()]
    Param()

    Test-DotNetPresent

    if ($Script:DotNet20Present) {
        Write-Host -ForegroundColor Green '[DotNet] Applying .NET Framework 2.x/3.x settings ...'

        # Enable strong cryptography
        Set-RegistryValue -Path 'HKLM:\Software\Microsoft\.NETFramework\v2.0.50727' -Name 'SchUseStrongCrypto' -Type DWord -Value 1
        if ($Script:Wow64Present) {
            Set-RegistryValue -Path 'HKLM:\Software\Wow6432Node\Microsoft\.NETFramework\v2.0.50727' -Name 'SchUseStrongCrypto' -Type DWord -Value 1
        }

        # Let OS choose protocols
        Set-RegistryValue -Path 'HKLM:\Software\Microsoft\.NETFramework\v2.0.50727' -Name 'SystemDefaultTlsVersions' -Type DWord -Value 1 # DevSkim: ignore DS440000
        if ($Script:Wow64Present) {
            Set-RegistryValue -Path 'HKLM:\Software\Microsoft\.NETFramework\v2.0.50727' -Name 'SystemDefaultTlsVersions' -Type DWord -Value 1 # DevSkim: ignore DS440000
        }
    } else {
        Write-Warning -Message 'Skipping .NET Framework 2.x/3.x settings as not installed.'
    }

    if ($Script:DotNet40Present) {
        Write-Host -ForegroundColor Green '[DotNet] Applying .NET Framework 4.x settings ...'

        # Enable strong cryptography
        Set-RegistryValue -Path 'HKLM:\Software\Microsoft\.NETFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Type DWord -Value 1
        if ($Script:Wow64Present) {
            Set-RegistryValue -Path 'HKLM:\Software\Wow6432Node\Microsoft\.NETFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Type DWord -Value 1
        }

        # Let OS choose protocols
        Set-RegistryValue -Path 'HKLM:\Software\Microsoft\.NETFramework\v4.0.30319' -Name 'SystemDefaultTlsVersions' -Type DWord -Value 1 # DevSkim: ignore DS440000
        if ($Script:Wow64Present) {
            Set-RegistryValue -Path 'HKLM:\Software\Microsoft\.NETFramework\v4.0.30319' -Name 'SystemDefaultTlsVersions' -Type DWord -Value 1 # DevSkim: ignore DS440000
        }
    } else {
        Write-Warning -Message 'Skipping .NET Framework 4.x settings as not installed.'
    }
}

Function Optimize-Office365 {
    [CmdletBinding()]
    Param()

    if ($Script:WindowsServerCore) {
        Write-Warning -Message 'Skipping Office 365 settings as unsupported on Windows Server Core.'
        return
    }

    Write-Host -ForegroundColor Green '[Office 365] Disabling automatic updates ...'
    Set-RegistryValue -Path 'HKLM:\Software\Policies\Microsoft\Office\16.0\Common\OfficeUpdate' -Name 'EnableAutomaticUpdates' -Type DWord -Value 0
}

Function Optimize-PowerShell {
    [CmdletBinding()]
    Param()

    if (!($PSVersionTable.PSVersion.Major -ge 5)) {
        Write-Warning 'Skipping PowerShell settings as version is not 5.0 or newer.'
        return
    }

    Write-Host -ForegroundColor Green '[PowerShell] Installing NuGet package provider ...'
    if (Get-Command -Name 'Install-PackageProvider' -ErrorAction Ignore) {
        $null = Install-PackageProvider -Name NuGet -Force
    } else {
        # Older versions of PowerShellGet lack the Install-PackageProvider
        # command. They will try to download the NuGet package provider on
        # calling Install-Module but the manifest specifies a dead URL. The
        # workaround is to manually retrieve the required binary and place it
        # where the module expects.
        $ProvidersPath = Join-Path -Path $env:ProgramFiles -ChildPath 'PackageManagement\ProviderAssemblies'
        $NuGetPath = Join-Path -Path $ProvidersPath -ChildPath 'nuget-anycpu.exe'
        $NuGetUrl = 'https://oneget.org/nuget-anycpu-2.8.5.127.exe'

        if (!(Test-Path -Path $NuGetPath -PathType Leaf)) {
            if (!(Test-Path -Path $ProvidersPath -PathType Container)) {
                $null = New-Item -Path $ProvidersPath -ItemType Directory
            }

            # Disabling progress output substantially improves performance
            $ProgressPreferenceOriginal = $ProgressPreference
            $ProgressPreference = 'SilentlyContinue'
            $null = Invoke-WebRequest -Uri $NuGetUrl -OutFile $NuGetPath -UseBasicParsing
            $ProgressPreference = $ProgressPreferenceOriginal

            # There's some caching of package providers and I've yet to find a
            # way to invalidate it other than restarting the session.
            if (Get-Module -Name PowerShellGet) {
                Write-Host -ForegroundColor Cyan '[PowerShell] You must restart PowerShell to complete NuGet package provider installation.'
                Write-Host -ForegroundColor Cyan '             Re-run this script afterwards to continue initial PowerShell configuration.'
                return
            }
        }
    }

    Write-Host -ForegroundColor Green '[PowerShell] Setting PSGallery repository to trusted ...'
    $null = Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

    Write-Host -ForegroundColor Green '[PowerShell] Installing PowerShellGet module ...'
    $PSGetLoaded = Get-Module -Name PowerShellGet | Sort-Object -Property Version -Descending | Select-Object -First 1
    Install-Module -Name PowerShellGet -Force
    Import-Module -Name PowerShellGet -Force
    $PSGetInstalled = Get-Module -Name PowerShellGet | Sort-Object -Property Version -Descending | Select-Object -First 1

    # PowerShellGet loads various .NET types, and types can't be unloaded (at
    # least not easily). That can be problematic as when loading a new version
    # of PowerShellGet into a session with an earlier version already loaded,
    # some types may have been updated but cannot be loaded to replace earlier
    # loaded types. The simple solution is to restart PowerShell so we have a
    # new session which isn't "polluted" by earlier module imports.
    if ($PSGetLoaded.Version -ne $PSGetInstalled.Version) {
        Write-Host -ForegroundColor Cyan '[PowerShell] You must restart PowerShell to complete PowerShellGet module installation.'
        Write-Host -ForegroundColor Cyan '             Re-run this script afterwards to continue initial PowerShell configuration.'
        return
    }

    Write-Host -ForegroundColor Green '[PowerShell] Determining modules to install ...'
    $Modules = @('SpeculationControl', 'PSWindowsUpdate', 'PSWinGlue', 'PSWinVitals')
    if (!(Get-Module -Name PSReadLine)) {
        $Modules += 'PSReadLine'
    }

    Write-Host -ForegroundColor Green '[PowerShell] Installing modules ...'
    foreach ($Module in $Modules) {
        Write-Host -ForegroundColor Gray ('[PowerShell] - {0}' -f $Module)
        $null = Install-Module -Name $Module -Force
    }

    if ($Modules -notcontains 'PSReadLine') {
        Write-Host -ForegroundColor Cyan '[PowerShell] To update PSReadLine run the following from an elevated Command Prompt:'
        Write-Host -ForegroundColor Cyan '             powershell -NoProfile -NonInteractive -Command "Install-Module -Name PSReadLine -AllowPrerelease -Force"'
    }
}

Function Optimize-WindowsComponents {
    [CmdletBinding()]
    Param()

    Write-Host -ForegroundColor Green -NoNewline '[Windows] Performing component store clean-up ...'
    & dism.exe /Online /Cleanup-Image /StartComponentCleanup
    Write-Host
}

Function Optimize-WindowsDefender {<commit_msg>Initialize-TestVM: Improve PowerShell tasks performance & misc tweaks<commit_after>[CmdletBinding(DefaultParameterSetName = 'OptOut')]
Param(
    [Parameter(ParameterSetName = 'OptOut')]
    [ValidateSet(
        'DotNet',
        'Office365',
        'PowerShell',
        'WindowsComponents',
        'WindowsDefender',
        'WindowsPower',
        'WindowsRestore',
        'WindowsSecurity',
        'WindowsSettingsComputer',
        'WindowsSettingsUser',
        'WindowsUpdate'
    )]
    [String[]]$ExcludeTasks,

    [Parameter(ParameterSetName = 'OptIn', Mandatory = $true)]
    [ValidateSet(
        'DotNet',
        'Office365',
        'PowerShell',
        'WindowsComponents',
        'WindowsDefender',
        'WindowsPower',
        'WindowsRestore',
        'WindowsSecurity',
        'WindowsSettingsComputer',
        'WindowsSettingsUser',
        'WindowsUpdate'
    )]
    [String[]]$IncludeTasks
)

Function Optimize-DotNet {
    [CmdletBinding()]
    Param()

    Test-DotNetPresent

    if ($Script:DotNet20Present) {
        Write-Host -ForegroundColor Green '[DotNet] Applying .NET Framework 2.x/3.x settings ...'

        # Enable strong cryptography
        Set-RegistryValue -Path 'HKLM:\Software\Microsoft\.NETFramework\v2.0.50727' -Name 'SchUseStrongCrypto' -Type DWord -Value 1
        if ($Script:Wow64Present) {
            Set-RegistryValue -Path 'HKLM:\Software\Wow6432Node\Microsoft\.NETFramework\v2.0.50727' -Name 'SchUseStrongCrypto' -Type DWord -Value 1
        }

        # Let OS choose protocols
        Set-RegistryValue -Path 'HKLM:\Software\Microsoft\.NETFramework\v2.0.50727' -Name 'SystemDefaultTlsVersions' -Type DWord -Value 1 # DevSkim: ignore DS440000
        if ($Script:Wow64Present) {
            Set-RegistryValue -Path 'HKLM:\Software\Microsoft\.NETFramework\v2.0.50727' -Name 'SystemDefaultTlsVersions' -Type DWord -Value 1 # DevSkim: ignore DS440000
        }
    } else {
        Write-Warning -Message 'Skipping .NET Framework 2.x/3.x settings as not installed.'
    }

    if ($Script:DotNet40Present) {
        Write-Host -ForegroundColor Green '[DotNet] Applying .NET Framework 4.x settings ...'

        # Enable strong cryptography
        Set-RegistryValue -Path 'HKLM:\Software\Microsoft\.NETFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Type DWord -Value 1
        if ($Script:Wow64Present) {
            Set-RegistryValue -Path 'HKLM:\Software\Wow6432Node\Microsoft\.NETFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Type DWord -Value 1
        }

        # Let OS choose protocols
        Set-RegistryValue -Path 'HKLM:\Software\Microsoft\.NETFramework\v4.0.30319' -Name 'SystemDefaultTlsVersions' -Type DWord -Value 1 # DevSkim: ignore DS440000
        if ($Script:Wow64Present) {
            Set-RegistryValue -Path 'HKLM:\Software\Microsoft\.NETFramework\v4.0.30319' -Name 'SystemDefaultTlsVersions' -Type DWord -Value 1 # DevSkim: ignore DS440000
        }
    } else {
        Write-Warning -Message 'Skipping .NET Framework 4.x settings as not installed.'
    }
}

Function Optimize-Office365 {
    [CmdletBinding()]
    Param()

    if ($Script:WindowsServerCore) {
        Write-Warning -Message 'Skipping Office 365 settings as unsupported on Windows Server Core.'
        return
    }

    Write-Host -ForegroundColor Green '[Office 365] Disabling automatic updates ...'
    Set-RegistryValue -Path 'HKLM:\Software\Policies\Microsoft\Office\16.0\Common\OfficeUpdate' -Name 'EnableAutomaticUpdates' -Type DWord -Value 0
}

Function Optimize-PowerShell {
    [CmdletBinding()]
    Param()

    if ($PSVersionTable.PSVersion.Major -lt 5) {
        Write-Host -ForegroundColor Yellow '[PowerShell] Skipping as version is not at least v5.0.'
        return
    }

    Write-Host -ForegroundColor Green '[PowerShell] Installing NuGet package provider ...'
    if (Get-Command -Name 'Install-PackageProvider' -ErrorAction Ignore) {
        $null = Install-PackageProvider -Name NuGet -Force
    } else {
        # Older versions of PowerShellGet lack the Install-PackageProvider
        # command. They will try to download the NuGet package provider on
        # calling Install-Module but the manifest specifies a dead URL. The
        # workaround is to manually retrieve the required binary and place it
        # where the module expects.
        $ProvidersPath = Join-Path -Path $env:ProgramFiles -ChildPath 'PackageManagement\ProviderAssemblies'
        $NuGetPath = Join-Path -Path $ProvidersPath -ChildPath 'nuget-anycpu.exe'
        $NuGetUrl = 'https://oneget.org/nuget-anycpu-2.8.5.127.exe'

        if (!(Test-Path -Path $NuGetPath -PathType Leaf)) {
            if (!(Test-Path -Path $ProvidersPath -PathType Container)) {
                $null = New-Item -Path $ProvidersPath -ItemType Directory
            }

            # Disabling progress output substantially improves performance
            $ProgressPreferenceOriginal = $ProgressPreference
            $ProgressPreference = 'SilentlyContinue'
            $null = Invoke-WebRequest -Uri $NuGetUrl -OutFile $NuGetPath -UseBasicParsing
            $ProgressPreference = $ProgressPreferenceOriginal

            # There's some caching of package providers and I've yet to find a
            # way to invalidate it so we request the user restart the session.
            if (Get-Module -Name PowerShellGet) {
                Write-Host -ForegroundColor Cyan '[PowerShell] You must restart PowerShell to complete NuGet package provider installation.'
                Write-Host -ForegroundColor Cyan '             Re-run this script afterwards to continue initial PowerShell configuration.'
                return
            }
        }
    }

    $PSGallery = Get-PSRepository -Name PSGallery
    if ($PSGallery.InstallationPolicy -ne 'Trusted') {
        Write-Host -ForegroundColor Green '[PowerShell] Setting PSGallery repository to trusted ...'
        $null = Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
    }

    Write-Host -ForegroundColor Green '[PowerShell] Checking PowerShellGet module ...'
    $PSGetOutdated = $true
    $PSGetLoaded = Get-Module -Name PowerShellGet | Sort-Object -Property Version -Descending | Select-Object -First 1
    if ($PSGetLoaded) {
        $PSGetLatest = Find-Module -Name PowerShellGet
        if ($PSGetLoaded.Version -ge $PSGetLatest.Version) {
            $PSGetOutdated = $false
        }
    }

    if ($PSGetOutdated) {
        Write-Host -ForegroundColor Green '[PowerShell] Updating PowerShellGet module ...'
        Install-Module -Name PowerShellGet -Force
        Import-Module -Name PowerShellGet -Force
        $PSGetImported = Get-Module -Name PowerShellGet | Sort-Object -Property Version -Descending | Select-Object -First 1

        # PowerShellGet loads various .NET types, and types can't be unloaded
        # (at least not easily). That can be problematic as when loading a new
        # version of PowerShellGet into a session which has already imported an
        # earlier version, some types may have been updated but cannot replace
        # the previously loaded types. The solution is to restart PowerShell so
        # we have a new session which isn't "polluted" by an earlier import.
        if ($PSGetLoaded.Version -ne $PSGetImported.Version) {
            Write-Host -ForegroundColor Cyan '[PowerShell] You must restart PowerShell to complete PowerShellGet module installation.'
            Write-Host -ForegroundColor Cyan '             Re-run this script afterwards to continue initial PowerShell configuration.'
            return
        }
    }

    Write-Host -ForegroundColor Green '[PowerShell] Determining modules to install ...'
    $Modules = 'PSReadLine', 'PSWinGlue', 'PSWinVitals', 'PSWindowsUpdate', 'SpeculationControl'
    $ModulesLatest = Find-Module -Name $Modules -Repository PSGallery
    $ModulesInstall = [Collections.ArrayList]::new()

    foreach ($ModuleLatest in $ModulesLatest) {
        $ModuleCurrent = Get-Module -Name $ModuleLatest.Name -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1
        if ($ModuleCurrent.Version -ge $ModuleLatest.Version) {
            continue
        }

        if ($ModuleLatest.Name -eq 'PSReadLine') {
            $PSReadLineOutdated = $true
        } else {
            $null = $ModulesInstall.Add($ModuleLatest.Name)
        }
    }

    if ($ModulesInstall.Count -ne 0) {
        Write-Host -ForegroundColor Green '[PowerShell] Updating modules ...'
        foreach ($Module in $ModulesInstall) {
            Write-Host -ForegroundColor Gray ('[PowerShell] - {0}' -f $Module)
            $null = Install-Module -Name $Module -Force
        }
    }

    if ($PSReadLineOutdated) {
        Write-Host -ForegroundColor Cyan '[PowerShell] To update PSReadLine run the following from an elevated Command Prompt:'
        Write-Host -ForegroundColor Cyan '             powershell -NoProfile -NonInteractive -Command "Install-Module -Name PSReadLine -Force"'
    }
}

Function Optimize-WindowsComponents {
    [CmdletBinding()]
    Param()

    Write-Host -ForegroundColor Green -NoNewline '[Windows] Performing component store clean-up ...'
    & dism.exe /Online /Cleanup-Image /StartComponentCleanup
    Write-Host
}

Function Optimize-WindowsDefender {
{'fraction_non_alphanumeric': 0.09640831758034027, 'fraction_numerical': 0.016726814458383456, 'mean_word_length': 2.737529436951402, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '109382', 'n_tokens_mistral': 5092, 'n_tokens_neox': 4736, 'n_words': 1387}