{"id":7595,"date":"2024-01-19T00:21:22","date_gmt":"2024-01-19T00:21:22","guid":{"rendered":"https:\/\/pariswells.com\/blog\/?p=7595"},"modified":"2024-01-23T02:56:02","modified_gmt":"2024-01-23T02:56:02","slug":"install-defender-on-server-2012r22016","status":"publish","type":"post","link":"https:\/\/pariswells.com\/blog\/research\/install-defender-on-server-2012r22016","title":{"rendered":"Install Defender on Server 2012R2\\2016"},"content":{"rendered":"\n<p>Install Defender<\/p>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/github.com\/microsoft\/mdefordownlevelserver\n<\/div><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">&lt;#\n.SYNOPSIS\n    Helper script for installing\/uninstalling Microsoft Defender for Downlevel Servers.\n.DESCRIPTION\n    On install scenario:\n        It first removes MMA workspace when RemoveMMA guid is provided.\n        Next uninstalls SCEP if present and OS version is Server2012R2\n        Next installs two hotfixes required by the MSI (if they are not installed)\n        Next installs the Microsoft Defender for Downlevel Servers MSI (i.e. md4ws.msi)\n        Finally, it runs the onboarding script, if provided using the parameter OnboardingScript. \n        Please use the script for Group Policy as it is non-interactive; the local onboarding script will fail.\n    On uninstall scenario:\n        It will run the offboarding script, if provided.\n        Uninstalls the MSI unless IsTamperProtected is on.\n        Removes Defender Powershell module, if loaded inside current Powershell session.\n.INPUTS\n    md4ws.msi\n.OUTPUTS\n    none\n.EXAMPLE\n    .\\Install.ps1\n.EXAMPLE\n    .\\Install.ps1 -UI -NoMSILog -NoEtl\n.EXAMPLE\n    .\\Install.ps1 -Uninstall\n.EXAMPLE\n    .\\Install.ps1 -Uninstall -NoEtl\n#&gt;\nparam(\n    [Parameter(ParameterSetName = 'install')]\n    ## MMA Workspace Id to be removed\n    [guid] $RemoveMMA,\n    [Parameter(ParameterSetName = 'install')]\n    ## Path to onboarding script (required by WD-ATP)\n    [string] $OnboardingScript,    \n    [Parameter(ParameterSetName = 'install')]\n    ## Installs devmode msi instead of the realeased one\n    [switch] $DevMode,\n    [Parameter(ParameterSetName = 'uninstall', Mandatory)]\n    ## Uninstalls Microsoft Defender for Downlevel Servers. Offboarding has to be run manually prior to uninstall.\n    [switch] $Uninstall,\n    [Parameter(ParameterSetName = 'uninstall')]\n    [Parameter(ParameterSetName = 'install')]\n    ## Offboarding script to run prior to uninstalling\/reinstalling MSI \n    [string] $OffboardingScript,\n    [Parameter(ParameterSetName = 'install')]\n    [Parameter(ParameterSetName = 'uninstall')]\n    ## Enables UI in MSI \n    [switch] $UI,\n    [Parameter(ParameterSetName = 'install')]\n    ## Put WinDefend in passive mode.\n    [switch] $Passive,\n    [Parameter(ParameterSetName = 'install')]\n    [Parameter(ParameterSetName = 'uninstall')]\n    ## Disable MSI Logging\n    [switch] $NoMSILog,\n    [Parameter(ParameterSetName = 'install')]\n    ## Used to pass extra arguments to Invoke-WebRequest calls used by this script (like WebSession, Proxy, ProxyCredential)\n    [hashtable] $ExtraWebRequestOptions = @{},\n    [Parameter(ParameterSetName = 'install')]\n    [Parameter(ParameterSetName = 'uninstall')]\n    ## Disable ETL logging\n    [switch] $NoEtl)\n \n\nfunction Get-CommandLine {\n    &lt;#\n.synopsis\n    Returns the equivalent command line used to invoke a script\n.DESCRIPTION\n    Returns the equivalent command line used to invoke a script\n.EXAMPLE\n    Get-CommandLine $PSCmdLet.MyInvocation\n#&gt;\n    [CmdletBinding()]\n    [OutputType([string])]\n    ## Usually $PSCmdLet.MyInvocation.\n    param([Parameter(ValueFromPipeline = $true, Position = 0)] [System.Management.Automation.InvocationInfo] $info)\n\n    process {\n        function EscapeString {\n            param([string] $s)\n            if ($null -ne $s -and ' ' -in $s -and $s[0] -ne '\"') {\n                \"`\"{0}'\" -f $s\n            }\n            else {\n                $s\n            }\n        }\n\n        [string] $commandLine = ''\n        if ($null -ne $info) {\n            $commandLine = EscapeString $info.MyCommand.Name\n            foreach ($boundparam in $info.BoundParameters.GetEnumerator()) {\n                $val = ''\n                foreach ($k in ($boundparam.Value)) {\n                    $val += if ($val.Length) { ',' } else { ':' }\n                    $val += if ($k -is [switch]) {\n                        if ($k.ToBool()) { '$true' } else { '$false' }\n                    }\n                    else {\n                        EscapeString $k\n                    }\n                }\n                $commandLine += \" -{0}{1}\" -f $boundparam.Key, $val\n            }\n\n            foreach ($k in $info.UnboundArguments.GetEnumerator()) {\n                $commandLine += \" {0}\" -f (EscapeString $k)\n            }\n        }\n\n        return $commandLine\n    }\n}    \n\nfunction Set-RegistryKey {\n    [CmdletBinding()]\n    param([Parameter(Mandatory)][string] $LiteralPath,\n        [Parameter(Mandatory)][string] $Name,\n        [Parameter(Mandatory)][object] $Value)\n\n    function Set-ContainerPath {\n        [CmdletBinding()]\n        param([Parameter(Mandatory)][string] $LiteralPath)\n        if (!(Test-Path -LiteralPath:$LiteralPath -PathType:Container)) {\n            $parent = Split-Path -Path:$LiteralPath -Parent\n            Set-ContainerPath -LiteralPath:$parent\n            $leaf = Split-Path -Path:$LiteralPath -Leaf\n            $null = New-Item -Path:$parent -Name:$leaf -ItemType:Directory\n        }\n    }   \n    Set-ContainerPath -LiteralPath:$LiteralPath\n    Set-ItemProperty -LiteralPath:$LiteralPath -Name:$Name -Value:$Value\n    Trace-Message \"$LiteralPath[$Name]=$Value\" -SkipFrames:3\n}\n\nfunction Remove-RegistryKey {\n    [CmdletBinding()]\n    param (\n        [Parameter(Mandatory)][string] $LiteralPath\n    )\n\n    if (Test-Path -LiteralPath:$LiteralPath) {\n        Remove-Item -LiteralPath:$LiteralPath -Recurse -Force -ErrorAction SilentlyContinue -ErrorVariable err\n        if ($err.count -gt 0){\n            Trace-Message \"Remove-Item $LiteralPath message: $err\" -SkipFrames:3\n        } else {\n            Trace-Message \"Removed registry key: $LiteralPath\" -SkipFrames:3\n        }\n    }\n}\n\n[System.IO.StreamWriter] $Script:InstallLog = $null\nSet-Variable -Name:'InstallPS1HKLM' -Value:'HKLM:\\SOFTWARE\\Microsoft\\Microsoft Defender for Endpoint Install' -Option:Constant -Scope:Script\n\nfunction Get-TraceMessage {\n    [OutputType([string])]\n    param(\n        [Parameter(Mandatory, Position = 0)] [string] $Message,\n        [Parameter(Position = 1)][uint16] $SkipFrames = 2,\n        [datetime] $Date = (Get-Date))\n    function Get-Time {\n        param([datetime] $Date = (Get-Date))\n        return $Date.ToString('yy\/MM\/ddTHH:mm:ss.fff')\n    }\n    \n    [System.Management.Automation.CallStackFrame[]] $stackFrames = Get-PSCallStack\n    for ($k = $SkipFrames; $k -lt $stackFrames.Count; $k++) {\n        $currentPS = $stackFrames[$k]\n        if ($null -ne $currentPS.ScriptName -or $currentPS.FunctionName -eq \"&lt;ScriptBlock&gt;\") {\n            [int] $lineNumber = $currentPS.ScriptLineNumber\n            if ($null -ne $currentPS.ScriptName) {\n                $scriptFullName = $currentPS.ScriptName\n            }\n            else {\n                if ($null -eq (Get-Variable VMPosition -ErrorAction:Ignore)) {\n                    $scriptFullName = '&lt;interactive&gt;'\n                }\n                else {\n                    $lineNumber += $VMPosition.Line\n                    $scriptFullName = $VMPosition.File\n                }\n            }\n            \n            $scriptName = $scriptFullName.Substring(1 + $scriptFullName.LastIndexOf('\\'))  \n            return \"[{0}:{1:00} {2} {3}:{4,-3}] {5}\" -f $env:COMPUTERNAME, [System.Threading.Thread]::CurrentThread.ManagedThreadId, (Get-Time $date), $scriptName, $lineNumber, $message\n        }\n    }\n    \n    throw \"Cannot figure out the right caller for $SkipFrames, $stackFrames\"\n}\n\nfunction Get-CurrentBootSession {\n    [CmdletBinding()]\n    [OutputType([string])]\n    param()\n    return (Get-CimInstance -ClassName:Win32_OperatingSystem).LastBootUpTime.ToString('yy\/MM\/ddTHH:mm:ss.fff')\n}\n\nfunction Exit-Install {\n    [CmdletBinding()]\n    param ([Parameter(Mandatory, Position = 0)] [string] $Message,\n        [Parameter(Mandatory)] [uint32] $ExitCode)\n    $fullMessage = Get-TraceMessage -Message:$Message\n    if ($Script:ERR_PENDING_REBOOT -eq $ExitCode) {\n        ## Subsequent runs of this scripts will be able to detect if a reboot happend since it was requested\n        Set-RegistryKey -LiteralPath:$Script:InstallPS1HKLM -Name:'PendingReboot' -Value:$(Get-CurrentBootSession)\n    }\n    if ($null -ne $Script:InstallLog) {\n        $Script:InstallLog.WriteLine($fullMessage)\n        $exitMessage = Get-TraceMessage -Message (\"Script will exit with code {0}(0x{0:x})\" -f $ExitCode) -SkipFrames:1\n        $Script:InstallLog.WriteLine($exitMessage)\n        $Script:InstallLog.Close()\n        $Script:InstallLog = $null\n    }\n    Write-Error $fullMessage -ErrorAction:Continue\n    exit $ExitCode\n}\nfunction Trace-Message {\n    [CmdletBinding()]\n    param ([Parameter(Mandatory, Position = 0)] [string] $Message,\n        [Parameter(Position = 1)][uint16] $SkipFrames = 2,\n        [datetime] $Date = (Get-Date))\n    $fullMessage = Get-TraceMessage -Message:$Message -SkipFrames:$SkipFrames -Date:$Date\n    if ($null -ne $Script:InstallLog) {\n        $Script:InstallLog.WriteLine($fullMessage)\n    }\n    Write-Host $fullMessage\n}\n\nfunction Trace-Warning {\n    [CmdletBinding()]\n    param ([Parameter(Mandatory)] [string] $Message)\n    $fullMessage = Get-TraceMessage \"WARNING: $message\"\n    ## not using Write-Warning is intentional.\n    if ($null -ne $Script:InstallLog) {\n        $Script:InstallLog.WriteLine($fullMessage)\n    }\n    Write-Host $fullMessage\n}\n\nfunction Use-Object {\n    [CmdletBinding()]\n    param (\n        [Parameter(Mandatory = $true)]\n        [AllowEmptyString()] [AllowEmptyCollection()] [AllowNull()]\n        [Object]$InputObject,\n        [Parameter(Mandatory = $true)]\n        [scriptblock] $ScriptBlock,\n        [Object[]]$ArgumentList\n    )\n\n    try {\n        &amp; $ScriptBlock @ArgumentList\n    }\n    catch {\n        throw\n    }\n    finally {\n        if ($null -ne $InputObject -and $InputObject -is [System.IDisposable]) {\n            $InputObject.Dispose()\n        }\n    }\n}\n\nfunction New-TempFile {\n    #New-TemporaryFile is not available on PowerShell 4.0.\n    [CmdletBinding()]\n    [OutputType('System.IO.FileInfo')]\n    param()\n\n    $path = [System.Io.Path]::GetTempPath() + [guid]::NewGuid().Guid + '.tmp'\n    return New-Object -TypeName 'System.IO.FileInfo' -ArgumentList:$path\n}\n\nfunction Get-Digest {\n    &lt;#\n.SYNOPSIS\n    Returns an unique digest dependent on $sa array\n#&gt;\n    param ([string[]] $sa)\n    $sb = New-Object -TypeName:'System.Collections.Generic.List[byte]'\n    $sha256 = [System.Security.Cryptography.SHA256]::Create()\n    foreach ($element in $sa) {\n        $null = $sb.AddRange($sha256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($element)))\n    }\n    $hash = $sha256.ComputeHash($sb.ToArray())\n    $sha256.Dispose()\n    $rez = New-Object -TypeName:'System.Text.StringBuilder'\n    foreach ($hb in $hash) {\n        $null = $rez.Append($hb.ToString('X2'))\n    }\n    return $rez.ToString()\n}\n\nfunction Get-ScriptVersion {\n    [CmdLetBinding()]\n    param([string] $LiteralPath)\n    ## DO NOT EDIT THIS BLOCK - BEGIN\n    $version = @{\n        Major    = '1'\n        Minor    = '20231204'\n        Patch    = '0'\n        Metadata = 'E8E12DEA'\n    }\n    ## DO NOT EDIT THIS BLOCK - END\n    [bool] $seen = $false\n    $scriptLines = @(Get-Content -Path:$LiteralPath | ForEach-Object {\n            $line = $_\n            if (-not $seen) {            \n                $seen = $line -ieq \"#Copyright (C) Microsoft Corporation. All rights reserved.\"\n                if ($line -match \"^\\s*Metadata\\s*=\\s*'([0-9A-F]{8})'\") {\n                    # skip it\n                }\n                else {\n                    $line\n                }\n            }\n        })\n    \n    $digest = (Get-Digest -sa:$scriptLines).Substring(0, 8)\n    if ($digest -ne $version.Metadata) {\n        $version.Patch = '1'\n    }\n    \n    return \"$($version.Major).$($version.Minor).$($version.Patch)+$digest\"\n}\n\nfunction Measure-Process {\n    [CmdletBinding()]\n    param (\n        [Parameter(Mandatory = $true)]\n        [ValidateScript( { Test-Path -LiteralPath:$_ -PathType:Leaf })]\n        [string] $FilePath,\n\n        [AllowEmptyString()]\n        [AllowEmptyCollection()]\n        [string[]] $ArgumentList,\n        [switch] $PassThru,\n        [ValidateScript( { Test-Path -LiteralPath:$_ -PathType:Container })]\n        [string] $WorkingDirectory = (Get-Location).Path,\n        [uint16] $SkipFrames = 3)\n\n    Trace-Message \"Running $FilePath $ArgumentList in $WorkingDirectory ...\" -SkipFrames:$SkipFrames\n\n    $startParams = @{\n        FilePath               = $FilePath\n        WorkingDirectory       = $WorkingDirectory\n        Wait                   = $true\n        NoNewWindow            = $true\n        PassThru               = $true        \n        RedirectStandardOutput = New-TempFile\n        RedirectStandardError  = New-TempFile\n    }\n    if ($ArgumentList) {\n        $startParams.ArgumentList = $ArgumentList\n    }\n    $info = @{ ExitCode = 1 }\n    try {\n        Use-Object ($proc = Start-Process @startParams) {\n            param ($ArgumentList, $SkipFrames)\n            [TimeSpan] $runningTime = ($proc.ExitTime - $proc.StartTime).Ticks\n            $exitCode = $info.exitCode = $proc.ExitCode\n            $info.ExitTime = $proc.ExitTime\n            Get-Content -Path $startParams.RedirectStandardOutput | ForEach-Object {\n                Trace-Message \"[StandardOutput]: $_\" -Date:$info.ExitTime -SkipFrames:$(1 + $SkipFrames)\n            }\n            Get-Content -Path $startParams.RedirectStandardError | ForEach-Object {\n                Trace-Message \"[StandardError]: $_\" -Date:$info.ExitTime -SkipFrames:$(1 + $SkipFrames)\n            }\n            $commandLine = $(Split-Path -Path:$FilePath -Leaf)\n            if ($ArgumentList) {\n                $commandLine += \" $ArgumentList\"\n            }\n            $message = if (0 -eq $exitCode) {\n                \"Command `\"$commandLine`\" run for $runningTime\"\n            }\n            else {\n                \"Command `\"$commandLine`\" failed with error $exitCode after $runningTime\"\n            }\n            Trace-Message $message -SkipFrames:$SkipFrames           \n            if (-not $PassThru -and 0 -ne $exitCode) {\n                exit $exitCode\n            }\n        } -ArgumentList:$ArgumentList, (2 + $SkipFrames)\n    }\n    catch {\n        throw\n    }\n    finally {\n        Remove-Item -LiteralPath:$startParams.RedirectStandardError.FullName -Force -ErrorAction:SilentlyContinue\n        Remove-Item -LiteralPath:$startParams.RedirectStandardOutput.FullName -Force -ErrorAction:SilentlyContinue\n    }\n    if ($PassThru) {\n        return $info.ExitCode\n    }\n}\n\nfunction Test-CurrentUserIsInRole {\n    [CmdLetBinding()]\n    param([string[]] $SIDArray)\n    foreach ($sidString in $SIDArray) {\n        $sid = New-Object System.Security.Principal.SecurityIdentifier($sidString)\n        $role = $sid.Translate([Security.Principal.NTAccount]).Value\n        if (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole($role)) {\n            return $true\n        }\n    }\n    return $false\n}\n\nfunction Get-GuidHelper {\n    [CmdletBinding()]\n    param (\n        # Parameter help description\n        [Parameter(Mandatory)] [string] $Name,\n        [Parameter(Mandatory)] [string] $Value,\n        [Parameter(Mandatory)] [string] $LiteralPath,\n        [Parameter(Mandatory)] [string] $Pattern\n    )\n    ## guids are regenerated every time we change .wx{i,s} files\n    ## @note: SilentlyContinue just in case $Path does not exist.\n    $result = @(Get-ChildItem -LiteralPath:$LiteralPath -ErrorAction:SilentlyContinue |\n        Where-Object { $_.GetValue($Name) -match $Value -and $_.PSChildName -match $Pattern } |\n        Select-Object -ExpandProperty:PSChildName)\n    if ($result.Count -eq 1) {\n        return $result[0]\n    }\n    return $null\n}\n\nfunction Get-UninstallGuid {\n    [CmdletBinding()]\n    param (\n        # Parameter help description\n        [Parameter(Mandatory)] [string] $DisplayName\n    )\n    $extraParams = @{\n        Name        = 'DisplayName'\n        Value       = $DisplayName\n        LiteralPath = 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall'\n        Pattern     = '^{[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}}$'\n    }\n    \n    return Get-GuidHelper @extraParams\n}\n\nfunction Get-CodeSQUID {\n    [CmdletBinding()]\n    param (\n        [string] $ProductName\n    )\n    \n    if (-not (Get-PSDrive -Name:'HKCR' -ErrorAction:SilentlyContinue)) {\n        $null = New-PSDrive -Name:'HKCR' -PSProvider:Registry -Root:HKEY_CLASSES_ROOT -Scope:Script\n        Trace-Message \"'HKCR' PSDrive created(script scoped)\"\n    }\n    ## msi!MsiGetProductInfoW\n    $extraParams = @{\n        Name        = 'ProductName'\n        Value       = $ProductName\n        LiteralPath = 'HKCR:\\Installer\\Products'\n        Pattern     = '^[0-9a-f]{32}$'\n    }\n    \n    return Get-GuidHelper @extraParams\n}\n\nfunction Test-IsAdministrator {\n    Test-CurrentUserIsInRole 'S-1-5-32-544'\n}\n\nfunction Get-FileVersion {\n    [OutputType([System.Version])]\n    [CmdletBinding()]\n    param([Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $File)\n    $versionInfo = [Diagnostics.FileVersionInfo]::GetVersionInfo($File)\n    New-Object System.Version $($versionInfo.FileMajorPart), $($versionInfo.FileMinorPart), $($versionInfo.FileBuildPart), $($versionInfo.FilePrivatePart)\n}\n\nfunction Get-OSVersion {\n    [OutputType([System.Version])]\n    [CmdletBinding()]\n    param ()\n    # [environment]::OSVersion.Version on PowerShell ISE has issues on 2012R2 (see https:\/\/devblogs.microsoft.com\/scripting\/use-powershell-to-find-operating-system-version\/)\n    # Get-CIMInstance provides a string where we don't get the revision. \n    return Get-FileVersion -File:\"$env:SystemRoot\\system32\\ntoskrnl.exe\"\n}\n\nfunction Invoke-Member {\n    [CmdletBinding()]\n    param ( [Object] $ComObject,\n        [Parameter(Mandatory)] [string] $Method,\n        [System.Object[]] $ArgumentList)\n    if ($ComObject) {\n        return $ComObject.GetType().InvokeMember($Method, [System.Reflection.BindingFlags]::InvokeMethod, $null, $ComObject, $ArgumentList)\n    }\n}\n\nfunction Invoke-GetProperty {\n    [CmdletBinding()]\n    param ( [Object] $ComObject,\n        [Parameter(Mandatory)] [string] $Property,\n        [Parameter(Mandatory)] [int] $Colummn)\n    if ($ComObject) {\n        return $ComObject.GetType().InvokeMember($Property, [System.Reflection.BindingFlags]::GetProperty, $null, $ComObject, $Colummn)\n    }\n}\n\nfunction ReleaseComObject {\n    [CmdletBinding()]\n    param ([Object] $ComObject)\n    if ($ComObject) {\n        $null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject($ComObject)\n    }\n}\n\nfunction Get-MsiFilesInfo {\n    [CmdletBinding()]\n    param ([Parameter(Mandatory)] [string] $MsiPath)\n\n    function Get-MsiFileTableHelper {\n        param ([Parameter(Mandatory)] [Object] $Database)\n        try {\n            ## @see https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/msi\/file-table\n            $view = Invoke-Member $Database 'OpenView' (\"SELECT * FROM File\")\n            Invoke-Member $view 'Execute'\n            $rez = @{}\n            while ($null -ne ($record = Invoke-Member $view 'Fetch')) {\n                $file = Invoke-GetProperty $record 'StringData' 1\n                $FileName = Invoke-GetProperty $record 'StringData' 3\n                $versionString = $(Invoke-GetProperty $record 'StringData' 5)\n                $version = if ($versionString) {\n                    [version]$versionString\n                }\n                else {\n                    $null\n                }\n                $rez.$file = [ordered] @{\n                    Component  = Invoke-GetProperty $record 'StringData' 2\n                    FileName   = $FileName\n                    FileSize   = [convert]::ToInt64($(Invoke-GetProperty $record 'StringData' 4))\n                    Version    = $version\n                    Language   = Invoke-GetProperty $record 'StringData' 6\n                    Attributes = [convert]::ToInt16($(Invoke-GetProperty $record 'StringData' 7))\n                    Sequence   = [convert]::ToInt16($(Invoke-GetProperty $record 'StringData' 8))\n                }\n                ReleaseComObject $record\n            }\n            return $rez\n        }\n        catch {\n            throw\n        }\n        finally {\n            Invoke-Member $view 'Close'\n            ReleaseComObject $view \n        }\n    }\n    \n    try {\n        $installer = New-Object -ComObject:WindowsInstaller.Installer        \n        ## @see https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/msi\/database-object\n        $database = Invoke-Member $installer 'OpenDatabase' ($MsiPath, 0)\n        return Get-MsiFileTableHelper -Database:$database\n    }\n    catch {\n        throw\n    }\n    finally {\n        ReleaseComObject $database\n        ReleaseComObject $installer\n    }\n}\n\nfunction Test-ExternalScripts {\n    [CmdletBinding()]\n    param ()\n    if ($OnboardingScript.Length) {\n        if (-not (Test-Path -LiteralPath:$OnboardingScript -PathType:Leaf)) {\n            Exit-Install -Message:\"$OnboardingScript does not exist\" -ExitCode:$ERR_ONBOARDING_NOT_FOUND\n        }       \n        ## validate it is an \"onboarding\" script.\n        $on = Get-Content -LiteralPath:$OnboardingScript | Where-Object {\n            $_ -match 'add\\s+\"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Advanced Threat Protection\"\\s+\\\/v\\s+OnboardingInfo'\n        }\n        if ($on.Length -eq 0) {\n            Exit-Install -Message:\"Not an onboarding script: $OnboardingScript\" -ExitCode:$ERR_INVALID_PARAMETER\n        }\n\n        if (-not (Test-IsAdministrator)) {\n            Exit-Install -Message:'Onboarding scripts need to be invoked from an elevated process' -ExitCode:$ERR_INSUFFICIENT_PRIVILEGES\n        }\n        \n        $pause = Get-Content -LiteralPath:$OnboardingScript | Where-Object { $_ -imatch '^pause$' }\n        if ($pause.Length -ne 0) {\n            ## Please read: https:\/\/github.com\/microsoft\/mdefordownlevelserver#project\n            Exit-Install -Message:\"Please use the onboarding script for Group Policy as it is non-interactive, $OnboardingScript might wait for user input\" -ExitCode:$ERR_INVALID_SCRIPT_TYPE\n        }\n    }\n\n    if ($OffboardingScript.Length) {\n        if (-not (Test-Path -LiteralPath:$OffboardingScript -PathType:Leaf)) {\n            Exit-Install -Message:\"$OffboardingScript does not exist\" -ExitCode:$ERR_OFFBOARDING_NOT_FOUND\n        }\n\n        $off = Get-Content -LiteralPath:$OffboardingScript | Where-Object {\n            $_ -match 'add\\s+\"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Advanced Threat Protection\"\\s+\\\/v\\s+696C1FA1-4030-4FA4-8713-FAF9B2EA7C0A'\n        }\n        \n        if ($off.Length -eq 0) {\n            Exit-Install -Message:\"Not an offboarding script: $OffboardingScript\" -ExitCode:$ERR_INVALID_PARAMETER\n        }\n\n        if (-not (Test-IsAdministrator)) {\n            Exit-Install -Message:'Offboarding scripts need to be invoked from an elevated process' -ExitCode:$ERR_INSUFFICIENT_PRIVILEGES\n        }\n\n        $pause = Get-Content -LiteralPath:$OffboardingScript | Where-Object { $_ -imatch '^pause$' }\n        if ($pause.Length -ne 0) {\n            ## Please read: https:\/\/github.com\/microsoft\/mdefordownlevelserver#project\n            Exit-Install -Message:\"Please use the offboarding script for Group Policy as it is non-interactive, $OffboardingScript might wait for user input\" -ExitCode:$ERR_INVALID_SCRIPT_TYPE\n        }\n    }   \n}\n\nfunction Get-RegistryKey {\n    [CmdLetBinding()]\n    param([Parameter(Mandatory)][ValidateNotNullOrEmpty()][string] $LiteralPath,\n        [Parameter(Mandatory)][ValidateNotNullOrEmpty()][string] $Name)\n\n    ## @note: Get-ItemPropertyValue ... -ErrorAction:SilentlyContinue is complaining about errors.\n    $k = Get-ItemProperty -LiteralPath:$LiteralPath -Name:$Name -ErrorAction:SilentlyContinue\n    if ($k) {\n        return $k.$Name\n    }\n\n    return $null\n}\n\nfunction Invoke-MpCmdRun {\n    [CmdLetBinding()]\n    param(\n        [AllowEmptyString()] [AllowEmptyCollection()] [string[]] $ArgumentList,\n        [uint16] $SkipFrames = 4\n    )\n    $startParams = @{\n        FilePath   = Join-Path -Path:$(Get-RegistryKey -LiteralPath:'HKLM:\\SOFTWARE\\Microsoft\\Windows Defender' -Name:'InstallLocation') 'MpCmdRun.exe'\n        SkipFrames = $SkipFrames\n    }   \n    if ($ArgumentList) {\n        $startParams.ArgumentList = $ArgumentList\n    }\n    Measure-Process @startParams\n}\n\nfunction Start-TraceSession {\n    [CmdLetBinding()]\n    param()\n\n    $guid = [guid]::NewGuid().Guid\n    $wdprov = Join-Path -Path:$env:TEMP \"$guid.temp\"\n    $tempFile = Join-Path -Path:$env:TEMP \"$guid.etl\"\n    $etlLog = \"$PSScriptRoot\\$logBase.etl\"\n    $wppTracingLevel = 'WppTracingLevel'        \n    $reportingPath = 'HKLM:\\Software\\Microsoft\\Windows Defender\\Reporting'\n    $etlParams = @{\n        ArgumentList = @($PSScriptRoot, $logBase, $wdprov, $tempFile, $etlLog, $wppTracingLevel, $reportingPath)\n    }\n\n    if (-not (Test-IsAdministrator)) {\n        # non-administrator should be able to install.\n        $etlParams.Credential = Get-Credential -UserName:Administrator -Message:\"Administrator credential are required for starting an ETW session:\"\n        $etlParams.ComputerName = 'localhost'\n        $etlParams.EnableNetworkAccess = $true\n    }\n\n    if (Test-Path -LiteralPath:$etlLog -PathType:leaf) {\n        if (Test-Path -LiteralPath:\"$PSScriptRoot\\$logBase.prev.etl\") {\n            Remove-Item -LiteralPath:\"$PSScriptRoot\\$logBase.prev.etl\" -ErrorAction:Stop\n        }\n        Rename-Item -LiteralPath:$etlLog -NewName:\"$logBase.prev.etl\" -ErrorAction:Stop\n    }\n\n    $scmWppTracingKey = 'HKLM:\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Tracing\\SCM\\Regular'\n    $scmWppTracingValue = 'TracingDisabled'\n    $scmTracingDisabled = Get-RegistryKey -LiteralPath:$scmWppTracingKey -Name:$scmWppTracingValue\n    if (1 -eq $scmTracingDisabled) {\n        ## certain SCM issues could be investigated only if ebcca1c2-ab46-4a1d-8c2a-906c2ff25f39 is enabled.\n        ## Unfortunatelly SCM does not register ebcca1c2-ab46-4a1d-8c2a-906c2ff25f39 when HKLM:\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Tracing\\SCM\\Regular[TracingDisabled] is (DWORD)1,\n        ## therefore it cannot be enabled \/ disabled without a restart.\n        Trace-Warning \"Service Control Manager tracing is disabled (see $scmWppTracingKey[$scmWppTracingValue])\"\n    }\n\n    Invoke-Command @etlparams -ScriptBlock: {\n        param($ScriptRoot, $logBase, $wdprov, $tempFile, $etlLog, $wppTracingLevel, $reportingPath);\n        ## enable providers\n        $providers = @(\n            @{Guid = 'ebcca1c2-ab46-4a1d-8c2a-906c2ff25f39'; Flags = 0x0FFFFFFF; Level = 0xff; Name = \"SCM\" },\n            @{Guid = 'B0CA1D82-539D-4FB0-944B-1620C6E86231'; Flags = 0xffffffff; Level = 0xff; Name = 'EventLog' },\n            @{Guid = 'A676B545-4CFB-4306-A067-502D9A0F2220'; Flags = 0xfffff; Level = 0x5; Name = 'setup' },\n            @{Guid = '81abafee-28b9-4df5-bb2d-5b0be87829f5'; Flags = 0xff; Level = 0x1f; Name = 'mpwixca' },\n            @{Guid = '68edb168-7705-494b-a746-9297abdc91d3'; Flags = 0xff; Level = 0x1f; Name = 'mpsigstub' },\n            @{Guid = '2a94554c-2fbe-46d0-9fa6-60562281b0cb'; Flags = 0xff; Level = 0x1f; Name = 'msmpeng' },\n            @{Guid = 'db30e9dc-354d-48b5-9dc0-aeaebc5c6b54'; Flags = 0xff; Level = 0x1f; Name = 'mpclient' },\n            @{Guid = 'ac45fef1-612b-4066-85a7-dd0a5e8a7f30'; Flags = 0xff; Level = 0x1f; Name = 'mpsvc' },\n            @{Guid = '5638cd78-bc82-608a-5b69-c9c7999b411c'; Flags = 0xff; Level = 0x1f; Name = 'mpengine' },\n            @{Guid = '449df70e-dba7-42c8-ba01-4d0911a4aecb'; Flags = 0xff; Level = 0x1f; Name = 'mpfilter' },\n            @{Guid = 'A90E9218-1F47-49F5-AB71-9C6258BD7ECE'; Flags = 0xff; Level = 0x1f; Name = 'mpcmdrun' },\n            @{Guid = '0c62e881-558c-44e7-be07-56b991b9401a'; Flags = 0xff; Level = 0x1f; Name = 'mprtp' },\n            @{Guid = 'b702d31c-f586-4fc0-bcf5-f929745199a4'; Flags = 0xff; Level = 0x1f; Name = 'nriservice' },\n            @{Guid = '4bc60e5e-1e5a-4ec8-b0a3-a9efc31c6667'; Flags = 0xff; Level = 0x1f; Name = 'nridriver' },\n            @{Guid = 'FFBD47B1-B3A9-4E6E-9A44-64864363DB83'; Flags = 0xff; Level = 0x1f; Name = 'mpdlpcmd' },\n            @{Guid = '942bda7f-e07d-5a00-96d3-92f5bcb7f377'; Flags = 0xff; Level = 0x1f; Name = 'mpextms' },\n            @{Guid = 'bc4992b8-a44c-4f70-834b-9d45df9b1824'; Flags = 0xff; Level = 0x1f; Name = 'WdDevFlt' }\n        )\n        Set-Content -LiteralPath:$wdprov -Value:\"# {PROVIDER_GUID}&lt;space&gt;FLAGS&lt;space&gt;LEVEL\" -Encoding:ascii\n        $providers | ForEach-Object {\n            # Any line that starts with '#','*',';' is commented out\n            # '-' in front of a provider disables it.\n            # {PROVIDER_GUID}&lt;space&gt;FLAGS&lt;space&gt;LEVEL\n            Add-Content -LiteralPath:$wdprov -Value:(\"{{{0}}} {1} {2}\" -f $_.Guid, $_.Flags, $_.Level) -Encoding:ascii\n        }        \n        \n        try {            \n            $jobParams = @{\n                Name               = \"Setting up $wppTracingLevel\"\n                ScriptBlock        = { \n                    param([string] $reportingPath, [string] $wppTracingLevel)\n                    function Set-RegistryKey {\n                        [CmdletBinding()]\n                        param([Parameter(Mandatory)][string] $LiteralPath,\n                            [Parameter(Mandatory)][string] $Name,\n                            [Parameter(Mandatory)][object] $Value)\n            \n                        function Set-ContainerPath {\n                            [CmdletBinding()]\n                            param([Parameter(Mandatory)][string] $LiteralPath)\n                            if (!(Test-Path -LiteralPath:$LiteralPath -PathType:Container)) {\n                                $parent = Split-Path -Path:$LiteralPath -Parent\n                                Set-ContainerPath -LiteralPath:$parent\n                                $leaf = Split-Path -Path:$LiteralPath -Leaf\n                                $null = New-Item -Path:$parent -Name:$leaf -ItemType:Directory\n                            }\n                        }   \n                        Set-ContainerPath -LiteralPath:$LiteralPath\n                        Set-ItemProperty -LiteralPath:$LiteralPath -Name:$Name -Value:$Value\n                    }\n\n                    Set-RegistryKey -LiteralPath:$reportingPath -Name:$wppTracingLevel -Value:0 -ErrorAction:SilentlyContinue\n                }\n                ArgumentList       = @($reportingPath, $wppTracingLevel)\n                ScheduledJobOption = New-ScheduledJobOption -RunElevated\n            }\n            try {\n                $scheduledJob = Register-ScheduledJob @jobParams -ErrorAction:Stop\n                $taskParams = @{\n                    TaskName  = $scheduledJob.Name\n                    Action    = New-ScheduledTaskAction -Execute $scheduledJob.PSExecutionPath -Argument:$scheduledJob.PSExecutionArgs\n                    Principal = New-ScheduledTaskPrincipal -UserId:'NT AUTHORITY\\SYSTEM' -LogonType:ServiceAccount -RunLevel:Highest\n                }\n                $scheduledTask = Register-ScheduledTask @taskParams -ErrorAction:Stop\n                Start-ScheduledTask -InputObject:$scheduledTask -ErrorAction:Stop -AsJob | Wait-Job | Remove-Job -Force -Confirm:$false\n                $SCHED_S_TASK_RUNNING = 0x41301\n                do {\n                    Start-Sleep -Milliseconds:10\n                    $LastTaskResult = (Get-ScheduledTaskInfo -InputObject:$scheduledTask).LastTaskResult\n                } while ($LastTaskResult -eq $SCHED_S_TASK_RUNNING)\n            }\n            catch {\n                Trace-Warning \"Error: $_\"\n            }\n            finally {\n                if ($scheduledJob) {\n                    Unregister-ScheduledJob -InputObject $scheduledJob -Force\n                }\n                if ($scheduledTask) {\n                    Unregister-ScheduledTask -InputObject $scheduledTask -Confirm:$false\n                }\n            }\n            $wpp = Get-RegistryKey -LiteralPath:$reportingPath -Name:$wppTracingLevel\n            if ($null -eq $wpp) {\n                Trace-Warning \"$reportingPath[$wppTracingLevel] could not be created\"\n            }\n            else {\n                Trace-Message \"$reportingPath[$wppTracingLevel]=$wpp\"\n            }\n\n            #Set-ItemProperty -LiteralPath:'HKLM:\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Tracing\\SCM\\Regular' -Name:'TracingDisabled' -Value:0\n            &amp; logman.exe create trace -n $logBase -pf $wdprov -ets -o $tempFile *&gt;$null\n            if (0 -eq $LASTEXITCODE) {\n                Trace-Message \"Tracing session '$logBase' started.\"\n            }\n            else {\n                Trace-Warning \"logman.exe create trace -n $logBase -pf $wdprov -ets -o $tempFile exited with exitcode $LASTEXITCODE\"\n            }\n        }\n        catch {\n            throw\n        }\n        finally {\n            Remove-Item -LiteralPath:$wdprov -ErrorAction:Continue\n        }\n    }\n    return $etlParams\n}\n\n$currentDate = Get-Date\n$Installps1LogName = \"InstallPS1-$env:COMPUTERNAME.$($currentDate.ToString('yyMMddTHHmmssfffzzz').Replace(':', '')).log\"\nif (-not $NoMSILog.IsPresent -or -not $NoEtl.IsPresent) { \n    $InstallLogPath = Join-Path $PSScriptRoot -ChildPath:$Installps1LogName\n    try {\n        $Script:InstallLog = New-Object -TypeName:'System.IO.StreamWriter' -ArgumentList:@($InstallLogPath, $true)\n        Trace-Message \"$($PSCmdLet.MyInvocation.MyCommand.Name) traces will be saved to $InstallLogPath\"\n    } \n    catch {\n        Trace-Warning \"Error: $_\"\n    } \n}\nTrace-Message \"Running command: $(Get-CommandLine $PSCmdLet.MyInvocation)\"\n\n@(\n    @{ Name = 'ERR_INTERNAL'; Value = 1 }                   ## Not used.\n    @{ Name = 'ERR_INSUFFICIENT_PRIVILEGES'; Value = 3 }    ## Are you running as Administrator?\n    @{ Name = 'ERR_NO_INTERNET_CONNECTIVITY'; Value = 4 }   ## Are you behind a proxy? Is network on?\n    @{ Name = 'ERR_CONFLICTING_APPS'; Value = 5 }           ## Not used.\n    @{ Name = 'ERR_INVALID_PARAMETER'; Value = 6 }          ## Are you providing the right parameters to this script? Did you missmatch **On**boardingScript with an **Off**boarding script or vice-versa?\n    @{ Name = 'ERR_UNSUPPORTED_DISTRO'; Value = 10 }        ## Is this a server SKU? Is this '2012 R2' or '2016' Server?\n    @{ Name = 'ERR_UNSUPPORTED_VERSION'; Value = 11 }       ## Uninstall using the regular Administator account (Using System was fixed in Feb 2023)\n    @{ Name = 'ERR_PENDING_REBOOT'; Value = 12 }            ## A dependent component requested a reboot.\n    @{ Name = 'ERR_INSUFFICIENT_REQUIREMENTS'; Value = 13 } ## A requirement was not satisfied, cannot continue.\n    @{ Name = 'ERR_UNEXPECTED_STATE'; Value = 14 }          ## Cannot handle the task in the current state of the product. Manual intervention is required.\n    @{ Name = 'ERR_CORRUPTED_FILE'; Value = 15 }            ## All executable files (and this script) should be signed. Was one of the files (md4ws.msi) truncated?\n    @{ Name = 'ERR_MSI_NOT_FOUND'; Value = 16 }             ## Is the MSI in the same directory like this file?\n    @{ Name = 'ERR_ALREADY_UNINSTALLED'; Value = 17 }       ## Not used.\n    @{ Name = 'ERR_DIRECTORY_NOT_WRITABLE'; Value = 18 }    ## Current directory should be writeable (to write the installation\/uninstallation logs)\n    @{ Name = 'ERR_MDE_NOT_INSTALLED'; Value = 20 }         ## Cannot uninstall something that is not installed.\n    @{ Name = 'ERR_INSTALLATION_FAILED'; Value = 21 }       ## Not used.\n    @{ Name = 'ERR_UNINSTALLATION_FAILED'; Value = 22 }     ## Not used.\n    @{ Name = 'ERR_FAILED_DEPENDENCY'; Value = 23 }         ## Not used\n    @{ Name = 'ERR_ONBOARDING_NOT_FOUND'; Value = 30 }      ## Check passed onboarding script path. Does it point to an existing file? \n    @{ Name = 'ERR_ONBOARDING_FAILED'; Value = 31 }         ## Onboarding script failed.\n    @{ Name = 'ERR_OFFBOARDING_NOT_FOUND'; Value = 32 }     ## Check passed offboarding script path. Does it point to an existing file? \n    @{ Name = 'ERR_OFFBOARDING_FAILED'; Value = 33 }        ## Offboarding script failed.\n    @{ Name = 'ERR_NOT_ONBOARDED'; Value = 34 }             ## Cannot offboard if not onboarded\n    @{ Name = 'ERR_NOT_OFFBOARDED'; Value = 35 }            ## Cannot onboard if already onboarded.\n    @{ Name = 'ERR_MSI_USED_BY_OTHER_PROCESS'; Value = 36 } ## md4ws.msi is opened by a process (orca.exe?!), preventing a successful installation.\n    @{ Name = 'ERR_INVALID_SCRIPT_TYPE'; Value = 37 }       ## Onboarding\/Offboading scripts shouldn't require any user interaction.\n    @{ Name = 'ERR_TAMPER_PROTECTED'; Value = 38 }           ## Uninstallation cannot continue, since the product is still tamper protected.\n    @{ Name = 'ERR_MDE_GROUP_POLICY_DISABLED'; Value = 39 }  ## HKLM:\\Software\\Policies\\Microsoft\\Windows Defender[DisableAntiSpyware] is set to 1.\n) | ForEach-Object { \n    Set-Variable -Name:$_.Name -Value:$_.Value -Option:Constant -Scope:Script \n}\n\nif (-not [System.Environment]::Is64BitOperatingSystem) {\n    Exit-Install \"Only 64 bit OSes (Server 2012 R2 or Server 2016) are currently supported by this script\" -ExitCode:$ERR_UNSUPPORTED_DISTRO\n}\nelseif (-not [System.Environment]::Is64BitProcess) {\n    Trace-Warning \"Current process IS NOT 64bit. Did you start a 'Windows Powershell (x86)'?!\"\n    $nativePowershell = \"$env:SystemRoot\\sysnative\\windowspowershell\\v1.0\\powershell.exe\"\n    if (-not (Test-Path -LiteralPath:$nativePowershell -PathType:Leaf)) {\n        Exit-Install \"Cannot figure out 64 bit powershell location. Please run this script from a 64bit powershell.\" -ExitCode:$ERR_UNEXPECTED_STATE\n    }\n    \n    [System.Collections.ArrayList] $argumentList = New-Object -TypeName:'System.Collections.ArrayList'\n    $argumentList.AddRange(@('-NoProfile', '-NonInteractive', '-File', $MyInvocation.MyCommand.Path))\n    if ($MyInvocation.BoundParameters.Count -gt 0) {\n        function Get-EscapeString {\n            param([string] $s)\n            if ($null -ne $s -and ' ' -in $s -and $s[0] -ne '\"') {\n                \"`\"{0}'\" -f $s\n            }\n            else {\n                $s\n            }\n        }\n        foreach ($boundparam in $MyInvocation.BoundParameters.GetEnumerator()) {\n            if ($boundparam.Value -is [switch]) {\n                if ($boundparam.Value.ToBool()) {\n                    $null = $argumentList.Add($(\"-{0}\" -f $boundparam.Key))\n                }\n            }\n            else {\n                $val = ''\n                foreach ($k in ($boundparam.Value)) {\n                    $val += if ($val.Length) { ',' } else { ':' }\n                    $val += Get-EscapeString $k\n                }\n                $null = $argumentList.Add($(\"-{0}{1}\" -f $boundparam.Key, $val))\n            }\n        }\n        foreach ($k in $MyInvocation.UnboundArguments.GetEnumerator()) {\n            $null = $argumentList.Add($(\"{0}\" -f (Get-EscapeString $k)))\n        }\n    }\n    \n    $psArgumentList = $argumentList.ToArray()\n    Trace-Message \"Running $nativePowershell $psArgumentList\"\n    &amp; $nativePowershell $psArgumentList\n    if (-not $?) {\n        Trace-Warning \"$nativePowershell $psArgumentList exited with exitcode $LASTEXITCODE\"\n    }\n    exit $LASTEXITCODE\n}\n\nTest-ExternalScripts\nif ('Tls12' -notin [Net.ServicePointManager]::SecurityProtocol) {\n    ## Server 2016\/2012R2 might not have this one enabled and all Invoke-WebRequest might fail.\n    [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12\n    Trace-Message \"[Net.ServicePointManager]::SecurityProtocol updated to '$([Net.ServicePointManager]::SecurityProtocol)'\"\n} \n\nif ($null -eq $ExtraWebRequestOptions) {\n    $ExtraWebRequestOptions = @{}\n}\nelse {\n    ## validate ExtraWebRequestOptions hash\n    [bool] $validExtraWebRequestOptions = $true\n    foreach ($useOption in 'Uri', 'OutFile', 'ErrorAction', 'UseBasicParsing') {\n        if ($ExtraWebRequestOptions.ContainsKey($useOption)) {\n            Trace-Warning \"Please remove $useOption from ExtraWebRequestOption hash and try again.\"\n            $validExtraWebRequestOptions = $false\n        }\n    }\n    if (-not $validExtraWebRequestOptions) {\n        Exit-Install -Message:\"Invalid parameter ExtraWebRequestOption (see the above warnings)\" -ExitCode:$ERR_INVALID_PARAMETER\n    }\n}\n\n$osVersion = Get-OSVersion\n\n## make sure we capture logs by default.\n[bool] $etl = -not $NoEtl.IsPresent\n[bool] $log = -not $NoMSILog.IsPresent\n\n[string] $msi = if ($DevMode.IsPresent -or ((Test-Path -Path:\"$PSScriptRoot\\md4ws-devmode.msi\") -and -not (Test-Path -Path:\"$PSScriptRoot\\md4ws.msi\"))) {\n    ## This is used internally (never released to the public) by product team to test private builds.\n    Join-Path -Path:$PSScriptRoot \"md4ws-devmode.msi\"\n}\nelse {\n    Join-Path -Path:$PSScriptRoot \"md4ws.msi\"\n}\n\n$action = if ($Uninstall.IsPresent) { 'uninstall' }  else { 'install' }\n$logBase = \"$action-$env:COMPUTERNAME\"\n\nif ($etl -or $log) {\n    ## make sure $PSSCriptRoot is writable. \n    $tempFile = Join-Path -Path:$PSScriptRoot \"$([guid]::NewGuid().Guid).tmp\"\n    Set-Content -LiteralPath:$tempFile -Value:'' -ErrorAction:SilentlyContinue\n    if (-not (Test-Path -LiteralPath:$tempFile -PathType:Leaf)) {\n        Exit-Install \"Cannot create $tempFile. Is $PSScriptRoot writable?\" -ExitCode:$ERR_DIRECTORY_NOT_WRITABLE\n    }\n    else {\n        Remove-Item -LiteralPath:$tempFile -ErrorAction:SilentlyContinue\n        $tempFile = $null\n    }\n}\n\n$etlParams = @{}\n\ntry {\n    $tempMsiLog = Join-Path -Path:$env:TEMP \"$([guid]::NewGuid().Guid).log\"\n    [System.IO.FileStream] $msiStream = $null\n    if ($action -eq 'install') {\n        ## $msi should be checked as early as possible, see ICM#413339981\n        if (-not (Test-Path -LiteralPath:$msi -PathType:leaf)) {\n            Exit-Install \"$msi does not exist. Please download latest $(Split-Path -Path:$msi -Leaf) into $PSScriptRoot and try again.\" -ExitCode:$ERR_MSI_NOT_FOUND\n        }\n        else {\n            try {\n                $msiStream = [System.IO.File]::OpenRead($msi)\n                Trace-Message (\"Handle {0} opened over {1}\" -f $msiStream.SafeFileHandle.DangerousGetHandle(), $msi)\n            }\n            catch {\n                ## Orca (https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/msi\/orca-exe) likes to keep a opened handle to $msi\n                ## and if installation happens during this time  Get-AuthenticodeSignature will get an 'Unknown' status. \n                ## Same with msiexec.exe, so better check for this scenario here.\n                Exit-Install \"Cannot open $msi for read: $_.Exception\" -ExitCode:$ERR_MSI_USED_BY_OTHER_PROCESS\n            }\n            $status = (Get-AuthenticodeSignature -FilePath:$msi).Status\n            if ($status -ne 'Valid') {\n                Exit-Install \"Unexpected authenticode signature status($status) for $msi\" -ExitCode:$ERR_CORRUPTED_FILE\n            }\n            Trace-Message \"$($(Get-FileHash -LiteralPath:$msi).Hash) $msi\"\n        }\n    }\n    if ($null -ne $RemoveMMA) {\n        $mma = New-Object -ComObject 'AgentConfigManager.MgmtSvcCfg'\n        $workspaces = @($mma.GetCloudWorkspaces() | Select-Object -ExpandProperty:workspaceId)\n        if ($RemoveMMA -in $workspaces) {\n            Trace-Message \"Removing cloud workspace $($RemoveMMA.Guid)...\" \n            $mma.RemoveCloudWorkspace($RemoveMMA)\n            $workspaces = @($mma.GetCloudWorkspaces() | Select-Object -ExpandProperty:workspaceId)\n            if ($workspaces.Count -gt 0) {\n                $mma.ReloadConfiguration()\n            }\n            else {\n                Stop-Service HealthService\n            }\n            Trace-Message \"Workspace $($RemoveMMA.Guid) removed.\"\n        }\n        else {\n            Exit-Install \"Invalid workspace id $($RemoveMMA.Guid)\" -ExitCode:$ERR_INVALID_PARAMETER\n        }\n    }\n    \n    $msiLog = \"$PSScriptRoot\\$logBase.log\"    \n    if ($log -and (Test-Path -LiteralPath:$msiLog -PathType:Leaf)) {\n        if (Test-Path -LiteralPath:\"$PSScriptRoot\\$logBase.prev.log\") {\n            Remove-Item -LiteralPath:\"$PSScriptRoot\\$logBase.prev.log\" -ErrorAction:Stop\n        }\n        Rename-Item -LiteralPath:$msiLog -NewName:\"$PSScriptRoot\\$logBase.prev.log\"\n    }\n    \n    ## The new name is 'Microsoft Defender for Endpoint' - to avoid confusions on Server 2016.\n    $displayName = 'Microsoft Defender for (Windows Server|Endpoint)'\n    $uninstallGUID = Get-UninstallGuid -DisplayName:$displayName\n\n    ## Next 3 traces are here because they are helpful for investigations.\n    $buildLabEx = Get-RegistryKey -LiteralPath:'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion' -Name:'BuildLabEx'\n    Trace-Message \"BuildLabEx: $buildLabEx\"\n    $editionID = Get-RegistryKey -LiteralPath:'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion' -Name:'EditionID'\n    Trace-Message \"EditionID: $editionID\"\n    $lastBootTime = Get-CurrentBootSession\n    Trace-Message \"LastBootUpTime: $lastBootTime\"\n    Trace-Message \"CurrentTime   : $($currentDate.ToString('yy\/MM\/ddTHH:mm:ss.fffzzz'))\"\n    $scriptPath = $MyInvocation.MyCommand.Path\n    Trace-Message \"$($MyInvocation.MyCommand.Name) version: $(Get-ScriptVersion -LiteralPath:$scriptPath)\"\n\n    $pendingReboot = Get-RegistryKey -LiteralPath:$Script:InstallPS1HKLM -Name:'PendingReboot'\n    if ($pendingReboot -eq $lastBootTime) {        \n        Trace-Warning \"Previous run of $($PSCmdLet.MyInvocation.MyCommand.Name) requested a reboot\"\n        Exit-Install -Message:\"Please restart this computer to continue $($PSCmdLet.MyInvocation.MyCommand.Name) actions\" -ExitCode:$ERR_PENDING_REBOOT\n    }\n    elseif ($null -ne $pendingReboot) {\n        Remove-ItemProperty -LiteralPath:$Script:InstallPS1HKLM -Name:'PendingReboot' -ErrorAction:SilentlyContinue\n    }\n\n    if ($action -eq 'install') {\n        if ($osVersion.Major -eq 6 -and $osVersion.Minor -eq 3) {\n            $windefend = Get-Service -Name:'WinDefend' -ErrorAction:SilentlyContinue\n            $wdnissvc = Get-Service -Name:'WdNisSvc' -ErrorAction:SilentlyContinue\n            $wdfilter = Get-Service -Name:'WdFilter' -ErrorAction:SilentlyContinue\n            if ($windefend -and -not $wdnissvc -and -not $wdfilter) {\n                ## workaround for ICM#278342470 (or VSO#37292177). Fixed on MOCAMP version 4.18.2111.150 or newer.\n                if ($windefend.Status -eq 'Running') {\n                    Exit-Install \"Please reboot this computer to remove 'WinDefend' Service\" -ExitCode:$ERR_PENDING_REBOOT\n                }\n                elseif ($windefend.Status -eq 'Stopped') {\n                    $winDefendServicePath = 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\WinDefend'\n                    if (Test-Path -LiteralPath:$winDefendServicePath) {\n                        $imagePath = Get-RegistryKey -LiteralPath:$winDefendServicePath -Name:'ImagePath'\n                        Trace-Message \"WinDefend service is Stopped. ImagePath is $imagePath. Trying to remove $winDefendServicePath\"\n                        Remove-Item -LiteralPath:$winDefendServicePath -Force -Recurse -ErrorAction:SilentlyContinue\n                        if (Test-Path -LiteralPath:$winDefendServicePath) {\n                            Exit-Install \"Cannot remove $winDefendServicePath\" -ExitCode:$ERR_UNEXPECTED_STATE\n                        }\n                    }\n                    else {\n                        Trace-Warning \"WinDefend service is stopped but $winDefendServicePath is gone. This usually happens when running this script more than once without restarting the machine.\"\n                    }\n                    Exit-Install \"Please restart this machine to complete 'WinDefend' service removal\" -ExitCode:$ERR_PENDING_REBOOT\n                }\n                else {\n                    Exit-Install -Message:\"Unexpected WinDefend service status: $($windefend.Status)\" -ExitCode:$ERR_UNEXPECTED_STATE\n                }\n            }\n\n            ## SCEP is different on Server 2016.\n            $path = \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Microsoft Security Client\"        \n            if (Test-Path -LiteralPath:$path) {\n                $displayName = (Get-ItemProperty -LiteralPath:$path -Name:'DisplayName').DisplayName\n                # See camp\\src\\amcore\\Antimalware\\Source\\AppLayer\\Components\\Distribution\\Common\\CmdLineParser.h\n                $exitCode = Measure-Process -FilePath:\"$env:ProgramFiles\\Microsoft Security Client\\Setup.exe\" -ArgumentList:@('\/u', '\/s') -PassThru\n                if (0 -eq $exitCode) {\n                    Trace-Message \"Uninstalling '$displayName' successful.\"\n                }\n                else {\n                    Trace-Warning \"Uninstalling '$displayName' exitcode: $exitCode.\"\n                }\n            }\n\n            # Server2012R2 needs two KBs to be installed ... \n            function Install-KB {\n                [CmdletBinding()]\n                param([string] $Uri, [string]$KB, [scriptblock] $scriptBlock)\n                $present = &amp; $scriptBlock\n                if ($present) {\n                    return\n                }\n                $PreviousProgressPreference = $ProgressPreference               \n                $outFile = Join-Path -Path:$env:TEMP $((New-Object System.Uri $Uri).Segments[-1])\n                try {\n                    $ProgressPreference = 'SilentlyContinue'\n                    if (Get-HotFix -Id:$KB -ErrorAction:SilentlyContinue) {\n                        Trace-Message \"$KB already installed.\"\n                        return\n                    }\n                    Trace-Message \"Downloading $KB to $outFile\"\n                    Invoke-WebRequest -Uri:$Uri -OutFile:$outFile -ErrorAction:Stop @ExtraWebRequestOptions\n                    Trace-Message \"Installing $KB\"\n                    $link = \"https:\/\/support.microsoft.com\/kb\/{0}\" -f $($KB.Substring(2))\n                    $exitCode = Measure-Process -FilePath:$((Get-Command 'wusa.exe').Path) -ArgumentList:@($outFile, '\/quiet', '\/norestart') -PassThru\n                    if (0 -eq $exitCode) {\n                        Trace-Message \"$KB installed.\"\n                    }\n                    elseif (0x80240017 -eq $exitCode) {\n                        #0x80240017 = WU_E_NOT_APPLICABLE = Operation was not performed because there are no applicable updates.\n                        Exit-Install -Message:\"$KB not applicable, please follow the instructions from $link\" -ExitCode:$ERR_INSUFFICIENT_REQUIREMENTS\n                    }\n                    elseif (0xbc2 -eq $exitCode) {\n                        #0xbc2=0n3010,ERROR_SUCCESS_REBOOT_REQUIRED The requested operation is successful. Changes will not be effective until the system is rebooted\n                        Exit-Install -Message \"$KB required a reboot\" -ExitCode:$ERR_PENDING_REBOOT\n                    }\n                    else {\n                        Exit-Install -Message:\"$KB installation failed with exitcode: $exitCode. Please follow the instructions from $link\" -ExitCode:$exitCode\n                    }\n                }\n                catch {\n                    ## not ok to ignore, MSI will simply fail with generic error 1603.\n                    throw\n                }\n                finally {\n                    $ProgressPreference = $PreviousProgressPreference\n                    if (Test-Path -LiteralPath:$outFile -PathType:Leaf) {\n                        Trace-Message \"Removing $outFile\"\n                        Remove-Item -LiteralPath:$outFile -Force -ErrorAction:SilentlyContinue\n                    }\n                }\n            }\n            &lt;## The minimum number of KBs to be applied (in this order) to a RTM Server 2012R2 image to have a successful install:\n                KB2919442   prerequisite for KB2919355, https:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=42153\n                KB2919355   prerequisite for KB3068708, KB2999226 and KB3080149, https:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=42334\n                KB2999226   needed by WinDefend service, https:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=49063\n                KB3080149   telemetry dependency, https:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=48637\n                KB2959977   prerequisite for KB3045999,  https:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=42529\n                KB3068708   prerequisite for KB3045999,  https:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=47362\n                KB3045999   workaround for VSO#35611997, https:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=46547\n\n                To see the list of installed hotfixes run: 'Get-HotFix | Select-Object -ExpandProperty:HotFixID'\n            #&gt;\n            ## ucrt dependency (needed by WinDefend service) - see https:\/\/www.microsoft.com\/en-us\/download\/confirmation.aspx?id=49063\n            Install-KB -Uri:'https:\/\/download.microsoft.com\/download\/D\/1\/3\/D13E3150-3BB2-4B22-9D8A-47EE2D609FFF\/Windows8.1-KB2999226-x64.msu' -KB:KB2999226 -ScriptBlock: {\n                $ucrtbaseDll = \"$env:SystemRoot\\system32\\ucrtbase.dll\"\n                if (Test-Path -LiteralPath:$ucrtbaseDll -PathType:Leaf) {\n                    $verInfo = Get-FileVersion -File:$ucrtbaseDll\n                    Trace-Message \"$ucrtBaseDll version is $verInfo\"\n                    return $true\n                }\n                Trace-Warning \"$ucrtbaseDll not present, trying to install KB2999226\"\n                return $false\n            }\n            ## telemetry dependency (needed by Sense service) - see https:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=48637\n            Install-KB -Uri:'https:\/\/download.microsoft.com\/download\/A\/3\/E\/A3E82C15-7762-4104-B969-6A486C49DB8D\/Windows8.1-KB3080149-x64.msu' -KB:KB3080149 -ScriptBlock: {\n                $tdhDll = \"$env:SystemRoot\\system32\\Tdh.dll\"\n                if (Test-Path -LiteralPath:$tdhDll -PathType:Leaf) {\n                    $fileVersion = Get-FileVersion -File:$tdhDll\n                    $minFileVersion = New-Object -TypeName:System.Version -ArgumentList:6, 3, 9600, 17958\n                    if ($fileVersion -ge $minFileVersion) {\n                        Trace-Message \"$tdhDll version is $fileVersion\"\n                        return $true\n                    }\n                    Trace-Warning \"$tdhDll version is $fileVersion (minimum version is $minFileVersion), trying to install KB3080149\"\n                    return $false\n                }\n                Trace-Warning \"$tdhDll not present, trying to install KB3080149\"\n                return $false\n            }\n            ## needed by Sense - see VSO#35611997\n            Install-KB -Uri:'https:\/\/download.microsoft.com\/download\/3\/9\/E\/39EAFBBF-A801-4D79-B2B1-DAC4673AFB09\/Windows8.1-KB3045999-x64.msu' -KB:KB3045999 -ScriptBlock: {\n                $osVersion = Get-OSVersion\n                $minNtVersion = New-Object -TypeName:System.Version -ArgumentList:6, 3, 9600, 17736\n                if ($osVersion -ge $minNtVersion) {\n                    Trace-Message \"OsVersion is $osVersion\"\n                    return $true\n                }\n                Trace-Warning \"Current ntoskrnl.exe version is $osVersion (minimum required is $minNtVersion), trying to install KB3045999\"\n                return $false\n            }\n\n            $disableAntiSpywareGP = Get-RegistryKey -LiteralPath:'HKLM:\\Software\\Policies\\Microsoft\\Windows Defender' -Name:'DisableAntiSpyware'\n            if ($disableAntiSpywareGP) {\n                Exit-Install \"Remove(or change it to 0) HKLM:\\Software\\Policies\\Microsoft\\Windows Defender[DisableAntiSpyware] and try installing again.\" -ExitCode:$ERR_MDE_GROUP_POLICY_DISABLED\n            }\n        }\n        elseif ($osVersion.Major -eq 10 -and $osVersion.Minor -eq 0 -and $osVersion.Build -lt 18362) {\n            $defenderFeature = Get-WindowsOptionalFeature -Online -FeatureName:'Windows-Defender' -ErrorAction:Stop\n            if ($defenderFeature.State -ne 'Enabled') {\n                #see ICM#394684348\n                Remove-RegistryKey -LiteralPath:'HKLM:\\System\\CurrentControlSet\\Services\\EventLog\\Microsoft-Windows-Windows Defender\/Operational'\n\n                $defenderFeature = $defenderFeature | Enable-WindowsOptionalFeature -Online -NoRestart\n            }\n            if ($defenderFeature.RestartNeeded) {\n                Exit-Install \"Restart is required by 'Windows-Defender'\" -ExitCode:$ERR_PENDING_REBOOT\n            }\n\n            if ($null -eq $uninstallGUID) {\n                $codeSQUID = Get-CodeSQUID -ProductName:$displayName\n                if ($null -ne $codeSQUID) {\n                    ## Workaround for ICM#320556857\n                    ## Previous version of this product was not properly uninstalled triggering an upgrade scenario\n                    ## that fails because MSSecFlt.inf is missing.\n                    Trace-Warning \"Previously installed msi was not properly uninstalled(code:$codeSQUID)\"\n                    foreach ($subdir in 'Products', 'Features') {\n                        $item = \"HKCR:\\Installer\\$subdir\\$codeSQUID\"\n                        if (Test-Path -LiteralPath:$item -PathType:Container) {\n                            Rename-Item -LiteralPath:$item -NewName:\"$codeSQUID~\" -ErrorAction:Stop\n                            Trace-Warning \"$item renamed to $codeSQUID~\"\n                        }\n                        else {\n                            Trace-Warning \"$item not present\"\n                        }\n                    }\n                }\n            }\n            \n            $windefendStatus = (Get-Service -Name:'WinDefend' -ErrorAction:SilentlyContinue).Status\n            Trace-Message \"'WindDefend' service status is '$windefendStatus'\"\n            $imageName = (Get-RegistryKey -LiteralPath:'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\WinDefend' -Name:ImagePath) -replace '\"', ''            \n            if (0 -eq $imageName.Length) {\n                Trace-Warning \"'WinDefend' image path is null or empty. Still the '$($defenderFeature.FeatureName)' feature state is $($defenderFeature.State)\"\n                ## Workaround for ICM#423646508. In this scenario, \"Restart is required by 'Windows-Defender'\" error is ignored and this script is executed again without a restart.\n                ## Windows-Defender optional feature is seen as 'Enabled' (but no services\/files are present on the computer just yet) and previous versions of this script started\n                ## to report issues unrelated with the issue at hand.\n                Exit-Install \"Restart is required by 'Windows-Defender'\" -ExitCode:$ERR_PENDING_REBOOT\n            }\n\n            $currentVersion = Get-FileVersion -File:$imageName\n            if ($currentVersion -lt '4.18.23050.5') {\n                Trace-Warning \"Current platform version is $currentVersion, a platform update is needed.\"\n            }\n\n            if ($windefendStatus -ne 'Running') {\n                $disableAntiSpywareGP = Get-RegistryKey -LiteralPath:'HKLM:\\Software\\Policies\\Microsoft\\Windows Defender' -Name:'DisableAntiSpyware'\n                if ($disableAntiSpywareGP) {\n                    ## ICM#383475289 - WinDefend disabled via GP\n                    Exit-Install \"Remove(or change it to 0) HKLM:\\Software\\Policies\\Microsoft\\Windows Defender[DisableAntiSpyware] and try installing again.\" -ExitCode:$ERR_MDE_GROUP_POLICY_DISABLED\n                }\n\n                if ($currentVersion -lt '4.18.2102.4' -and $windefendStatus -eq 'Stopped') {\n                    ## ICM#391597247. Possible scenarios:\n                    ## - WinDefend was disabled via 'mpcmdrun.exe disableservice' sometimes between 2017 to 2021.\n                    ## - or the platform was reset to inbox version and after that disabled.\n                    $isDisabled = (Get-Service -Name:'WinDefend' -ErrorAction:SilentlyContinue).StartType -eq 'Disabled'\n                    if ($isDisabled) {\n                        #define SERVICE_AUTO_START 0x00000002\n                        #define SERVICE_DISABLED   0x00000004\n                        Set-ItemProperty -LiteralPath:'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\WinDefend' -Name:'Start' -Value:2 -ErrorAction:SilentlyContinue\n                        $isDisabled = (Get-Service -Name:'WinDefend' -ErrorAction:SilentlyContinue).StartType -eq 'Disabled'\n                        if ($isDisabled) {\n                            Exit-Install \"Cannot enable 'WinDefend' service\" -ExitCode:$ERR_UNEXPECTED_STATE\n                        }\n                        Trace-Message \"'WinDefend' service has been enabled.\"\n                    }\n                }\n                ## try to start it using 'mpcmdrun wdenable' (best effort)\n                $disableAntiSpyware = Get-RegistryKey -LiteralPath:'HKLM:\\Software\\Microsoft\\Windows Defender' -Name:'DisableAntiSpyware'\n                if ($null -ne $disableAntiSpyware -and 0 -ne $disableAntiSpyware) {\n                    Trace-Warning \"DisableAntiSpyware is set to $disableAntiSpyware (should be zero)\"\n                }\n                Invoke-MpCmdRun -ArgumentList:@('WDEnable')\n                $windefendStatus = (Get-Service -Name:'WinDefend' -ErrorAction:SilentlyContinue).Status\n            }\n\n            # Server 2016 - Windows Defender is shipped with OS, need to check if inbox version is updatable and latest.\n            # Expectations are that 'Windows Defender Features' are installed and up-to-date            \n            if ($windefendStatus -eq 'Running') {                \n                if ($currentVersion -lt '4.10.14393.2515') {\n                    Exit-Install 'Windows Defender platform update requirement not met. Please apply the latest cumulative update (LCU) for Windows first. Minimum required is https:\/\/support.microsoft.com\/en-us\/help\/4457127' -ExitCode:$ERR_INSUFFICIENT_REQUIREMENTS\n                }\n                $previousProgressPreference = $Global:ProgressPreference\n                $deleteUpdatePlatform = $false\n                try {\n                    $Global:ProgressPreference = 'SilentlyContinue'\n                    $msiVersion = (Get-MsiFilesInfo -MsiPath:$msi).'MPCLIENT.DLL'.Version\n                    $updatePlatformBaseName = if ($DevMode.IsPresent) { 'UpdatePlatformD.exe' } else { 'UpdatePlatform.exe' }\n                    if ($currentVersion -lt $msiVersion) {\n                        Trace-Message \"Current platform version is $currentVersion, msiVersion is $msiVersion\"\n                        $updatePlatform = Join-Path -Path:$PSScriptRoot $updatePlatformBaseName\n                        if (-not (Test-Path -LiteralPath:$updatePlatform -PathType:Leaf) -and -not $DevMode.IsPresent) {\n                            ## Download $updatePlatformBaseName from $uri *only if* the UpdatePlatform is not present.\n                            $uri = 'https:\/\/go.microsoft.com\/fwlink\/?linkid=870379&amp;arch=x64'\n                            Trace-Message \"$updatePlatformBaseName not present under $PSScriptRoot\"\n                            \n                            try {\n                                $latestVersion = ([xml]((Invoke-WebRequest -UseBasicParsing -Uri:\"$uri&amp;action=info\" @ExtraWebRequestOptions).Content)).versions.platform\n                            }\n                            catch {\n                                Trace-Warning \"Error: $_\"\n                                Exit-Install \"Cannot download the latest $updatePlatformBaseName. Please download it from $uri under $PSScriptRoot\\$updatePlatformBaseName\" -ExitCode:$ERR_NO_INTERNET_CONNECTIVITY\n                            }\n\n                            if ($latestVersion -lt $msiVersion) {\n                                Trace-Warning \"Changing msiVersion from $msiVersion to $latestVersion\"\n                                $msiVersion = $latestVersion\n                            }\n                            \n                            if ($latestVersion -gt $currentVersion) {\n                                Trace-Message \"Downloading latest $updatePlatformBaseName (version $latestVersion) from $uri\"\n                                $deleteUpdatePlatform = $true\n                                $updatePlatform = Join-Path -Path:$env:TEMP $updatePlatformBaseName\n                                Invoke-WebRequest -UseBasicParsing -Uri:$uri -OutFile:$updatePlatform @ExtraWebRequestOptions\n                            }\n                            else {\n                                Trace-Message \"Running platform is up-to-date\"\n                            }\n                        }\n                        \n                        if (Test-Path -LiteralPath:$updatePlatform -PathType:Leaf) {\n                            $updatePlatformVersion = Get-FileVersion -File:$updatePlatform\n                            if ($updatePlatformVersion -lt $msiVersion) {\n                                Exit-Install \"Minimum required version is $msiVersion. $updatePlatform version is $updatePlatformVersion\" -ExitCode:$ERR_INSUFFICIENT_REQUIREMENTS\n                            }\n\n                            $status = (Get-AuthenticodeSignature -FilePath:$updatePlatform).Status\n                            if ($status -ne 'Valid') {\n                                Exit-Install \"Unexpected authenticode signature status($status) for $updatePlatform\" -ExitCode:$ERR_CORRUPTED_FILE\n                            }\n                            ## make sure the right file was downloaded (or present in this directory)\n                            $fileInfo = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($updatePlatform)\n                            if ($updatePlatformBaseName -ne $fileInfo.InternalName) {\n                                Exit-Install \"Unexpected file: $updatePlatform, InternalName='$($fileInfo.InternalName)' (expecting '$updatePlatformBaseName')\" -ExitCode:$ERR_CORRUPTED_FILE\n                            }                       \n                            if ('Microsoft Malware Protection' -ne $fileInfo.ProductName) {\n                                Exit-Install \"Unexpected file: $updatePlatform, ProductName='$($fileInfo.ProductName)' (expecting 'Microsoft Malware Protection')\" -ExitCode:$ERR_CORRUPTED_FILE\n                            }\n\n                            Trace-Message (\"Running $updatePlatformBaseName (version {0})\" -f (Get-FileVersion -File:$updatePlatform))\n                            Measure-Process -FilePath:$updatePlatform\n                            $imageName = (Get-ItemPropertyValue -LiteralPath:'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\WinDefend' -Name:ImagePath) -replace '\"', ''\n                            $currentVersion = Get-FileVersion -File:$imageName\n                            if ($currentVersion -lt $latestVersion) {\n                                Exit-Install \"Current version is $currentVersion, expected to be at least $latestVersion\" -ExitCode:$ERR_INSUFFICIENT_REQUIREMENTS\n                            }\n                        }\n                        Trace-Message \"Current platform version is $currentVersion\"\n                    }\n                }\n                catch {\n                    throw\n                }\n                finally {\n                    $Global:ProgressPreference = $previousProgressPreference\n                    if ($deleteUpdatePlatform) {\n                        Remove-Item -LiteralPath:$updatePlatform -ErrorAction:SilentlyContinue\n                        if (Test-Path -LiteralPath:$updatePlatform -PathType:Leaf) {\n                            Trace-Warning \"Could not delete $updatePlatform\"\n                        }\n                        else {\n                            Trace-Message \"$updatePlatform deleted\"\n                        }\n                    }\n                }\n            }\n            else {\n                Exit-Install \"'WinDefend' service is not running.\" -ExitCode:$ERR_UNEXPECTED_STATE\n            }\n\n            $krnlACL = Get-Acl -Path:\"$env:SystemRoot\\System32\\ntoskrnl.exe\"\n            if ($krnlACL.Owner -ne 'NT SERVICE\\TrustedInstaller') {\n                ## See ICM#379926141 - unable to install md4ws.msi \"Unsupported OS version\"\n                $wrongOwner = $krnlACL.Owner\n                $ti = New-Object -TypeName:System.Security.Principal.NTAccount('NT SERVICE\\TrustedInstaller')\n                $krnlACL.SetOwner($ti)\n                Set-Acl -Path:\"$env:SystemRoot\\System32\\ntoskrnl.exe\" -AclObject:$krnlACL\n                Trace-Warning \"Current owner for $env:SystemRoot\\System32\\ntoskrnl.exe changed from '$wrongOwner' to '$($krnlACL.Owner)'\"\n            }\n        }\n        else {\n            Exit-Install \"Unsupported OS version: $osVersion\" -ExitCode:$ERR_UNSUPPORTED_DISTRO\n        }\n    }\n    \n    [hashtable] $etlParams = @{}\n    $onboardedSense = Get-RegistryKey -LiteralPath:'HKLM:SYSTEM\\CurrentControlSet\\Services\\Sense' -Name:'Start'\n    if ($OffboardingScript.Length -gt 0 -and ($action -eq 'uninstall' -or $null -ne $uninstallGUID)) {\n        if (2 -ne $onboardedSense) {\n            Exit-Install -Message:\"Sense Service is not onboarded, nothing to offboard.\" -ExitCode:$ERR_NOT_ONBOARDED\n        }\n        Trace-Message \"Invoking offboarding script $OffboardingScript\"\n        $scriptPath = if ($OffboardingScript.Contains(' ') -and -not $OffboardingScript.StartsWith('\"')) {\n            '\"{0}\"' -f $OffboardingScript\n        }\n        else {\n            $OffboardingScript\n        }\n        ## Sense service is delay starting and for offboarding to work without false positives Sense has to run. \n        $senseService = Get-Service -Name:Sense\n        if ($senseService.Status -ne 'Running') {\n            $senseService = Start-Service -Name:Sense -ErrorAction:SilentlyContinue\n        }\n        if ($senseService) {\n            Trace-Message \"Sense service status is '$($senseService.Status)'\"             \n        }\n\n        if ($etl) {\n            ## Offboard might fail due to WinDefend changes.\n            $etlParams = Start-TraceSession\n        }\n    \n        $exitCode = Measure-Process -FilePath:$((Get-Command 'cmd.exe').Path) -ArgumentList:@('\/c', $scriptPath) -PassThru\n        if (0 -eq $exitCode) {\n            Trace-Message \"Offboarding script $OffboardingScript reported success.\"\n            $onboardedSense = Get-RegistryKey -LiteralPath:'HKLM:SYSTEM\\CurrentControlSet\\Services\\Sense' -Name:'Start'\n            $endWait = (Get-Date) + 30 * [timespan]::TicksPerSecond\n            $traceWarning = $true\n            while (2 -eq $onboardedSense -and (Get-Date) -lt $endWait) {\n                if ($traceWarning) {\n                    $traceWarning = $false\n                    Trace-Warning \"HKLM:SYSTEM\\CurrentControlSet\\Services\\Sense[Start] is still 2. Waiting for it to change...\"\n                }\n                Start-Sleep -Milliseconds:100\n                $onboardedSense = Get-RegistryKey -LiteralPath:'HKLM:SYSTEM\\CurrentControlSet\\Services\\Sense' -Name:'Start'\n            }\n            if (2 -eq $onboardedSense) {\n                Exit-Install \"`'HKLM:SYSTEM\\CurrentControlSet\\Services\\Sense[Start]`' is still 2(onboarded) so offboarding failed\" -ExitCode:$ERR_OFFBOARDING_FAILED\n            }\n        }\n        else {\n            Exit-Install \"Offboarding script returned $exitCode.\" -ExitCode:$exitCode\n        }       \n    }\n\n    if ($action -eq 'uninstall') {\n        [bool] $isTamperProtected = (Get-MpComputerStatus -ErrorAction:SilentlyContinue).IsTamperProtected\n        if ($isTamperProtected) {\n            # This is already encoded in the product, added here for clarity.\n            Exit-Install \"Tamper protection is still enabled. Please disable it (or boot in 'Safe Mode') before uninstalling the product.\" -ExitCode:$ERR_TAMPER_PROTECTED\n        }\n\n        &amp; logman.exe query \"SenseIRTraceLogger\" -ets *&gt;$null\n        if (0 -eq $LASTEXITCODE) {\n            Trace-Warning \"SenseIRTraceLogger still present, removing it!\"\n            &amp; logman.exe stop -n \"SenseIRTraceLogger\" -ets *&gt;$null\n            if (0 -ne $LASTEXITCODE) {\n                Trace-Warning \"SenseIRTraceLogger could not be removed, exitCode=$LASTEXITCODE\"\n            }\n        }\n        \n        try {\n            # MsSense executes various Powershell scripts and these ones start executables that are not tracked anymore by the MsSense.exe or SenseIr.exe\n            # This is mitigated in the latest package but for previously installed packages we have to implement this hack to have a successful uninstall.\n            $procs = Get-Process -ErrorAction:SilentlyContinue\n            foreach ($proc in $procs) {\n                foreach ($m in $proc.Modules.FileName) {\n                    if ($m.StartsWith(\"$env:ProgramFiles\\Windows Defender Advanced Threat Protection\\\") -or\n                        $m.StartsWith(\"$env:ProgramData\\Microsoft\\Windows Defender Advanced Threat Protection\\\")) {\n                        Trace-Warning \"Terminating outstanding process $($proc.Name)(pid:$($proc.Id))\"\n                        Stop-Process -InputObject:$proc -Force -ErrorAction:Stop\n                        break\n                    }\n                }\n            }\n        }\n        catch {\n            Trace-Warning \"Error: $_\"\n            Exit-Install \"Offboarding left processes that could not be stopped\" -ExitCode:$ERR_OFFBOARDING_FAILED\n        }\n\n        ## Once in a long while (after an UpdateSenseClient.exe update) MsSecFlt cannot be unloaded anymore.\n        ## a kernel dump is needed to investigate this issue so this block stays here until we are lucky.\n        $msSecFlt = Get-Service -Name:'MsSecFlt' -ErrorAction:SilentlyContinue\n        if ($null -ne $msSecFlt -and $msSecFlt.Status -eq 'Running' -and -not $msSecFlt.CanStop) {\n            Trace-Warning \"Service '$($msSecFlt.Name)' cannot be stopped, reboot is required\"\n            Exit-Install \"Please restart this machine to complete '$($msSecFlt.Name)' service removal\" -ExitCode:$ERR_PENDING_REBOOT\n        }\n\n        # dealing with current powershell session that error out after this script finishes.\n        foreach ($name in 'ConfigDefender', 'Defender') {\n            $defender = Get-Module $name -ErrorAction:SilentlyContinue\n            if ($defender) {\n                Remove-Module $defender\n                Trace-Message 'Defender module unloaded.'\n                break\n            }\n        }\n\n        if ($osVersion.Major -eq 6 -and $osVersion.Minor -eq 3) {\n            if (Test-CurrentUserIsInRole 'S-1-5-18') {\n                if ($null -ne $uninstallGUID) {\n                    $displayVersion = Get-RegistryKey -LiteralPath:\"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${uninstallGUID}\" -Name:'DisplayVersion'\n                    if ($displayVersion -contains '4.18.' -and $displayVersion -lt '4.18.60326') {\n                        # See ICM#337407672 - This will be (or has been) fixed with build 4.18.2301.126 such that newer md4ws.msi could be uninstalled from system account. \n                        # Older msis have to be uninstalled from a normal Administrator account\n                        Exit-Install \"Uninstallation of version $displayVersion is not supported from System account. Try uninstalling from a regular Administrator account\" -ErrorAction:$ERR_UNSUPPORTED_VERSION\n                    }\n                    else {\n                        Trace-Warning \"Running uninstall from System account - UninstallGUID is $uninstallGUID\"\n                    }\n                }\n                else {\n                    Trace-Warning \"Running uninstall from System account\"\n                }\n            }\n\n            $needWmiPrvSEMitigation = if ($null -ne $uninstallGUID) {\n                $displayVersion = Get-RegistryKey -LiteralPath:\"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${uninstallGUID}\" -Name:'DisplayVersion'\n                ## newer versions handle this via custom action inside the MSI\n                $displayVersion -lt '4.18.60321'\n            }\n            else {\n                $true\n            }\n            \n            if ($needWmiPrvSEMitigation) {\n                # dealing with WmiPrvSE.exe keeping ProtectionManagement.dll in use (needed only on Server 2012 R2)\n                Get-Process -Name:'WmiPrvSE' -ErrorAction:SilentlyContinue | ForEach-Object {\n                    if ($_.MainModule.FileName -ne \"$env:SystemRoot\\system32\\wbem\\wmiprvse.exe\") {\n                        return\n                    }\n                    [string] $loadedModule = ''                    \n                    foreach ($m in $_.Modules.FileName) {\n                        if ($m.StartsWith(\"$env:ProgramFiles\\Windows Defender\\\") -or \n                            $m.StartsWith(\"$env:ProgramData\\Microsoft\\Windows Defender\\Platform\\\")) {\n                            $loadedModule = $m\n                            break\n                        }\n                    }\n                    if ($loadedModule.Length -gt 0) {\n                        Trace-Warning \"Terminating $($proc.Name)(pid:$($proc.Id)) because has '$loadedModule' in use\"\n                        Stop-Process $_.Id -Force -ErrorAction:Stop\n                    }\n                }\n            }\n        }\n    } \n    \n    if (2 -eq $onboardedSense) {\n        # all MSI operations (installing, uninstalling, upgrading) should be performed while Sense is offboarded.\n        Exit-Install -Message:\"Sense Service is onboarded, offboard before reinstalling(or use -OffboardingScript with this script)\" -ExitCode:$ERR_NOT_OFFBOARDED\n    }\n\n    $argumentList = if ($action -eq 'install') {\n        if ($msi.Contains(' ')) { @('\/i', \"`\"$msi`\"\") } else { @('\/i', $msi) }\n    }\n    else {\n        if ($null -eq $uninstallGUID) {\n            Exit-Install \"'$displayName' already uninstalled.\" -ExitCode:$ERR_MDE_NOT_INSTALLED\n        }\n        @('\/x', $uninstallGUID)\n    }\n\n    if ($log) {\n        $argumentList += '\/lvx*+'\n        $argumentList += if ($tempMsiLog.Contains(' ')) { \"`\"$tempMsiLog`\"\" } else { $tempMsiLog }\n    }\n\n    if (-not $UI.IsPresent) {\n        $argumentList += '\/quiet'\n    }\n\n    if ($Passive.IsPresent) {\n        Trace-Message \"Will force passive mode.\"\n        $argumentList += 'FORCEPASSIVEMODE=1'\n    }\n    \n    if ($etl -and 0 -eq $etlParams.Count) {\n        ## start ETW session if not already.\n        $etlParams = Start-TraceSession\n    }\n\n    $exitCode = Measure-Process -FilePath:$((Get-Command 'msiexec.exe').Path) -ArgumentList:$argumentList -PassThru\n    if (0 -eq $exitCode) {\n        Trace-Message \"$action successful.\"\n    }\n    else {\n        Exit-Install \"$action exitcode: $exitCode\" -ExitCode:$exitCode\n    }\n    \n    if ($action -eq 'install') {\n        if ($null -ne $codeSQUID) {\n            ## install succeeded, no need to keep around these 2 registry keys.\n            foreach ($subdir in 'Products', 'Features') {\n                $itemPath = \"HKCR:\\Installer\\$subdir\\$codeSQUID~\"\n                if (Test-Path -LiteralPath:$itemPath -PathType:Container) {\n                    try {\n                        Remove-Item -LiteralPath:$itemPath -Recurse -ErrorAction:Stop\n                        Trace-Message \"$itemPath recusively removed\"\n                    }\n                    catch {\n                        Trace-Warning \"Failed to remove $itemPath\"\n                    }\n                }\n            }\n        }\n\n        if ($OnboardingScript.Length) {\n            Trace-Message \"Invoking onboarding script $OnboardingScript\"\n            $scriptPath = if ($OnboardingScript.Contains(' ') -and -not $OnboardingScript.StartsWith('\"')) {\n                '\"{0}\"' -f $OnboardingScript\n            }\n            else {\n                $OnboardingScript\n            }\n            $argumentList = @('\/c', $scriptPath)\n            \n            $exitCode = Measure-Process -FilePath:$((Get-Command 'cmd.exe').Path) -ArgumentList:$argumentList -PassThru\n            if (0 -eq $exitCode) {\n                Trace-Message \"Onboarding successful.\"\n            }\n            else {\n                Trace-Warning \"Onboarding script returned $exitCode\"\n            }\n        }\n    }\n}\ncatch {\n    throw\n}\nfinally {\n    if ($msiStream.CanRead) {\n        Trace-Message (\"Closing handle {0}\" -f $msiStream.SafeFileHandle.DangerousGetHandle())\n        $msiStream.Close()\n    }\n    if ($etlParams.ContainsKey('ArgumentList')) {\n        Invoke-Command @etlparams -ScriptBlock: {\n            param($ScriptRoot, $logBase, $wdprov, $tempFile, $etlLog, $wppTracingLevel, $reportingPath)\n            &amp; logman.exe stop -n $logBase -ets *&gt;$null\n            if (0 -eq $LASTEXITCODE) {\n                Trace-Message \"Tracing session '$logBase' stopped.\"\n            }\n            else {\n                Trace-Warning \"logman.exe stop -n $logBase -ets returned $LASTEXITCODE\"\n            }\n\n            try {                \n                $jobParams = @{\n                    Name               = \"Cleanup $wppTracingLevel\"\n                    ScriptBlock        = { \n                        param($reportingPath, $wppTracingLevel)\n                        Remove-ItemProperty -LiteralPath:$reportingPath -Name:$wppTracingLevel -ErrorAction:SilentlyContinue \n                    }\n                    ArgumentList       = @($reportingPath, $wppTracingLevel)\n                    ScheduledJobOption = New-ScheduledJobOption -RunElevated\n                }\n                $scheduledJob = Register-ScheduledJob @jobParams -ErrorAction:Stop\n                $taskParams = @{\n                    TaskName  = $scheduledJob.Name\n                    Action    = New-ScheduledTaskAction -Execute $scheduledJob.PSExecutionPath -Argument:$scheduledJob.PSExecutionArgs\n                    Principal = New-ScheduledTaskPrincipal -UserId:'NT AUTHORITY\\SYSTEM' -LogonType:ServiceAccount -RunLevel:Highest\n                }\n                $scheduledTask = Register-ScheduledTask @taskParams -ErrorAction:Stop\n                Start-ScheduledTask -InputObject:$scheduledTask -ErrorAction:Stop -AsJob | Wait-Job | Remove-Job -Force -Confirm:$false\n                $SCHED_S_TASK_RUNNING = 0x41301\n                do {\n                    Start-Sleep -Milliseconds:10\n                    $LastTaskResult = (Get-ScheduledTaskInfo -InputObject:$scheduledTask).LastTaskResult\n                } while ($LastTaskResult -eq $SCHED_S_TASK_RUNNING)\n                $wpp = Get-RegistryKey -LiteralPath:$reportingPath -Name:$wppTracingLevel\n                if ($null -eq $wpp) {\n                    Trace-Message \"$reportingPath[$wppTracingLevel] removed\"\n                }\n            }\n            catch {\n                Trace-Warning \"Error: $_\"\n            }\n            finally {\n                if ($scheduledJob) {\n                    Unregister-ScheduledJob -InputObject $scheduledJob -Force\n                }\n                if ($scheduledTask) {\n                    Unregister-ScheduledTask -InputObject $scheduledTask -Confirm:$false\n                }\n            }\n\n            Move-Item -LiteralPath:$tempFile -Destination:$etlLog -ErrorAction:Continue\n            Trace-Message \"$action.etl file: '$etlLog'.\"    \n        }\n    }\n    else {\n        Trace-Message \"No $action.etl file generated.\"\n    }\n\n    if ($log -and (Test-Path -LiteralPath:$tempMsiLog -PathType:Leaf)) {\n        Move-Item -LiteralPath:$tempMsiLog -Destination:$msiLog -ErrorAction:Continue\n        Trace-Message \"Msi $action.log: '$msiLog'\"\n    }\n    else {\n        Trace-Message \"No $action.log file generated.\"\n    }\n    if ($null -ne $Script:InstallLog) {\n        Trace-Message \"$($PSCmdLet.MyInvocation.MyCommand.Name) traces: '$InstallLogPath'\"\n        $Script:InstallLog.Close()\n        $Script:InstallLog = $null\n    }\n}\n#Copyright (C) Microsoft Corporation. All rights reserved.\n\n# SIG # Begin signature block\n# MIImAgYJKoZIhvcNAQcCoIIl8zCCJe8CAQExDzANBglghkgBZQMEAgEFADB5Bgor\n# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG\n# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAFjr2nNTaokDaK\n# joR4niyDCj+U4v+UCDIh7RRZ5dItvqCCC1MwggTgMIIDyKADAgECAhMzAAAK7CQL\n# sju2bxocAAAAAArsMA0GCSqGSIb3DQEBCwUAMHkxCzAJBgNVBAYTAlVTMRMwEQYD\n# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy\n# b3NvZnQgQ29ycG9yYXRpb24xIzAhBgNVBAMTGk1pY3Jvc29mdCBXaW5kb3dzIFBD\n# QSAyMDEwMB4XDTIzMTAxOTE5MTgwM1oXDTI0MTAxNjE5MTgwM1owcDELMAkGA1UE\n# BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc\n# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEaMBgGA1UEAxMRTWljcm9zb2Z0\n# IFdpbmRvd3MwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDxlYs7SirE\n# 2DMWmJDHmyPDmkzh+fLl2bNdYJFYVIxEDXmuYo7qVT\/TlzRyHZNjfnCpNIN5BGy+\n# tL1DHfbYMyeZ64rRBk5ZDyfxpC0PjuOKeo8l1Yp0DYH8o\/tovvyg\/7t7RBqawaFi\n# 8mo9wrD5ISkTwSSMv2itkTg00L+gE8awFU17AUmplCQ9mZ91C\/9wLp9wH9bIBGm5\n# LnsMVzGxaxLbcqzuyi0CUj0ANTuQNZUFNTvLWj\/k3W3j7iiNZRDaniVqF2i7UEpU\n# Twl0A2\/ET31\/zrvHBzhJKaUtC31IicLI8HqTuUA96FAxGfczxleoZI6jXS2sWSYI\n# wU6YnckWSSAhAgMBAAGjggFoMIIBZDAfBgNVHSUEGDAWBgorBgEEAYI3CgMGBggr\n# BgEFBQcDAzAdBgNVHQ4EFgQUK97sk9qa9IVpYVlzmmULjVzY6akwRQYDVR0RBD4w\n# PKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEWMBQGA1UEBRMN\n# MjMwMDI4KzUwMTcwMjAfBgNVHSMEGDAWgBTRT6mKBwjO9CQYmOUA\/\/PWeR03vDBT\n# BgNVHR8ETDBKMEigRqBEhkJodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny\n# bC9wcm9kdWN0cy9NaWNXaW5QQ0FfMjAxMC0wNy0wNi5jcmwwVwYIKwYBBQUHAQEE\n# SzBJMEcGCCsGAQUFBzAChjtodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2Nl\n# cnRzL01pY1dpblBDQV8yMDEwLTA3LTA2LmNydDAMBgNVHRMBAf8EAjAAMA0GCSqG\n# SIb3DQEBCwUAA4IBAQArGdljm580qkATgRqYVsgvfdFUkL\/7TpOb8yh1h5vk2SEL\n# El5Bfz46bs3+ywayV\/mXd8Y43M3yku5Dp7dMwRXkze6j4LJLpLQ4CMPN4fvtlPkb\n# w+fQmXkHjogsb4bcJo\/aUKfLy4hGUbw+uqKBLx0RRIEj6Vj2m5W7lB+rdBl8hhtr\n# v5F4HYoy9lvXQhGGDwSsph+0uaZvCXSP7DOM3wOaYUQSNX6hYF5EHZsPrd334YGd\n# dTWIPRHrOWqg9FplGJumgZLgdlwY+WNZbXGCZwEQN3P88LTgrH\/gmlSD0fHbZDyM\n# YZ77M6PFlz4eXvC6I7J3VemS8OoU4DzYgxSahDXFMIIGazCCBFOgAwIBAgIKYQxq\n# GQAAAAAABDANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT\n# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m\n# dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh\n# dGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzA2MjA0MDIzWhcNMjUwNzA2MjA1MDIz\n# WjB5MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH\n# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSMwIQYDVQQD\n# ExpNaWNyb3NvZnQgV2luZG93cyBQQ0EgMjAxMDCCASIwDQYJKoZIhvcNAQEBBQAD\n# ggEPADCCAQoCggEBAMB5uzqx8A+EuK1kKnUWc9C7B\/Y+DZ0U5LGfwciUsDh8H9Az\n# VfW6I2b1LihIU8cWg7r1Uax+rOAmfw90\/FmV3MnGovdScFosHZSrGb+vlX2vZqFv\n# m2JubUu8LzVs3qRqY1pf+\/MNTWHMCn4x62wK0E2XD\/1\/OEbmisdzaXZVaZZM5Njw\n# NOu6sR\/OKX7ET50TFasTG3JYYlZsioGjZHeYRmUpnYMUpUwIoIPXIx\/zX99vLM\/a\n# FtgOcgQo2Gs++BOxfKIXeU9+3DrknXAna7\/b\/B7HB9jAvguTHijgc23SVOkoTL9r\n# XZ\/\/XTMSN5UlYTRqQst8nTq7iFnho0JtOlBbSNECAwEAAaOCAeMwggHfMBAGCSsG\n# AQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTRT6mKBwjO9CQYmOUA\/\/PWeR03vDAZBgkr\n# BgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH\/BAUw\n# AwEB\/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBN\n# MEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0\n# cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoG\n# CCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01p\n# Y1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBnQYDVR0gBIGVMIGSMIGPBgkrBgEE\n# AYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9Q\n# S0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcA\n# YQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZI\n# hvcNAQELBQADggIBAC5Bpoa1Bm\/wgIX6O8oX6cn65DnClHDDZJTD2FamkI7+5Jr0\n# bfVvjlONWqjzrttGbL5\/HVRWGzwdccRRFVR+v+6llUIz\/Q2QJCTj+dyWyvy4rL\/0\n# wjlWuLvtc7MX3X6GUCOLViTKu6YdmocvJ4XnobYKnA0bjPMAYkG6SHSHgv1QyfSH\n# KcMDqivfGil56BIkmobt0C7TQIH1B18zBlRdQLX3sWL9TUj3bkFHUhy7G8JXOqiZ\n# VpPUxt4mqGB1hrvsYqbwHQRF3z6nhNFbRCNjJTZ3b65b3CLVFCNqQX\/QQqbb7yV7\n# BOPSljdiBq\/4Gw+Oszmau4n1NQblpFvDjJ43X1PRozf9pE\/oGw5rduS4j7DC6v11\n# 9yxBt5yj4R4F\/peSy39ZA22oTo1OgBfU1XL2VuRIn6MjugagwI7RiE+TIPJwX9hr\n# cqMgSfx3DF3Fx+ECDzhCEA7bAq6aNx1QgCkepKfZxpolVf1Ayq1kEOgx+RJUeRry\n# DtjWqx4z\/gLnJm1hSY\/xJcKLdJnf+ZMakBzu3ZQzDkJQ239Q+J9iguymghZ8Zrzs\n# mbDBWF2osJphFJHRmS9J5D6Bmdbm78rj\/T7u7AmGAwcNGw186\/RayZXPhxIKXezF\n# ApLNBZlyyn3xKhAYOOQxoyi05kzFUqOcasd9wHEJBA1w3gI\/h+5WoezrtUyFMYIa\n# BTCCGgECAQEwgZAweTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x\n# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv\n# bjEjMCEGA1UEAxMaTWljcm9zb2Z0IFdpbmRvd3MgUENBIDIwMTACEzMAAArsJAuy\n# O7ZvGhwAAAAACuwwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisG\n# AQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcN\n# AQkEMSIEIFCGAnf18xiZFgzZEHR7X0NKQYjZ3V0q3LIYEkQJ2VMYMEIGCisGAQQB\n# gjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1p\n# Y3Jvc29mdC5jb20wDQYJKoZIhvcNAQEBBQAEggEANtZIp7cEkAGCVgU65wL6BFui\n# 16y194nk6Vh3pL6m9P9qyWrtidW4ZF4xL\/z6hoPHfMEMLzI9TDMGWSIUtKCQoU4H\n# B8a9r6BkenTf6sU5YXWY9ELXrySeya9VwpEBizAIEGdusQg7S+xSnv1f6tU956OC\n# ijmbDVYSVvNQ7siWEyifefwg9YmjFhMHMTIJMAxkNY4tRcvVx4hT1oARjuQtmQFY\n# pl60OoUFEvWYQabgwBNF4FaZitQRuJGd4gU7N+1tM3StQ9upqP0ytvdqWbVZGrHT\n# 4GW5wCY80PIc0pxPr84SHOZ8n1nNcLGiTIoOrXGQBYXBV1RftRlBr78W94H8a6GC\n# F5QwgheQBgorBgEEAYI3AwMBMYIXgDCCF3wGCSqGSIb3DQEHAqCCF20wghdpAgED\n# MQ8wDQYJYIZIAWUDBAIBBQAwggFSBgsqhkiG9w0BCRABBKCCAUEEggE9MIIBOQIB\n# AQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQCAQUABCDEvC4hd6cwKfs335Ih1pQ6\n# 4WjW8\/XpfOKz6dV\/oCFyWQIGZVbIJ3dNGBMyMDIzMTIwNTEwNDk1Ny4wMDlaMASA\n# AgH0oIHRpIHOMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ\n# MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u\n# MSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQL\n# Ex5uU2hpZWxkIFRTUyBFU046QTkzNS0wM0UwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jv\n# c29mdCBUaW1lLVN0YW1wIFNlcnZpY2WgghHqMIIHIDCCBQigAwIBAgITMwAAAdGy\n# W0AobC7SRQABAAAB0TANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEG\n# A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj\n# cm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFt\n# cCBQQ0EgMjAxMDAeFw0yMzA1MjUxOTEyMThaFw0yNDAyMDExOTEyMThaMIHLMQsw\n# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u\n# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNy\n# b3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBF\n# U046QTkzNS0wM0UwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1w\n# IFNlcnZpY2UwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCZTNo0OeGz\n# 2XFd2gLg5nTlBm8XOpuwJIiXsMU61rwq1ZKDpa443RrSG\/pH8Gz6XNnFQKGnCqNC\n# tmvoKULApwrT\/s7\/e1X0lNFKmj7U7X4p00S0uQbW6LwSn\/zWHaG2c54ZXsGY+BYf\n# hWDgbFpCTxRzTnRCG62bkWPp6ZHbZPg4Ht1CRCAMhhOGTR8wI4G7wwWZwdMc6UvU\n# Ulq0ql9AxAfzkYRpi2tRvDHMdmZ3vyXpqhFwvRG8cgCH\/TTCjW5q6aNbdqKL3BFD\n# PzUtuCNsPXL3\/E0dR2bDMqa0aNH+iIfhGC4\/vcwuteOMCPUIDVSqDCNfIaPDEwYc\n# i1fd9gu1zVw+HEhDZM7Ea3nxIUrzt+Rfp5ToMMj4QAmJ6Uadm+TPbDbo8kFIK70S\n# hmW8wn8fJk9ReQQEpTtIN43eRv9QmXy3Ued80osOBE+WkdMvSCFh+qgCsKdzQxQJ\n# G62cTeoU2eqNhH3oppXmyfVUwbsefQzMPtbinCZd0FUlmlM\/dH+4OniqQyaHvrtY\n# y3wqIafY3zeFITlVAoP9q9vF4W7KHR\/uF0mvTpAL5NaTDN1plQS0MdjMkgzZK5gt\n# wqOe\/3rTlqBzxwa7YYp3urP5yWkTzISGnhNWIZOxOyQIOxZfbiIbAHbm3M8hj73K\n# QWcCR5JavgkwUmncFHESaQf4Drqs+\/1L1QIDAQABo4IBSTCCAUUwHQYDVR0OBBYE\n# FAuO8UzF7DcH0mmsF4XQxxHQvS2jMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg\/Tl0mWn\n# G1M1GelyMF8GA1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNv\n# bS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEw\n# KDEpLmNybDBsBggrBgEFBQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cu\n# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFt\n# cCUyMFBDQSUyMDIwMTAoMSkuY3J0MAwGA1UdEwEB\/wQCMAAwFgYDVR0lAQH\/BAww\n# CgYIKwYBBQUHAwgwDgYDVR0PAQH\/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQCb\n# u9rTAHV24mY0qoG5eEnImz5akGXTviBwKp2Y51s26w8oDrWor+m00R4\/3BcDmYlU\n# K8Nrx\/auYFYidZddcUjw42QxSStmv\/qWnCQi\/2OnH32KVHQ+kMOZPABQTG1XkcnY\n# PUOOEEor6f\/3Js1uj4wjHzE4V4aumYXBAsr4L5KR8vKes5tFxhMkWND\/O7W\/RaHY\n# wJMjMkxVosBok7V21sJAlxScEXxfJa+\/qkqUr7CZgw3R4jCHRkPqQhMWibXPMYar\n# \/iF0ZuLB9O89DMJNhjK9BSf6iqgZoMuzIVt+EBoTzpv\/9p4wQ6xoBCs29mkj\/EIW\n# Fdc+5a30kuCQOSEOj07+WI29A4k6QIRB5w+eMmZ0Jec0sSyeQB5KjxE51iYMhtlM\n# rUKcr06nBqCsSKPYsSAITAzgssJD+Z\/cTS7Cu35fJrWhM9NYX24uAxYLAW0ipNtW\n# ptIeV6akuZEeEV6BNtM3VTk+mAlV5\/eC\/0Y17aVSjK5\/gyDoLNmrgVwv5TAaBmq\/\n# wgRRFHmW9UJ3zv8Lmk6mIoAyTpqBbuUjMLyrtajuSsA\/m2DnKMO0Qiz1v+FSVbqM\n# 38J\/PTlhCTUbFOx0kLT7Y\/7+ZyrilVCzyAYfFIinDIjWlM85tDeU8ZfJCjFKwq3D\n# sRxV4JY18xww8TTmod3lkr9NqGQ54LmyPVc+5ibNrjCCB3EwggVZoAMCAQICEzMA\n# AAAVxedrngKbSZkAAAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVT\n# MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK\n# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290\n# IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMw\n# MDkzMDE4MzIyNVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x\n# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv\n# bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIiMA0G\n# CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC0\/3u\n# nAcH0qlsTnXIyjVX9gF\/bErg4r25PhdgM\/9cT8dm95VTcVrifkpa\/rg2Z4VGIwy1\n# jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP2CZT\n# fDlhAnrEqv1yaa8dq6z2Nr41JmTamDu6GnszrYBbfowQHJ1S\/rboYiXcag\/PXfT+\n# jlPP1uyFVk3v3byNpOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361VI\/c\n# +gVVmG1oO5pGve2krnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+\n# cakXW2dg3viSkR4dPf0gz3N9QZpGdc3EXzTdEonW\/aUgfX782Z5F37ZyL9t9X4C6\n# 26p+Nuw2TPYrbqgSUei\/BQOj0XOmTTd0lBw0gg\/wEPK3Rxjtp+iZfD9M269ewvPV\n# 2HM9Q07BMzlMjgK8QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoS\n# CtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR\/bLUHMVr9lxS\n# UV0S2yW6r1AFemzFER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+eFnJp\n# xq57t7c+auIurQIDAQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkr\n# BgEEAYI3FQIEFgQUKqdS\/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0A\n# XmJdg\/Tl0mWnG1M1GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYI\n# KwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9S\n# ZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIE\n# DB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH\/BAUwAwEB\/zAfBgNV\n# HSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVo\n# dHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29D\n# ZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAC\n# hj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1\n# dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9\/Cqt4SwfZwEx\n# JFvhnnJL\/Klv6lwUtj5OR2R4sQaTlz0xM7U518JxNj\/aZGx80HU5bbsPMeTCj\/ts\n# 0aGUGCLu6WZnOlNN3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu2D9I\n# dQHZGN5tggz1bSNU5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC\/GbYS\n# EhFdPSfgQJY4rPf5KYnDvBewVIVCs\/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMu\n# LGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j\/aRAfbOxnT9\n# 9kxybxCrdTDFNLB62FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2z\n# AVdJVGTZc9d\/HltEAY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I6Ile\n# T53S0Ex2tVdUCbFpAUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6l\n# MVGEvL8CwYKiexcdFYmNcP7ntdAoGokLjzbaukz5m\/8K6TT4JDVnK+ANuOaMmdbh\n# IurwJ0I9JZTmdHRbatGePu1+oDEzfbzL6Xu\/OHBE0ZDxyKs6ijoIYn\/ZcGNTTY3u\n# gm2lBRDBcQZqELQdVTNYs6FwZvKhggNNMIICNQIBATCB+aGB0aSBzjCByzELMAkG\n# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx\n# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9z\n# b2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNO\n# OkE5MzUtMDNFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT\n# ZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQBHJY2Fv+GhLQtRDR2vIzBaSv\/7LKCBgzCB\n# gKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH\n# EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV\n# BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUA\n# AgUA6Rj\/wzAiGA8yMDIzMTIwNTAxNDc0N1oYDzIwMjMxMjA2MDE0NzQ3WjB0MDoG\n# CisGAQQBhFkKBAExLDAqMAoCBQDpGP\/DAgEAMAcCAQACAgI3MAcCAQACAhQ\/MAoC\n# BQDpGlFDAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEA\n# AgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQELBQADggEBAB4OIDT1ZqC1ZD2g\n# ezvM8gnGarq2OuCXwM9UVdPkBmwrfcxtqDTsFJJovg1KR7biOMVwhBKmu2Agwzbu\n# rQyrNoX+4xecVefNzrjG4mz8tT4GCJVv9Vqfx0+6YxZ4OdUFZ04gQb6ojbB5VSi6\n# 7ecW004Gkiat\/\/RyGi1YgqS9jrzGpxlk2uOZRpGIO1mChbq0VwlaML2vjFO\/lIJx\n# ybVL5PaQogylDFKwYfRA8ryIRflnDfpftNWTQo6kkOAmmq09tuNtc+G10GCoDwu2\n# 6IlGsqtXNGlnDdsn3yR0w+K0yrrBqhfKzWiIMt7CMYgfSSexO6scVdtYErXlS2aX\n# aR4eamsxggQNMIIECQIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz\n# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv\n# cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAx\n# MAITMwAAAdGyW0AobC7SRQABAAAB0TANBglghkgBZQMEAgEFAKCCAUowGgYJKoZI\n# hvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCDHY\/X+ezIGQggz\n# 9pojwQRjS68POUKdJovFX3mw\/ir8BzCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQw\n# gb0EIMy8YXkCALv57c5sRhrPTub1q4TwJ6oVA36k8IiI\/AcMMIGYMIGApH4wfDEL\n# MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v\n# bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWlj\n# cm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAHRsltAKGwu0kUAAQAAAdEw\n# IgQgHWwSZv5Ko32MHb3PP7h5Z7Gr6Y9ZZhsEAyVFaP8fyqIwDQYJKoZIhvcNAQEL\n# BQAEggIAiwcCYwstHCEEHsQKWdL36qcw50VJd\/+gBLvYbdV0Hs6QDlNLfbwEPK\/5\n# NcrwOHUuz3bE6Ofx4kEnpWOlHfIG9vA0GyDTK7+o5usEh4TEZrQy3rzo5T0Hq1Zf\n# beg6uU\/hXWenkwXKaICS\/PYHl6HJaaT4hNWNbAzLpfhk23ReQ4xxv5OKJCuDM9gP\n# MVKpmjMLWOCUYJTmC3a4PoZHV2gezrxACfLgD9ZDUfO6i2XQOdu7WsU60a0Ss9XS\n# 5nkI2MMkgm6cESF7FsSdbdhHBM3x\/lnSBye2g0HZ3uMTbmpY9V+H8+4IWDJVrMI2\n# rOc\/oB95K6QbUvNvQ7h9XXyHm\/8MB3EZ7WhQTEC1EynW5gU70lfGp9rmNQ7Omx4N\n# e3DUzC8RlEqr3i2NAFauVH1mhB9iZEr7csV6tbtPR7SMUzAqyyt55Cr67fipd0M1\n# mw6hwGrrflc4T2eeWXaa\/BpVwF6llCPyPLfONQx7y4CcHO2S9fMtp8+kS+t2surn\n# XxoK0P0JfqzKjX\/4m3l1H9yHbk\/dEPqi3YNrDNBfpbOoV9V3UHN2gFyVh9+\/vXYD\n# iVSLg7Xw50hlhzMrN9s1d\/kYQZ9IQt\/rHjcZ9RLtNIFKajoCN3Qr+HBnnBRlRZt+\n# TIQMATB0KSux4OK2pk8LfgHQKnPZten+laRVH1xKkTh\/7alQYjA=\n# SIG # End signature block<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Install Defender<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-7595","post","type-post","status-publish","format-standard","hentry","category-research"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts\/7595","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/comments?post=7595"}],"version-history":[{"count":2,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts\/7595\/revisions"}],"predecessor-version":[{"id":7600,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts\/7595\/revisions\/7600"}],"wp:attachment":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/media?parent=7595"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/categories?post=7595"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/tags?post=7595"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}