{"id":387242,"date":"2024-12-02T16:38:04","date_gmt":"2024-12-02T16:38:04","guid":{"rendered":"https:\/\/www.ninjaone.com\/?post_type=script_hub&#038;p=387242"},"modified":"2024-12-02T16:41:41","modified_gmt":"2024-12-02T16:41:41","slug":"comprobar-el-estado-del-antivirus","status":"publish","type":"script_hub","link":"https:\/\/www.ninjaone.com\/es\/script-hub\/comprobar-el-estado-del-antivirus\/","title":{"rendered":"C\u00f3mo comprobar el estado del antivirus en Windows usando PowerShell"},"content":{"rendered":"<p>Asegurarte de que tu <strong>antivirus<\/strong> est\u00e9 correctamente instalado, actualizado y funcionando activamente es fundamental para mantener un entorno inform\u00e1tico seguro. Los profesionales de TI y los <a href=\"https:\/\/www.ninjaone.com\/es\/que-es-un-msp\" target=\"_blank\" rel=\"noopener\">proveedores de servicios gestionados (MSP)<\/a> a menudo necesitan herramientas fiables para verificar el estado de las soluciones antivirus en varios sistemas. Este script PowerShell proporciona una soluci\u00f3n potente y automatizada para detectar, comprobar el estado del antivirus, y exportar los resultados a campos personalizados para su posterior an\u00e1lisis.<\/p>\n<h2>Contexto<\/h2>\n<p>En el panorama digital actual, la prevalencia de <a href=\"https:\/\/www.ninjaone.com\/blog\/common-cyber-attacks\/\" target=\"_blank\" rel=\"noopener\">las ciberamenazas<\/a> hace necesaria una s\u00f3lida protecci\u00f3n antivirus. Los departamentos de TI y los MSP deben supervisar y verificar constantemente el estado de las soluciones antivirus para asegurarse de que ofrecen la protecci\u00f3n adecuada. Este script aborda un reto com\u00fan: determinar de forma eficiente qu\u00e9 software antivirus est\u00e1 instalado en un sistema, su versi\u00f3n, la antig\u00fcedad de sus definiciones y si se est\u00e1 ejecutando actualmente. Al automatizar estas comprobaciones, el script para comprobar el estado del antivirus ahorra un tiempo valioso y <a href=\"https:\/\/www.ninjaone.com\/blog\/how-human-error-relates-to-cybersecurity-risks\/\" target=\"_blank\" rel=\"noopener\">reduce el riesgo de error humano<\/a>.<\/p>\n<h2>El script para comprobar el estado del antivirus<\/h2>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\">#Requires -Version 4.0\r\n\r\n&lt;#\r\n.SYNOPSIS\r\n    This script will attempt to detect the installed antivirus (currently supports 11) and get the age of its definitions, version, and whether or not the antivirus is currently running. It can export the results to one or more custom fields. This script is a best effort and should be treated as such; we do recommend verifying any results.\r\n.DESCRIPTION\r\n    This script will attempt to detect the installed antivirus (currently supports 11) and get the age of its definitions, version, and whether or not the antivirus is currently running. \r\n    It can export the results to one or more custom fields. \r\n    This script is a best effort and should be treated as such; we do recommend verifying any results.\r\n    \r\n    AV List: BitDefender,Carbon Black,Crowdstrike,Cylance,ESET,Huntress,MalwareBytes,MDE,SentinelOne,Sophos,Vipre,Webroot\r\n\r\n.EXAMPLE\r\n    (No Parameters)\r\n    Desktop Windows Detected, Switching to WMI Method....\r\n\r\n    [Alert] The AV definitions are out of date!\r\n\r\n    Name             Installed Definitions UpToDate Running Service  Version    \r\n    ----             --------- ----------- -------- ------- -------  -------    \r\n    Sentinel Agent   Yes       2023\/05\/10      True Yes     Active   21.7.1219  \r\n    Windows Defender Yes       2023\/03\/31     False No      Inactive 4.18.2302.7\r\n\r\nPARAMETER: -ExcludeAV \"BitDefender\"\r\n    A comma separated list of AVs to exclude.\r\n.EXAMPLE\r\n    -ExcludeAV \"BitDefender\"\r\n\r\n    Name        Installed Version   Definitions UpToDate CurrentlyRunning HasRunningService\r\n    ----        --------- -------   ----------- -------- ---------------- -----------------\r\n    SentinelOne Yes       21.7.1219 2023\/04\/27      True Yes              Yes\r\n\r\nPARAMETER: -ExclusionsFromCustomField \"ReplaceWithTextCustomField\"\r\n    The name of a text custom field that contains your desired ExcludeAV comma separated list.\r\n    ex. \"ExcludedAVs\" where you have entered in your desired ExcludeAV list in the \"ExcludedAVs\" custom field rather than in a parameter.\r\n.EXAMPLE\r\n    -ExclusionsFromCustomField \"ExcludeAVs\"\r\n\r\n    Name        Installed Version   Definitions UpToDate CurrentlyRunning HasRunningService\r\n    ----        --------- -------   ----------- -------- ---------------- -----------------\r\n    SentinelOne Yes       21.7.1219 2023\/04\/27      True Yes              Yes\r\n\r\nPARAMETER: -OutOfDate \"7\"\r\n    Script will consider the AV to be out of date if the definitions are older than x days.\r\n.EXAMPLE\r\n    -OutOfDate \"1\"\r\n\r\n    Desktop Windows Detected, Switching to WMI Method....\r\n\r\n    [Alert] The AV definitions are out of date!\r\n\r\n    Name             Installed Definitions UpToDate Running Service  Version    \r\n    ----             --------- ----------- -------- ------- -------  -------    \r\n    Sentinel Agent   Yes       2023\/05\/10     False Yes     Active   21.7.1219  \r\n    Windows Defender Yes       2023\/03\/31     False No      Inactive 4.18.2302.7\r\n\r\n\r\nPARAMETER: -ShowNotFound\r\n    Script will show AV's it checked for but didn't find.\r\n.EXAMPLE\r\n    -ShowNotFound\r\n\r\n    Name             Installed Definitions UpToDate Running Service  Version    \r\n    ----             --------- ----------- -------- ------- -------  -------    \r\n    BitDefender      No                       False No      Inactive     \r\n    CarbonBlack      No                       False No      Inactive \r\n    ...\r\n\r\nPARAMETER: -ExportAll \"ReplaceWithNameOfAMultiLineCustomField\"\r\n    The name of a multiline customfield you'd like to export the resulting table into.\r\n.EXAMPLE\r\n    -ExportAll \"ReplaceWithNameOfAMultiLineCustomField\"\r\n\r\n    Name        Installed Version   Definitions UpToDate CurrentlyRunning HasRunningService\r\n    ----        --------- -------   ----------- -------- ---------------- -----------------\r\n    SentinelOne Yes       21.7.1219 2023\/04\/27      True Yes              Yes\r\n\r\nPARAMETER: -ExportDef \"ReplaceWithNameOfAMultiLineCustomField\"\r\n    The name of a multiline customfield you'd like to export the definitions column into.\r\n\r\nPARAMETER: -ExportDefStatus \"ReplaceWithNameOfAMultiLineCustomField\"\r\n    The name of a multiline customfield you'd like to export the UpToDate column into.\r\n\r\nPARAMETER: -ExportName \"ReplaceWithNameOfAMultiLineCustomField\"\r\n    The name of a multiline customfield you'd like to export the Name column into.\r\n\r\nPARAMETER: -ExportStatus \"ReplaceWithNameOfAMultiLineCustomField\"\r\n    The name of a multiline customfield you'd like to export the Running column into.\r\n\r\nPARAMETER: -ExportVersion \"ReplaceWithNameOfAMultiLineCustomField\"\r\n    The name of a multiline customfield you'd like to export the Version column into.\r\n.EXAMPLE\r\n    ExportOptions: -ExportAll, -ExportDef, -ExportDefStatus (Whether or not definitions are up to date), \r\n    -ExportName, -ExportStatus (Whether or not its running), -ExportVersion\r\n\r\n    -ExportAll \"ReplaceWithNameOfAMultiLineCustomField\" -DateFormat \"yyyy\/MM\/dd\"\r\n\r\n    [Alert] The AV definitions are out of date!\r\n\r\n    Name   Installed Definitions UpToDate Running Service Version                  \r\n    ----   --------- ----------- -------- ------- ------- -------                  \r\n    MDE    Yes       2023\/03\/02     False Yes     Active  4.18.2303.8              \r\n    Sophos Yes       2023\/04\/26      True Yes     Active  {2022.4.3.1 Legacy,      \r\n                                                      2.4.274.0}               \r\n\r\n.OUTPUTS\r\n    None\r\n.NOTES\r\n    Minimum OS Architecture Supported: Windows 10, Server 2012 R2\r\n    Release Notes: Initial Release\r\nBy using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https:\/\/www.ninjaone.com\/terms-of-use.\r\n    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. \r\n    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. \r\n    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. \r\n    Warranty Disclaimer: The script is provided \u201cas is\u201d and \u201cas available\u201d, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. \r\n    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. \r\n    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. \r\n    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).\r\n#&gt;\r\n\r\n[CmdletBinding()]\r\nparam (\r\n    [Parameter()]\r\n    [String]$ExcludeAV,\r\n    [Parameter()]\r\n    [String]$ExclusionsFromCustomField,\r\n    [Parameter()]\r\n    [String]$ExportAll,\r\n    [Parameter()]\r\n    [String]$ExportDef,\r\n    [Parameter()]\r\n    [String]$ExportDefStatus,\r\n    [Parameter()]\r\n    [String]$ExportName,\r\n    [Parameter()]\r\n    [String]$ExportStatus,\r\n    [Parameter()]\r\n    [String]$ExportVersion,\r\n    [Parameter()]\r\n    [String]$OutOfDate = \"7\",\r\n    [Parameter()]\r\n    [Switch]$ShowNotFound = [System.Convert]::ToBoolean($env:showNotFound)\r\n)\r\nbegin {\r\n    Write-Host \"Supported AVs: BitDefender, Carbon Black, Crowdstrike, Cylance, ESET, Huntress, MalwareBytes, Windows Defender, SentinelOne, Sophos, Vipre and Webroot.\"\r\n\r\n    # Grabbing the script variables\r\n    if ($env:definitionsAgeLimitInDays -and $env:definitionsAgeLimitInDays -notlike \"null\") { $OutOfDate = $env:definitionsAgeLimitInDays }\r\n    if ($env:excludeAntivirusProduct -and $env:excludeAntivirusProduct -notlike \"null\") { $ExcludeAV = $env:excludeAntivirusProduct }\r\n    if ($env:retrieveExclusionFromCustomField -and $env:retrieveExclusionFromCustomField -notlike \"null\") { $ExclusionsFromCustomField = $env:retrieveExclusionFromCustomField }\r\n    if ($env:allResultsCustomFieldName -and $env:allResultsCustomFieldName -notlike \"null\") { $ExportAll = $env:allResultsCustomFieldName }\r\n    if ($env:definitionsDateCustomFieldName -and $env:definitionsDateCustomFieldName -notlike \"null\") { $ExportDef = $env:definitionsDateCustomFieldName }\r\n    if ($env:definitionStatusCustomFieldName -and $env:definitionStatusCustomFieldName -notlike \"null\" ) { $ExportDefStatus = $env:definitionStatusCustomFieldName }\r\n    if ($env:statusCustomFieldName -and $env:statusCustomFieldName -notlike \"null\") { $ExportStatus = $env:statusCustomFieldName }\r\n    if ($env:antivirusNameCustomFieldName -and $env:antivirusNameCustomFieldName -notlike \"null\") { $ExportName = $env:antivirusNameCustomFieldName }\r\n    if ($env:statusCustomFieldName -and $env:statusCustomFieldName -notlike \"null\") { $ExportStatus = $env:statusCustomFieldName }\r\n    if ($env:antivirusVersionCustomFieldName -and $env:antivirusVersionCustomFieldName -notlike \"null\") { $ExportVersion = $env:antivirusVersionCustomFieldName }\r\n\r\n    # This script should run with administrator or system permissions. \r\n    # Technically it'll work without these permissions, however some directories would be inaccessible which could lead to false negatives.\r\n    function Test-IsElevated {\r\n        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()\r\n        $p = New-Object System.Security.Principal.WindowsPrincipal($id)\r\n        $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)\r\n    }\r\n\r\n    if (!(Test-IsElevated)) {\r\n        Write-Host \"[Error] Access Denied. Please run with Administrator privileges.\"\r\n        exit 1\r\n    }\r\n\r\n    function Test-IsWorkstation {\r\n        $OS = if ($PSVersionTable.PSVersion.Major -ge 5) {\r\n            Get-CimInstance -Class Win32_OperatingSystem\r\n        }\r\n        else {\r\n            Get-WmiObject -Class Win32_OperatingSystem\r\n        }\r\n\r\n        if ($OS.ProductType -eq \"1\") {\r\n            return $True\r\n        }\r\n    }\r\n\r\n    # This will go through the uninstall registry keys and look for the AV. On occasion, we don't want all the information so we have switch options for those cases.\r\n    function Find-UninstallKey {\r\n        [CmdletBinding()]\r\n        param (\r\n            [Parameter(ValueFromPipeline)]\r\n            [String]$DisplayName,\r\n            [Parameter()]\r\n            [Switch]$Version,\r\n            [Parameter()]\r\n            [Switch]$UninstallString,\r\n            [Parameter()]\r\n            [Switch]$InstallPath\r\n        )\r\n        process {\r\n            $UninstallList = New-Object System.Collections.Generic.List[Object]\r\n\r\n            $Result = Get-ChildItem HKLM:\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\* | Get-ItemProperty | \r\n                Where-Object { $_.DisplayName -like \"*$DisplayName*\" }\r\n\r\n            if ($Result) { $UninstallList.Add($Result) }\r\n\r\n            $Result = Get-ChildItem HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\* | Get-ItemProperty | \r\n                Where-Object { $_.DisplayName -like \"*$DisplayName*\" }\r\n\r\n            if ($Result) { $UninstallList.Add($Result) }\r\n\r\n            # Programs don't always have an uninstall string listed here, so to account for that, I made this optional.\r\n            if ($UninstallString) {\r\n                $UninstallList | ForEach-Object { $_ | Select-Object -ExpandProperty UninstallString -ErrorAction SilentlyContinue }\r\n            }\r\n\r\n            if ($Version) {\r\n                $UninstallList | ForEach-Object { ($_ | Select-Object -ExpandProperty DisplayVersion -ErrorAction SilentlyContinue) -replace '[^\\u0020-\\u007E\\u00A0-\\u00FF]', '' }\r\n            }\r\n\r\n            if ($InstallPath) {\r\n                $UninstallList | ForEach-Object { $_ | Select-Object -ExpandProperty InstallLocation -ErrorAction SilentlyContinue }\r\n            }\r\n\r\n            if (!$Version -and !$UninstallString -and !$InstallPath) {\r\n                $UninstallList\r\n            }\r\n        }\r\n    }\r\n\r\n    # This will find the last write time for a particular file. I made it a function in case I wanted to do something similar as the Uninstall-Key function.\r\n    function Find-Definitions {\r\n        [CmdletBinding()]\r\n        param(\r\n            [Parameter(ValueFromPipeline)]\r\n            [String]$Path\r\n        )\r\n        process {\r\n            Get-Item $Path -ErrorAction SilentlyContinue | Sort-Object LastWriteTime | Select-Object LastWriteTime -Last 1 | Get-Date\r\n        }\r\n    }\r\n\r\n    # This will search the typical directories programs are installed in.\r\n    function Find-Executable {\r\n        [CmdletBinding()]\r\n        param(\r\n            [Parameter(ValueFromPipeline)]\r\n            [String]$Path,\r\n            [Parameter()]\r\n            [Switch]$Special\r\n        )\r\n        process {\r\n            if (!$Special) {\r\n                if (Test-Path \"$env:ProgramFiles\\$Path\") {\r\n                    \"$env:ProgramFiles\\$Path\"\r\n                }\r\n        \r\n                if (Test-Path \"${Env:ProgramFiles(x86)}\\$Path\") {\r\n                    \"${Env:ProgramFiles(x86)}\\$Path\"\r\n                }\r\n    \r\n                if (Test-Path \"$env:ProgramData\\$Path\") {\r\n                    \"$env:ProgramData\\$Path\"\r\n                }\r\n            }\r\n            else {\r\n                if (Test-Path $Path) {\r\n                    $Path\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    # This will check the running processes for our AV.\r\n    function Find-Process {\r\n        [CmdletBinding()]\r\n        param(\r\n            [Parameter(ValueFromPipeline)]\r\n            [String]$Name\r\n        )\r\n        process {\r\n            Get-Process | Where-Object { $_.ProcessName -like \"*$Name*\" } | Select-Object -ExpandProperty Name\r\n        }\r\n    }\r\n\r\n    # This was moved outside the function so I don't overload WMI.\r\n    $ServiceList = if ($PSVersionTable.PSVersion.Major -ge 5) {\r\n        Get-CimInstance win32_service\r\n    }\r\n    else {\r\n        Get-WmiObject win32_service\r\n    }\r\n    \r\n    # Looks for a service based on the executable.\r\n    function Find-Service {\r\n        [CmdletBinding()]\r\n        param(\r\n            [Parameter(ValueFromPipeline)]\r\n            [String]$Name\r\n        )\r\n        process {\r\n            # Get-Service will display an error everytime it has an issue reading a service. Ignoring them as they're not relevant.\r\n            $ServiceList | Where-Object { $_.State -notlike \"Disabled\" -and $_.State -notlike \"Stopped\" } | \r\n                Where-Object { $_.PathName -Like \"*$Name.exe*\" }\r\n        }\r\n    }\r\n\r\n    function Set-NinjaProperty {\r\n        [CmdletBinding()]\r\n        Param(\r\n            [Parameter(Mandatory = $True)]\r\n            [String]$Name,\r\n            [Parameter()]\r\n            [String]$Type,\r\n            [Parameter(Mandatory = $True, ValueFromPipeline = $True)]\r\n            $Value,\r\n            [Parameter()]\r\n            [String]$DocumentName\r\n        )\r\n    \r\n        $Characters = $Value | Measure-Object -Character | Select-Object -ExpandProperty Characters\r\n        if ($Characters -ge 10000) {\r\n            throw [System.ArgumentOutOfRangeException]::New(\"Character limit exceeded, value is greater than 10,000 characters.\")\r\n        }\r\n        \r\n        # If we're requested to set the field value for a Ninja document we'll specify it here.\r\n        $DocumentationParams = @{}\r\n        if ($DocumentName) { $DocumentationParams[\"DocumentName\"] = $DocumentName }\r\n        \r\n        # This is a list of valid fields that can be set. If no type is given, it will be assumed that the input doesn't need to be changed.\r\n        $ValidFields = \"Attachment\", \"Checkbox\", \"Date\", \"Date or Date Time\", \"Decimal\", \"Dropdown\", \"Email\", \"Integer\", \"IP Address\", \"MultiLine\", \"MultiSelect\", \"Phone\", \"Secure\", \"Text\", \"Time\", \"URL\", \"WYSIWYG\"\r\n        if ($Type -and $ValidFields -notcontains $Type) { Write-Warning \"$Type is an invalid type! Please check here for valid types. https:\/\/ninjarmm.zendesk.com\/hc\/en-us\/articles\/16973443979789-Command-Line-Interface-CLI-Supported-Fields-and-Functionality\" }\r\n        \r\n        # The field below requires additional information to be set\r\n        $NeedsOptions = \"Dropdown\"\r\n        if ($DocumentName) {\r\n            if ($NeedsOptions -contains $Type) {\r\n                # We'll redirect the error output to the success stream to make it easier to error out if nothing was found or something else went wrong.\r\n                $NinjaPropertyOptions = Ninja-Property-Docs-Options -AttributeName $Name @DocumentationParams 2&gt;&amp;1\r\n            }\r\n        }\r\n        else {\r\n            if ($NeedsOptions -contains $Type) {\r\n                $NinjaPropertyOptions = Ninja-Property-Options -Name $Name 2&gt;&amp;1\r\n            }\r\n        }\r\n        \r\n        # If an error is received it will have an exception property, the function will exit with that error information.\r\n        if ($NinjaPropertyOptions.Exception) { throw $NinjaPropertyOptions }\r\n        \r\n        # The below type's require values not typically given in order to be set. The below code will convert whatever we're given into a format ninjarmm-cli supports.\r\n        switch ($Type) {\r\n            \"Checkbox\" {\r\n                # While it's highly likely we were given a value like \"True\" or a boolean datatype it's better to be safe than sorry.\r\n                $NinjaValue = [System.Convert]::ToBoolean($Value)\r\n            }\r\n            \"Date or Date Time\" {\r\n                # Ninjarmm-cli expects the GUID of the option to be selected. Therefore, the given value will be matched with a GUID.\r\n                $Date = (Get-Date $Value).ToUniversalTime()\r\n                $TimeSpan = New-TimeSpan (Get-Date \"1970-01-01 00:00:00\") $Date\r\n                $NinjaValue = $TimeSpan.TotalSeconds\r\n            }\r\n            \"Dropdown\" {\r\n                # Ninjarmm-cli is expecting the guid of the option we're trying to select. So we'll match up the value we were given with a guid.\r\n                $Options = $NinjaPropertyOptions -replace '=', ',' | ConvertFrom-Csv -Header \"GUID\", \"Name\"\r\n                $Selection = $Options | Where-Object { $_.Name -eq $Value } | Select-Object -ExpandProperty GUID\r\n        \r\n                if (-not $Selection) {\r\n                    throw [System.ArgumentOutOfRangeException]::New(\"Value is not present in dropdown\")\r\n                }\r\n        \r\n                $NinjaValue = $Selection\r\n            }\r\n            default {\r\n                # All the other types shouldn't require additional work on the input.\r\n                $NinjaValue = $Value\r\n            }\r\n        }\r\n        \r\n        # We'll need to set the field differently depending on if its a field in a Ninja Document or not.\r\n        if ($DocumentName) {\r\n            $CustomField = Ninja-Property-Docs-Set -AttributeName $Name -AttributeValue $NinjaValue @DocumentationParams 2&gt;&amp;1\r\n        }\r\n        else {\r\n            $CustomField = Ninja-Property-Set -Name $Name -Value $NinjaValue 2&gt;&amp;1\r\n        }\r\n        \r\n        if ($CustomField.Exception) {\r\n            throw $CustomField\r\n        }\r\n    }\r\n\r\n    function Get-NinjaProperty {\r\n        [CmdletBinding()]\r\n        Param(\r\n            [Parameter(Mandatory = $True, ValueFromPipeline = $True)]\r\n            [String]$Name,\r\n            [Parameter()]\r\n            [String]$Type,\r\n            [Parameter()]\r\n            [String]$DocumentName\r\n        )\r\n    \r\n        # If we're requested to get the field value from a Ninja document we'll specify it here.\r\n        $DocumentationParams = @{}\r\n        if ($DocumentName) { $DocumentationParams[\"DocumentName\"] = $DocumentName }\r\n    \r\n        # These two types require more information to parse.\r\n        $NeedsOptions = \"DropDown\", \"MultiSelect\"\r\n    \r\n        # Grabbing document values requires a slightly different command.\r\n        if ($DocumentName) {\r\n            # Secure fields are only readable when they're a device custom field\r\n            if ($Type -Like \"Secure\") { throw [System.ArgumentOutOfRangeException]::New(\"$Type is an invalid type! Please check here for valid types. https:\/\/ninjarmm.zendesk.com\/hc\/en-us\/articles\/16973443979789-Command-Line-Interface-CLI-Supported-Fields-and-Functionality\") }\r\n    \r\n            # We'll redirect the error output to the success stream to make it easier to error out if nothing was found or something else went wrong.\r\n            Write-Host \"Retrieving value from Ninja Document...\"\r\n            $NinjaPropertyValue = Ninja-Property-Docs-Get -AttributeName $Name @DocumentationParams 2&gt;&amp;1\r\n    \r\n            # Certain fields require more information to parse.\r\n            if ($NeedsOptions -contains $Type) {\r\n                $NinjaPropertyOptions = Ninja-Property-Docs-Options -AttributeName $Name @DocumentationParams 2&gt;&amp;1\r\n            }\r\n        }\r\n        else {\r\n            # We'll redirect error output to the success stream to make it easier to error out if nothing was found or something else went wrong.\r\n            $NinjaPropertyValue = Ninja-Property-Get -Name $Name 2&gt;&amp;1\r\n    \r\n            # Certain fields require more information to parse.\r\n            if ($NeedsOptions -contains $Type) {\r\n                $NinjaPropertyOptions = Ninja-Property-Options -Name $Name 2&gt;&amp;1\r\n            }\r\n        }\r\n    \r\n        # If we received some sort of error it should have an exception property and we'll exit the function with that error information.\r\n        if ($NinjaPropertyValue.Exception) { throw $NinjaPropertyValue }\r\n        if ($NinjaPropertyOptions.Exception) { throw $NinjaPropertyOptions }\r\n    \r\n        if (-not $NinjaPropertyValue) {\r\n            throw [System.NullReferenceException]::New(\"The Custom Field '$Name' is empty!\")\r\n        }\r\n    \r\n        # This switch will compare the type given with the quoted string. If it matches, it'll parse it further; otherwise, the default option will be selected.\r\n        switch ($Type) {\r\n            \"Dropdown\" {\r\n                # Drop-Down custom fields come in as a comma-separated list of GUIDs; we'll compare these with all the options and return just the option values selected instead of a GUID.\r\n                $Options = $NinjaPropertyOptions -replace '=', ',' | ConvertFrom-Csv -Header \"GUID\", \"Name\"\r\n                $Options | Where-Object { $_.GUID -eq $NinjaPropertyValue } | Select-Object -ExpandProperty Name\r\n            }\r\n            \"MultiSelect\" {\r\n                # Multi-Select custom fields come in as a comma-separated list of GUID's we'll compare these with all the options and return just the option values selected instead of a guid.\r\n                $Options = $NinjaPropertyOptions -replace '=', ',' | ConvertFrom-Csv -Header \"GUID\", \"Name\"\r\n                $Selection = ($NinjaPropertyValue -split ',').trim()\r\n    \r\n                foreach ($Item in $Selection) {\r\n                    $Options | Where-Object { $_.GUID -eq $Item } | Select-Object -ExpandProperty Name\r\n                }\r\n            }\r\n            default {\r\n                # If no type was given or not one that matches the above types just output what we retrieved.\r\n                $NinjaPropertyValue\r\n            }\r\n        }\r\n    }\r\n\r\n    # List of AV's and how to detect them.\r\n    $AVList = @(\r\n        [PSCustomObject]@{ Name = \"Bitdefender Antivirus\"; DisplayName = \"Bitdefender Agent\", \"Bitdefender Endpoint Security Tools\"; xmlPath = \"$env:ProgramFiles\\BitDefender\\Endpoint Security\\update_statistics.xml\"; ExecutablePath = \"Bitdefender\\Endpoint Security\\EPSecurityService.exe\", \"Bitdefender Agent\\ProductAgentService.exe\", \"Bitdefender\\Endpoint Security\\EPProtectedService.exe\"; ProcessName = \"ProductAgentUi\", \"ProductAgentService\", \"EPProtectedService\", \"EPSecurityService\" }\r\n        [PSCustomObject]@{ Name = \"Carbon Black\"; DisplayName = \"Carbon Black Cloud Sensor\", \"Carbon Black App Control Agent\"; Definitions = \"Confer\\scanner\\data_0\\aevdf.dat\"; ExecutablePath = \"Confer\\RepMgr64.exe\", \"Confer\\RepWSC64.exe\", \"Confer\\repwav.exe\"; SpecialExecutablePath = \"$env:SystemRoot\\CarbonBlack\\cb.exe\"; ProcessName = \"RepMgr64\", \"RepWSC64\", \"cb\" }\r\n        [PSCustomObject]@{ Name = \"Crowdstrike\"; DisplayName = \"CrowdStrike Windows Sensor\", \"Falcon Agent\"; Definitions = \"$env:SystemRoot\\system32\\drivers\\crowdstrike\\*.sys\"; ExecutablePath = \"CrowdStrike\\CSFalconService.exe\"; ProcessName = \"CSFalconService\" }\r\n        [PSCustomObject]@{ Name = \"Cylance\"; DisplayName = \"Cylance OPTICS\", \"Cylance Smart Antivirus\", \"Cylance PROTECT\"; Definitions = \"$env:ProgramData\\Cylance\\Desktop\\chp.db\"; ExecutablePath = \"Cylance\\Desktop\\CylanceSvc.exe\", \"Cylance\\Optics\\CyOptics.exe\"; ProcessName = \"cylancesvc\", \"cylancedrv\", \"CyOptics\" }\r\n        [PSCustomObject]@{ Name = \"ESET Security\"; DisplayName = \"ESET Security\", \"ESET Endpoint Security\", \"ESET Management Agent\", \"ESET Server Security\"; RegistryDefPath = \"HKLM:\\SOFTWARE\\ESET\\ESET Security\\CurrentVersion\\Info\"; RegistryDefName = \"ScannerVersion\"; ExecutablePath = \"ESET\\RemoteAdministrator\\Agent\\ERAAgent.exe\", \"ESET\\ESET Security\\ekrn.exe\"; ProcessName = \"ERAAgent\", \"ekrn\" }\r\n        [PSCustomObject]@{ Name = \"Huntress\"; DisplayName = \"Huntress Agent\"; ExecutablePath = \"Huntress\\HuntressAgent.exe\"; ProcessName = \"HuntressAgent\", \"HuntressRio\" }\r\n        [PSCustomObject]@{ Name = \"MalwareBytes\"; DisplayName = \"Malwarebytes\"; Definitions = \"$env:ProgramData\\Malwarebytes\\MBAMService\\scan.mbdb\"; ExecutablePath = \"Malwarebytes\\Anti-Malware\\mbam.exe\", \"Malwarebytes\\Anti-Malware\\MBAMService.exe\"; ProcessName = \"MBAMService\" }\r\n        [PSCustomObject]@{ Name = \"Windows Defender\"; ProcessName = \"MsMpEng\" }\r\n        [PSCustomObject]@{ Name = \"Sentinel Agent\"; DisplayName = \"Sentinel Agent\"; Definitions = \"$env:ProgramFiles\\SentinelOne\\Sentinel Agent *\\config\\DecoyPersistentConfig.json\"; ExecutablePath = \"SentinelOne\\Sentinel Agent *\\SentinelAgent.exe\"; ProcessName = \"SentinelServiceHost\", \"SentinelStaticEngine\", \"SentinelStaticEngineScanner\", \"SentinelUI\" }\r\n        [PSCustomObject]@{ Name = \"Sophos\"; DisplayName = \"Sophos Endpoint Agent\"; RegistryDefPath = \"HKLM:\\SOFTWARE\\Sophos\\Sophos File Scanner\\Application\\Versions\"; RegistryDefName = \"VirusDataVersion\"; ExecutablePath = \"Sophos\\Remote Management System\\ManagementAgentNT.exe\", \"Sophos\\Sophos Anti-Virus\\SavService.exe\", \"Sophos\\Endpoint Defense\\SEDService.exe\"; ProcessName = \"ManagementAgentNT\", \"SAVService\", \"SEDService\" }\r\n        [PSCustomObject]@{ Name = \"Vipre\"; DisplayName = \"VIPRE Business Agent\"; Definitions = \"$env:ProgramFiles\\VIPRE Business Agent\\Definitions\\defver.txt\"; ExecutablePath = \"VIPRE\\SBAMSvc.exe\"; ProcessName = \"SBAMSvc\" }\r\n        [PSCustomObject]@{ Name = \"Webroot SecureAnywhere\"; DisplayName = \"Webroot SecureAnywhere\"; Definitions = \"$env:ProgramData\\WRData\\WRlog.log\"; ExecutablePath = \"Webroot\\WRSA.exe\"; ProcessName = \"WRSA\" }\r\n    )\r\n\r\n    $ExitCode = 0\r\n}\r\nprocess {\r\n\r\n    # Let's see what tools we don't want to alert on.\r\n    $ExcludedAVs = New-Object System.Collections.Generic.List[String]\r\n\r\n    if ($ExcludeAV) {\r\n        $ExcludeAV.split(',') | ForEach-Object {\r\n            $ExcludedAVs.Add($_.Trim())\r\n        }\r\n    }\r\n\r\n    # For this kind of alert it might be worth it to create a whole custom field of ignorables.\r\n    if ($ExclusionsFromCustomField) {\r\n        try {\r\n            Write-Host \"Retrieving exclusions from custom field '$ExclusionsFromCustomField'...\"\r\n            $Exclusions = Get-NinjaProperty -Name $ExclusionsFromCustomField\r\n            Write-Host \"Successfully retrieved $Exclusions.\"\r\n        }\r\n        catch {\r\n            Write-Host \"[Error] $($_.Message)\"\r\n            exit 1\r\n        }\r\n        \r\n        if ($Exclusions) {\r\n            $Exclusions.split(',') | ForEach-Object {\r\n                $ExcludedAVs.Add($_.Trim())\r\n            }\r\n        }\r\n    }\r\n\r\n    # WMI Would have better AV coverage and would likely be more accurate. However Windows Server does not have the Security Center\r\n    if (Test-IsWorkstation) {\r\n        Write-Host \"Desktop Windows Detected, Checking the Windows Security Center....\"\r\n        $AVinfo = if ($PSVersionTable.PSVersion.Major -ge 5) {\r\n            Get-CimInstance -Namespace root\/SecurityCenter2 -Class AntivirusProduct\r\n        }\r\n        else {\r\n            Get-WmiObject -Namespace root\/SecurityCenter2 -Class AntivirusProduct\r\n        }\r\n    }\r\n\r\n    $AVs = New-Object System.Collections.Generic.List[Object]\r\n\r\n    # This takes our list and begins searching by the 4 methods in the begin block.\r\n    if ($AVInfo) {\r\n        Write-Warning \"Antivirus info received from the Windows Security Center, this may result in duplicate entries in the report due to their naming scheme.\"\r\n        $AVinfo | ForEach-Object {\r\n            $Executable = ($_.pathToSignedReportingExe -replace '%programfiles%', \"$env:ProgramFiles\" | Get-Item).BaseName\r\n            $RunningStatus = Find-Process -Name $Executable\r\n\r\n            $ConvertToHex = [Convert]::ToString($_.ProductState, 16).PadLeft(6, '0')\r\n            $ProductStateHex = $ConvertToHex.Substring(2, 2)\r\n            $DefinitionsHex = $ConvertToHex.Substring(4, 2)\r\n\r\n            $ProductState = switch ($ProductStateHex) {\r\n                \"10\" { \"Active\" }\r\n                default { \"Inactive\" }\r\n            }\r\n\r\n            $UpToDateWMI = switch ($DefinitionsHex) {\r\n                \"00\" { $True }\r\n                default { $False }\r\n            }\r\n\r\n            if ($_.displayName -eq \"Windows Defender\" -and ((Get-Command Get-MpComputerStatus -ErrorAction SilentlyContinue).Count -ne 0)) {\r\n                $Version = (Get-MpComputerStatus).AMProductVersion\r\n                $Definitions = (Get-MpComputerStatus).AntivirusSignatureLastUpdated\r\n            }\r\n            else {\r\n                $Definitions = Get-Date $_.timestamp -ErrorAction SilentlyContinue\r\n            }\r\n\r\n            $UpToDate = if ($Definitions -and $Definitions -gt (Get-Date).AddDays(-$OutOfDate) -and ($UpToDateWMI -like \"True\")) {\r\n                $True\r\n            }\r\n            else {\r\n                $False\r\n            }\r\n\r\n            if ($_.displayName -ne \"Windows Defender\") {\r\n                $Version = Find-UninstallKey -Version -DisplayName \"$($_.displayName)\"\r\n            }\r\n\r\n            [PSCustomObject]@{\r\n                Name        = $_.displayName\r\n                Installed   = \"Yes\"\r\n                Definitions = if ($Definitions) { Get-Date $Definitions -Format \"yyyy\/MM\/dd\" }else { $null }\r\n                UpToDate    = $UpToDate\r\n                Running     = if ($RunningStatus) { \"Yes\" }else { \"No\" }\r\n                Service     = $ProductState\r\n                Version     = if ($Version) { \"$Version\" }else { $null }\r\n            } | Where-Object { $ExcludedAVs -notcontains $_.Name } | ForEach-Object { $AVs.Add($_) }\r\n        } \r\n    }\r\n\r\n    $AVList | Where-Object { $AVs.Name -notcontains $_.Name } | ForEach-Object {\r\n\r\n        $UninstallKey = if ($_.DisplayName) {\r\n            $_.DisplayName | Find-UninstallKey\r\n        }\r\n        \r\n        $UninstallInfo = if ($_.DisplayName) {\r\n            $_.DisplayName | Find-UninstallKey -Version\r\n        }\r\n        \r\n        $RunningStatus = if ($_.ProcessName) {\r\n            $_.ProcessName | Find-Process\r\n        }\r\n\r\n        $ServiceStatus = if ($_.ProcessName) {\r\n            $_.ProcessName | Find-Service\r\n        }\r\n\r\n        # AV's don't really have a consistent way to check their definitions (unless it's desktop windows)\r\n        $Definitions = if ($_.Definitions) {\r\n            $_.Definitions | Find-Definitions\r\n        }\r\n        elseif ($_.Name -eq \"BitDefender\") {\r\n            [xml]$xml = Get-Content $_.xmlPath -ErrorAction SilentlyContinue\r\n            if ($xml) {\r\n                [datetime]$origin = '1970-01-01 00:00:00'\r\n                $ConvertFromUnix = $origin.AddSeconds($xml.UpdateStatistics.Antivirus.Check.updtime)\r\n                Get-Date ($ConvertFromUnix.ToLocalTime()) -ErrorAction SilentlyContinue\r\n            }\r\n        }\r\n        elseif ($_.Name -eq \"Sophos\") {\r\n            $RegValue = (Get-ItemProperty -Path $_.RegistryDefPath -ErrorAction SilentlyContinue).($_.RegistryDefName)\r\n            if ($RegValue) {\r\n                Get-Date ([datetime]::ParseExact($RegValue.SubString(0, 8), 'yyyyMMdd', $null)) -ErrorAction SilentlyContinue\r\n            }\r\n        }\r\n        elseif ($_.Name -eq \"ESET\") {\r\n            $RegValue = (Get-ItemProperty -Path $_.RegistryDefPath -ErrorAction SilentlyContinue).($_.RegistryDefName)\r\n            if ($RegValue) {\r\n                $RegValue -match '(\\d{8})' | Out-Null\r\n                Get-Date ([datetime]::ParseExact($Matches[0], 'yyyyMMdd', $null)) -ErrorAction SilentlyContinue\r\n            }\r\n        }\r\n        \r\n        $InstallPath = if ($_.ExecutablePath) {\r\n            $_.ExecutablePath | Find-Executable\r\n        }\r\n        elseif ($_.SpecialExecutablePath) {\r\n            $_.SpecialExecutablePath | Find-Executable -Special\r\n        }\r\n\r\n        if ($UninstallKey -or $RunningStatus -or $InstallPath -or $ServiceStatus) {\r\n            $Installed = \"Yes\"\r\n        }\r\n        else {\r\n            $Installed = \"No\"\r\n        }\r\n\r\n        if ($_.Name -eq \"Windows Defender\" -and ((Get-Command Get-MpComputerStatus -ErrorAction SilentlyContinue).Count -ne 0)) {\r\n            $UninstallInfo = (Get-MpComputerStatus).AMProductVersion\r\n            $Definitions = (Get-MpComputerStatus).AntivirusSignatureLastUpdated\r\n        }\r\n\r\n        $UpToDate = if ($Definitions -and $Definitions -gt (Get-Date).AddDays(-$OutOfDate)) {\r\n            $True\r\n        }\r\n        else {\r\n            $False\r\n        }\r\n\r\n        [PSCustomObject]@{\r\n            Name        = $_.Name\r\n            Installed   = $Installed\r\n            Definitions = if ($Definitions) { Get-Date $Definitions -Format \"yyyy\/MM\/dd\" }else { $Null }\r\n            UpToDate    = $UpToDate\r\n            Running     = if ($RunningStatus) { \"Yes\" }else { \"No\" }\r\n            Service     = if ($ServiceStatus) { \"Active\" }else { \"Inactive\" }\r\n            Version     = $UninstallInfo\r\n        } | Where-Object { $ExcludedAVs -notcontains $_.Name } | ForEach-Object { $AVs.Add($_) }\r\n    }\r\n\r\n    $InstalledAVs = $AVs | Where-Object { $_.Installed -eq \"Yes\" }\r\n    Write-Host \"\"\r\n\r\n    if (!$InstalledAVs) {\r\n        Write-Host \"[Alert] It appears there's no installed antivirus? You may want to check the list of AV's this script supports.\"\r\n        $ExitCode = 1\r\n    }\r\n    \r\n    if ($InstalledAVs | Where-Object { $_.UpToDate -Like \"False\" }) {\r\n        Write-Host \"[Alert] The AV definitions are out of date!\"\r\n        $ExitCode = 1\r\n    }\r\n\r\n    if ($InstalledAVs | Where-Object { $_.HasRunningService -Like \"False\" }) {\r\n        Write-Host \"[Alert] The AV's service doesn't appear to be running, is the AV Updating or performing maintenance?\"\r\n        $ExitCode = 1\r\n    }\r\n\r\n    if ($InstalledAVs | Where-Object { $_.CurrentlyRunning -Like \"False\" }) {\r\n        Write-Host \"[Alert] The AV doesn't appear to have a running process, is the AV Updating or performing maintenance?\"\r\n        $ExitCode = 1\r\n    }\r\n\r\n    # If we found anything in the four checks, we're going to indicate it's installed, but we may also want to save our results to a custom field.\r\n    if ($ShowNotFound) {\r\n        $AVs | Format-Table -AutoSize -Wrap | Out-String | Write-Host\r\n    }\r\n    else {\r\n        if ($InstalledAVs) {\r\n            $InstalledAVs | Format-Table -AutoSize -Wrap | Out-String | Write-Host\r\n        }\r\n    }\r\n\r\n    if ($ExportAll) {\r\n        $ExportReport = $InstalledAVs | Format-Table -AutoSize -Wrap | Out-String\r\n        try {\r\n            Write-Host \"Attempting to set Custom Field '$ExportAll'.\"\r\n            Set-NinjaProperty -Name $ExportAll -Value $ExportReport\r\n            Write-Host \"Successfully set Custom Field '$ExportAll'!\"\r\n        }\r\n        catch {\r\n            Write-Host \"[Error] $($_.Message)\"\r\n            $ExitCode = 1\r\n        }\r\n    }\r\n\r\n    if ($ExportDef) {\r\n        try {\r\n            Write-Host \"Attempting to set Custom Field '$ExportDef'.\"\r\n            $Value = ($InstalledAVs | Select-Object -ExpandProperty Definitions) -join ', '\r\n            Set-NinjaProperty -Name $ExportDef -Value ( $Value | Out-String )\r\n            Write-Host \"Successfully set Custom Field '$ExportDef'!\"\r\n        }\r\n        catch {\r\n            Write-Host \"[Error] $($_.Message)\"\r\n            $ExitCode = 1\r\n        }\r\n    }\r\n\r\n    if ($ExportDefStatus) {\r\n        try {\r\n            Write-Host \"Attempting to set Custom Field '$ExportDefStatus'.\"\r\n            $Value = ($InstalledAVs | Select-Object -ExpandProperty UpToDate) -join ', '\r\n            Set-NinjaProperty -Name $ExportDefStatus -Value ( $Value | Out-String )\r\n            Write-Host \"Successfully set Custom Field '$ExportDefStatus'!\"\r\n        }\r\n        catch {\r\n            Write-Host \"[Error] $($_.Message)\"\r\n            $ExitCode = 1\r\n        }\r\n    }\r\n\r\n    if ($ExportName) {\r\n        try {\r\n            Write-Host \"Attempting to set Custom Field '$ExportName'.\"\r\n            $Value = ($InstalledAVs | Select-Object -ExpandProperty Name) -join ', '\r\n            Set-NinjaProperty -Name $ExportName -Value ( $Value | Out-String )\r\n            Write-Host \"Successfully set Custom Field '$ExportName'!\"\r\n        }\r\n        catch {\r\n            Write-Host \"[Error] $($_.Message)\"\r\n            $ExitCode = 1\r\n        } \r\n    }\r\n\r\n    if ($ExportStatus) {\r\n        try {\r\n            Write-Host \"Attempting to set Custom Field '$ExportStatus'.\"\r\n            $Value = ($InstalledAVs | Select-Object -ExpandProperty Running) -join ', '\r\n            Set-NinjaProperty -Name $ExportStatus -Value ( $Value | Out-String )\r\n            Write-Host \"Successfully set Custom Field '$ExportStatus'!\"\r\n        }\r\n        catch {\r\n            Write-Host \"[Error] $($_.Message)\"\r\n            $ExitCode = 1\r\n        }\r\n    }\r\n\r\n    if ($ExportVersion) {\r\n        try {\r\n            Write-Host \"Attempting to set Custom Field '$ExportVersion'.\"\r\n            $Value = (($InstalledAVs | Select-Object -ExpandProperty Version | ForEach-Object { $_.Trim() }) -join ', ')\r\n            Set-NinjaProperty -Name $ExportVersion -Value ($Value | Out-String)\r\n            Write-Host \"Successfully set Custom Field '$ExportVersion'!\"\r\n        }\r\n        catch {\r\n            Write-Host \"[Error] $($_.Message)\"\r\n            $ExitCode = 1\r\n        }\r\n    }\r\n\r\n    exit $ExitCode\r\n}end {\r\n    \r\n    \r\n    \r\n}<\/pre>\n<p>&nbsp;<\/p>\n\n<div class=\"in-context-cta\"><p>Accede a m\u00e1s de 300 scripts en el Dojo de NinjaOne<\/p>\n<p><a href=\"https:\/\/www.ninjaone.com\/es\/prueba-gratuita-formulario\/\">Obt\u00e9n acceso<\/a><\/p>\n<\/div>\n<h2>An\u00e1lisis detallado<\/h2>\n<p>Este script PowerShell est\u00e1 dise\u00f1ado para detectar varios programas antivirus instalados en un sistema Windows, recuperar detalles sobre sus definiciones y estado, y exportar los resultados. Admite la detecci\u00f3n de 11 soluciones antivirus comunes, como BitDefender, Carbon Black, Crowdstrike, Cylance, ESET, Huntress, MalwareBytes, Windows Defender, SentinelOne, Sophos, Vipre y Webroot.<\/p>\n<h2>C\u00f3mo funciona<\/h2>\n<p><strong>1. Inicializaci\u00f3n y gesti\u00f3n de par\u00e1metros: <\/strong>el script para comprobar el estado del antivirus comienza definiendo varios par\u00e1metros que pueden utilizarse para personalizar su ejecuci\u00f3n. Estos incluyen opciones para excluir antivirus espec\u00edficos. Verifica que se est\u00e1 ejecutando con privilegios de administrador, ya que esto es necesario para acceder a cierta informaci\u00f3n del sistema. Si el script no se ejecuta como administrador, terminar\u00e1 con un mensaje de error.<\/p>\n<p><strong>2. Comprobaci\u00f3n de privilegios de administrador:<\/strong> el script para comprobar el estado del antivirus verifica que se est\u00e1 ejecutando con privilegios de administrador, ya que esto es necesario para acceder a cierta informaci\u00f3n del sistema. Si el script no se ejecuta como administrador, terminar\u00e1 con un mensaje de error.<\/p>\n<p><strong>3. Recuperaci\u00f3n de informaci\u00f3n del antivirus: e<\/strong>l script para comprobar el estado del antivirus utiliza varios m\u00e9todos para detectar el software antivirus instalado:<\/p>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:1440,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"1\" data-aria-level=\"2\"><strong>Claves de registro:<\/strong> Busca en el registro de Windows entradas relacionadas con software antivirus.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:1440,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"2\" data-aria-level=\"2\"><strong>WMI (Instrumentos de gesti\u00f3n de Windows):<\/strong> Para los sistemas de sobremesa, consulta el Centro de seguridad de Windows para obtener informaci\u00f3n sobre el antivirus.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:1440,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"3\" data-aria-level=\"2\"><strong>Procesos y servicios:<\/strong> Comprueba si se est\u00e1n ejecutando procesos y servicios asociados a programas antivirus conocidos.<\/li>\n<\/ul>\n<p><strong>4. Recopilaci\u00f3n de fechas de definici\u00f3n: <\/strong> Para cada programa antivirus detectado, el script para comprobar el estado del antivirus recupera la fecha de la \u00faltima actualizaci\u00f3n de la definici\u00f3n. Se utiliza para determinar si las definiciones est\u00e1n obsoletas en funci\u00f3n del umbral especificado.<\/p>\n<p><strong>5. Recopilaci\u00f3n de resultados: <\/strong> El script recopila los resultados en una tabla, incluyendo detalles como el nombre del software antivirus, si est\u00e1 instalado, la fecha de la \u00faltima actualizaci\u00f3n de la definici\u00f3n, su versi\u00f3n y su estado de ejecuci\u00f3n actual.<\/p>\n<p><strong>6. Exportaci\u00f3n de resultados: <\/strong> Si se especifica, el script exporta los resultados a campos personalizados, lo que puede ser \u00fatil para la integraci\u00f3n con herramientas de gesti\u00f3n de TI como NinjaOne.<\/p>\n<h2>Posibles casos de uso<\/h2>\n<p>Piensa en un profesional de TI que gestiona una gran red de sistemas Windows. Comprobar manualmente y con regularidad el estado del antivirus en cada sistema lleva mucho tiempo y es propenso a errores. Utilizando este script, el profesional de TI puede automatizar el proceso, asegur\u00e1ndose de que todos los sistemas tienen definiciones antivirus actualizadas y est\u00e1n ejecutando activamente su software antivirus. Si se detecta alg\u00fan problema, como definiciones obsoletas o programas antivirus inactivos, el script puede alertar al equipo de TI, lo que permite poner remedio r\u00e1pidamente.<\/p>\n<h2>M\u00e9todos alternativos<\/h2>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"2\" data-aria-level=\"1\"><strong>Comprobaci\u00f3n manual:<\/strong> Verificar manualmente el estado del antivirus en cada sistema es laborioso e ineficaz, especialmente en entornos grandes.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"3\" data-aria-level=\"1\"><strong>Herramientas de terceros:<\/strong> Aunque existen herramientas comerciales para supervisar el estado de los antivirus, pueden ser caras y requerir una infraestructura adicional.<\/li>\n<\/ul>\n<p>Este script PowerShell ofrece una alternativa rentable y flexible, que permite a los profesionales de TI personalizarlo seg\u00fan sus necesidades espec\u00edficas.<\/p>\n<h2>FAQ<\/h2>\n<h3>\u00bfC\u00f3mo puedo ejecutar el script con privilegios de administrador?<\/h3>\n<p>Haz clic con el bot\u00f3n derecho en la aplicaci\u00f3n PowerShell y selecciona \u00abEjecutar como administrador\u00bb antes de ejecutar el script.<\/p>\n<h3>\u00bfPuedo a\u00f1adir m\u00e1s programas antivirus a la lista de detecci\u00f3n?<\/h3>\n<p>S\u00ed, el script puede modificarse para incluir programas antivirus adicionales a\u00f1adiendo sus detalles a la matriz $AVList.<\/p>\n<h3>\u00bfQu\u00e9 debo hacer si el script informa de definiciones obsoletas?<\/h3>\n<p>Comprueba los sistemas afectados para asegurarte de que est\u00e1n conectados a Internet y configurados para recibir actualizaciones autom\u00e1ticas. Si es necesario, actualiza manualmente las definiciones antivirus.<\/p>\n<h2>Implicaciones<\/h2>\n<p>Comprobar regularmente el estado del antivirus es crucial para mantener un entorno inform\u00e1tico seguro. Este script ayuda a garantizar que los programas antivirus est\u00e9n instalados, actualizados y en ejecuci\u00f3n activa, <a href=\"https:\/\/www.ninjaone.com\/blog\/5-steps-for-removing-malware-from-your-computer\/\" target=\"_blank\" rel=\"noopener\">reduciendo as\u00ed el riesgo de infecciones por malware<\/a> y otras amenazas a la seguridad. Al automatizar estas comprobaciones, los departamentos de TI pueden centrarse en otras tareas cr\u00edticas, mejorando la eficacia general y la postura de seguridad.<\/p>\n<h2>Recomendaciones<\/h2>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"4\" data-aria-level=\"1\"><strong>Programa revisiones peri\u00f3dicas:<\/strong> ejecuta el script para comprobar el estado del antivirus de forma regular (por ejemplo, diaria o semanalmente) para garantizar una supervisi\u00f3n continua del estado del antivirus.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"5\" data-aria-level=\"1\"><strong>Personaliza las exclusiones:<\/strong> utiliza el par\u00e1metro -ExcludeAV para excluir cualquier programa antivirus que no sea relevante para tu entorno.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"6\" data-aria-level=\"1\"><strong>Revisa las alertas y act\u00faa en consecuencia:<\/strong> atiende r\u00e1pidamente cualquier alerta generada por el script, como definiciones obsoletas o programas antivirus inactivos.<\/li>\n<\/ul>\n<h2>Reflexiones finales<\/h2>\n<p>En el \u00e1mbito de la seguridad de TI, mantenerse alerta es primordial. Este script de PowerShell para comprobar el estado del antivirus constituye una potente herramienta para automatizar la supervisi\u00f3n del estado del antivirus, garantizando que los sistemas est\u00e9n protegidos contra las amenazas emergentes. Al integrar este script con herramientas de gesti\u00f3n como <a href=\"https:\/\/www.ninjaone.com\/es\/\" target=\"_blank\" rel=\"noopener\">NinjaOne<\/a>, los profesionales de TI pueden agilizar a\u00fan m\u00e1s sus flujos de trabajo y mejorar su postura de seguridad.<\/p>\n","protected":false},"author":35,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"_relevanssi_hide_post":"","_relevanssi_hide_content":"","_relevanssi_pin_for_all":"","_relevanssi_pin_keywords":"","_relevanssi_unpin_keywords":"","_relevanssi_related_keywords":"","_relevanssi_related_include_ids":"","_relevanssi_related_exclude_ids":"","_relevanssi_related_no_append":"","_relevanssi_related_not_related":"","_relevanssi_related_posts":"","_relevanssi_noindex_reason":"","_lmt_disableupdate":"no","_lmt_disable":""},"operating_system":[4212],"use_cases":[4262,4264],"class_list":["post-387242","script_hub","type-script_hub","status-publish","hentry","script_hub_category-windows","use_cases-mantenimiento","use_cases-seguridad-de-redes"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/script_hub\/387242","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/script_hub"}],"about":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/types\/script_hub"}],"author":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/users\/35"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/comments?post=387242"}],"wp:attachment":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/media?parent=387242"}],"wp:term":[{"taxonomy":"script_hub_category","embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/operating_system?post=387242"},{"taxonomy":"use_cases","embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/use_cases?post=387242"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}