Procedimientos para solucionar problemas relacionados con el agente de Log Analytics para Windows

En este artículo se proporciona información sobre los errores que es posible que experimente con el agente de Log Analytics para Windows en Azure Monitor y se sugieren posibles soluciones para resolverlos.

Herramienta de solución de problemas de Log Analytics

La herramienta de solución de problemas de Windows del agente de Log Analytics es una colección de scripts de PowerShell diseñada para ayudar a detectar y diagnosticar problemas del agente de Log Analytics. Se incluye automáticamente con el agente en la instalación. La ejecución de la herramienta debe ser el primer paso para diagnosticar un problema.

Uso de la herramienta de solución de problemas

  1. Abra el símbolo del sistema de PowerShell como administrador en la máquina donde está instalado el agente de Log Analytics.

  2. Vaya al directorio donde se encuentra la herramienta:

    cd "C:\Program Files\Microsoft Monitoring Agent\Agent\Troubleshooter"

  3. Ejecute el script principal con este comando:

    .\GetAgentInfo.ps1

  4. Seleccione un escenario de solución de problemas.

  5. Siga las instrucciones de la consola. Tenga en cuenta que los pasos de los registros de seguimiento requieren la intervención manual para detener la recopilación de registros. En función de la posibilidad de reproducir el problema, espere mientras dura y seleccione «s» para detener la recopilación de registros y seguir con el paso siguiente.

    La ubicación del archivo de resultados se registra al finalizar y se abre una nueva ventana del explorador en donde se resalta este archivo.

Instalación

La herramienta de solución de problemas se incluye automáticamente al instalar la compilación 10.20.18053.0 o posterior del agente de Log Analytics.

Escenarios descritos

La herramienta de solución de problemas comprueba los siguientes escenarios:

  • Faltan datos de informes del agente o faltan datos de latido.
  • La implementación de la extensión del agente está fallando.
  • El agente se bloquea.
  • El agente consume mucha CPU o memoria.
  • Errores de instalación y desinstalación.
  • Los registros personalizados tienen incidencias.
  • La puerta de enlace OMS tiene incidencias.
  • Los contadores de rendimiento tienen incidencias.
  • No se pueden recopilar los registros del agente.

Nota

Ejecute la herramienta de solución de problemas cuando experimente una incidencia. Disponer inicialmente de los registros ayudará a nuestro equipo de soporte técnico a solucionar la incidencia más rápido.

Orígenes de solución de problemas importantes

Para ayudar a solucionar los problemas relacionados con el agente de Log Analytics para Windows, el agente registra los eventos en el registro de eventos de Windows, concretamente en Aplicaciones y servicios\Operations Manager.

Problemas de conectividad

Si el agente se comunica a través de un servidor proxy o un firewall, es posible que haya restricciones vigentes que impidan la comunicación desde el equipo de origen y el servicio Azure Monitor. En caso de que se bloquee la comunicación, debido a un error de configuración, se puede producir un error en el registro con un área de trabajo al intentar instalar el agente o configurarlo después de la instalación para que notifique a otra área de trabajo. Se puede producir un error de comunicación del agente después de un registro correcto. En esta sección se describen los métodos para solucionar este tipo de problema con el agente de Windows.

Compruebe que el firewall o proxy está configurado para permitir los puertos y las direcciones URL descritas en la tabla siguiente. Confirme también que la inspección HTTP no está habilitada para el tráfico web. Puede evitar un canal TLS seguro entre el agente y Azure Monitor.

Recurso del agente Puertos Dirección Omitir inspección de HTTPS
*.ods.opinsights.azure.com Puerto 443 Salida
*.oms.opinsights.azure.com Puerto 443 Salida
*.blob.core.windows.net Puerto 443 Salida
*.agentsvc.azure-automation.net Puerto 443 Salida

Para obtener información sobre el firewall necesaria para Azure Government, vea Administración de Azure Government. Si tiene previsto usar Hybrid Runbook Worker de Azure Automation para conectarse al servicio Automation y registrarse en él para usar runbooks o soluciones de administración en el entorno, debe tener acceso al número de puerto y las direcciones URL descritos en Configuración de la red para Hybrid Runbook Worker.

Hay varias formas de comprobar si el agente se comunica de forma correcta con Azure Monitor:

  • Habilite la Evaluación de estado del agente de Azure Log Analytics en el área de trabajo. En el panel de Agent Health, examine la columna Count of unresponsive agents (Número de agentes que no responden) para ver rápidamente si aparece el agente.

  • Ejecute la consulta siguiente para confirmar que el agente envía un latido al área de trabajo que se ha configurado para que le envíe notificaciones. Reemplace <ComputerName> con el nombre real del equipo.

    Heartbeat 
    | where Computer like "<ComputerName>"
    | summarize arg_max(TimeGenerated, * ) by Computer 
    

    Si el equipo se comunica correctamente con el servicio, la consulta debe devolver un resultado. Si la consulta no ha devuelto un resultado, compruebe primero que el agente está configurado para notificar al área de trabajo correcta. Si está configurado correctamente, vaya al paso 3 y busque en el registro de eventos de Windows para identificar si el agente registra el problema que podría estar impidiendo la comunicación con Azure Monitor.

  • Otro método para identificar un problema de conectividad consiste en ejecutar la herramienta TestCloudConnectivity. La herramienta se instala de forma predeterminada con el agente en la carpeta %SystemRoot%\Archivos de programa\Microsoft Monitoring Agent\Agent. Desde un símbolo del sistema con privilegios elevados, vaya a la carpeta y ejecute la herramienta. La herramienta devuelve los resultados y resalta dónde se produjo un error en la prueba. Por ejemplo, quizás estaba relacionado con un puerto o dirección URL determinado que se bloqueó.

    Screenshot that shows TestCloudConnection tool execution results.

  • Filtre el registro de eventos de Operations Manager por Orígenes de eventosMódulos de servicio de mantenimiento, HealthService y Conector de servicio, y fíltrelo por Nivel de eventoAdvertencia y Error para confirmar si ha escrito eventos de la tabla siguiente. Si se han escrito, revise los pasos de resolución incluidos para cada evento posible.

    Id. de evento Source Descripción Resolución
    2133 y 2129 Servicio de mantenimiento La conexión con el servicio desde el agente ha fallado. Este error se puede producir cuando el agente no se puede comunicar directamente o a través de un servidor proxy o firewall con el servicio Azure Monitor. Compruebe la configuración de proxy de agente o que el firewall o proxy de red permite el tráfico TCP desde el equipo al servicio.
    2138 Módulos de servicio de mantenimiento Se requiere autenticación del proxy. Configure las opciones del proxy de agente y especifique el nombre de usuario y la contraseña necesarios para autenticarse con el servidor proxy.
    2129 Módulos de servicio de mantenimiento Error de conexión. Error en la negociación de TLS. Compruebe la configuración TCP/IP del adaptador de red y del proxy de agente.
    2127 Módulos de servicio de mantenimiento Código de error recibido al fallar el envío de datos. Si solo se produce de forma periódica durante el día, podría ser una anomalía aleatoria que se puede ignorar. Supervise para comprender la frecuencia con que sucede. Si se produce con frecuencia a lo largo del día, compruebe la configuración de red y de proxy. Si en la descripción se incluye el código de error HTTP 404 y es la primera vez que el agente intenta enviar datos al servicio, incluirá un error 500 con un código de error 404 interno. El código de error 404 significa "no se ha encontrado", lo que indica que el área de almacenamiento para la nueva área de trabajo todavía se está aprovisionando. En el siguiente reintento, los datos se escribirán correctamente en el área de trabajo según lo previsto. Un error HTTP 403 podría indicar un problema de credenciales o permisos. El error 403 incluye más información para ayudar a solucionar el problema.
    4000 Conector de servicio Error en la resolución de nombres DNS. El equipo no pudo resolver la dirección de Internet que se ha usado al enviar datos al servicio. Esta incidencia podría deberse a la configuración de resolución DNS en el equipo, la configuración incorrecta del proxy o un problema de DNS temporal con el proveedor. Si se produce de forma periódica, se podría deber a un problema transitorio relacionado con la red.
    4001 Conector de servicio Error de conexión al servicio. Este error se puede producir cuando el agente no se puede comunicar directamente o a través de un servidor proxy o firewall con el servicio Azure Monitor. Compruebe la configuración de proxy de agente o que el firewall o proxy de red permite el tráfico TCP desde el equipo al servicio.
    4002 Conector de servicio El servicio ha devuelto el código de estado HTTP 403 en respuesta a una consulta. Póngase en contacto con el administrador de servicios para el estado del servicio. La consulta se reintentará más tarde. Este error se escribe durante la fase de registro inicial del agente. Verá una dirección URL similar a https://<workspaceID>.oms.opinsights.azure.com/AgentService.svc/AgentTopologyRequest. Un código de error 403 significa "prohibido" y puede deberse a un id. o clave del área de trabajo mal escritos. La fecha y hora también podrían ser incorrectas en el equipo. Si la hora es +/-15 minutos de la hora actual, se produce un error en la incorporación. Para corregir esta incidencia, actualice la fecha o la hora del equipo Windows.

Problemas recopilación de datos

Después de instalar el agente y de que notifique a sus áreas de trabajo configuradas, es posible que deje de recibir configuración o de recopilar o reenviar rendimiento, registros u otros datos para el servicio en función de lo que se haya habilitado y destinado al equipo. Debe determinar:

  • ¿En el área de trabajo no está disponible un tipo de datos determinado o se trata de todos los datos?
  • El tipo de datos lo especifica una solución o se especifica como parte de la configuración de recopilación de datos del área de trabajo.
  • Cuántos equipos se ven afectados. ¿Cuántos equipos notifican al área de trabajo? ¿Uno o varios?
  • Funcionaba y se ha detenido a una hora concreta del día o nunca se ha recopilado.
  • ¿La consulta de búsqueda de registros que está usando es sintácticamente correcta?
  • El agente ha recibido alguna vez su configuración de Azure Monitor.

El primer paso para solucionar problemas consiste en determinar si el equipo envía un evento de latido.

Heartbeat 
    | where Computer like "<ComputerName>"
    | summarize arg_max(TimeGenerated, * ) by Computer

Si la consulta devuelve resultados, tendrá que determinar si no se ha recopilado un tipo de datos determinado y se ha reenviado al servicio. La causa de esta incidencia podría ser que el agente no reciba la configuración actualizada desde el servicio, o bien algún otro síntoma que impida el funcionamiento normal del agente. Para solucionar problemas adicionales, realice los pasos siguientes.

  1. Abra un símbolo del sistema con privilegios elevados en el equipo y escriba net stop healthservice && net start healthservice para reiniciar el servicio del agente.

  2. Abra el registro de eventos de Operations Manager y busque los identificadores de evento7023, 7024, 7025, 7028 y 1210 en Event source (Origen de eventos) HealthService. Estos eventos indican que el agente recibe correctamente la configuración de Azure Monitor y que supervisan el equipo de forma activa. La descripción del evento con el identificador 1210 también especificará en la última línea todas las soluciones y la información que se incluyen en el ámbito de supervisión del agente.

    Screenshot that shows an Event ID 1210 description.

  3. Espere varios minutos. Si no ve los datos esperados en los resultados de la consulta o la visualización, en función de si los ve desde una solución o Insight, desde el registro de eventos de Operations Manager, busque Orígenes de eventosHealthService y Módulos de servicio de mantenimiento. Filtre por Nivel de eventoAdvertencia y Error para confirmar si ha escrito eventos de la tabla siguiente.

    Id. de evento Source Descripción Resolución
    8000 HealthService Este evento especificará si un flujo de trabajo relacionado con el rendimiento, los eventos u otro tipo de datos recopilado no puede reenviar al servicio para la ingesta en el área de trabajo. El id. de evento 2136 de la fuente HealthService se escribe junto con este evento y puede indicar que el agente no puede comunicarse con el servicio. Los posibles motivos pueden ser una configuración incorrecta de los valores de proxy y autenticación, la interrupción de red o que el firewall de red o el proxy no permiten el tráfico TCP desde el equipo al servicio.
    10102 y 10103 Módulos de servicio de mantenimiento El flujo de trabajo no pudo resolver el origen de datos. Esta incidencia puede ocurrir si el contador de rendimiento especificado o la instancia no existen en el equipo o se han definido incorrectamente en la configuración de datos del área de trabajo. Si se trata de un contador de rendimiento especificado por el usuario, compruebe que la información especificada sigue el formato correcto y que existe en los equipos de destino.
    26002 Módulos de servicio de mantenimiento El flujo de trabajo no pudo resolver el origen de datos. Esta incidencia puede ocurrir si el registro de eventos de Windows especificado no existe en el equipo. Este error se puede omitir de forma segura si no se espera que el equipo tenga registrado este registro de eventos. De lo contrario, si se trata de un registro de eventos especificado por el usuario, compruebe que la información especificada es correcta.

Problemas de certificado anclado con los agentes de supervisión de Microsoft anteriores: cambio importante

Introducción al cambio de entidad de certificación raíz

A partir del 30 de junio de 2023, el back-end de Log Analytics ya no aceptará conexiones de MMA que hagan referencia a un certificado raíz de salida. Estas MMA son versiones anteriores a la versión de invierno de 2020 (Agente de Log Analytics) y anteriores a SCOM 2019 UR3 (SCOM). Cualquier versión, Agrupación: 10.20.18053 / Extensión: 1.0.18053.0, o superior, no tendrá ningún problema, así como ninguna versión anterior a SCOM 2019 UR3. Cualquier agente anterior a eso se interrumpirá y dejará de funcionar y cargarlo en Log Analytics.

¿Qué cambia exactamente?

Como parte de un esfuerzo de seguridad continuo en varios servicios de Azure, Azure Log Analytics cambiará oficialmente de la certificación raíz de CA baltimore CyberTrust a la certificación raíz de CA digiCert Global G2. Este cambio afectará a las comunicaciones TLS con Log Analytics si falta el nuevo certificado raíz de CA global G2 de DigiCert en el sistema operativo o la aplicación hace referencia al antiguo certificado raíz de CA de Baltimore. Esto significa que Log Analytics ya no aceptará conexiones de MMA que usen este certificado raíz de CA antiguo después de retirarse.

Productos que pueden ser la solución

Es posible que haya recibido la notificación de cambio importante incluso si no ha instalado personalmente Microsoft Monitoring Agent. Esto se debe a que varios productos de Azure aprovechan Microsoft Monitoring Agent. Si usa uno de estos productos, es posible que se vea afectado a medida que aprovechan el agente de Log Analytics de Windows. Para esos productos con vínculos siguientes, puede haber instrucciones específicas que le requerirán actualizar al agente más reciente.

Identificación y reasignación de agentes importantes

En el caso de las implementaciones con un número limitado de agentes, se recomienda encarecidamente actualizar el agente por nodo mediante estas instrucciones de administración.

En el caso de las implementaciones con varios nodos, hemos escrito un script que detectará los MMA de interrupción afectados por suscripción y, a continuación, los actualizará a la versión más reciente. Estos scripts deben ejecutarse secuencialmente, empezando por UpdateMMA.ps1 UpgradeMMA.ps1. En función de la máquina, el script puede tardar un tiempo. Es necesario ejecutar PowerShell 7 o superior para evitar un tiempo de espera.

UpdateMMA.ps1 Este script pasará por las máquinas virtuales de las suscripciones, comprobará si hay MMA existentes instaladas y, a continuación, generará un archivo .csv de agentes que deben actualizarse.

UpgradeMMA.ps1 Este script usará el archivo .CSV generado en UpdateMMA.ps1 para actualizar todos los MMA importantes.

Ambos scripts pueden tardar un tiempo en completarse.

# UpdateMMA.ps1
# This script is to be run per subscription, the customer has to set the az subscription before running this within the terminal scope.
# This script uses parallel processing, modify the $parallelThrottleLimit parameter to either increase or decrease the number of parallel processes
# PS> .\UpdateMMA.ps1 GetInventory
# The above command will generate a csv file with the details of VM's and VMSS that require MMA upgrade. 
# The customer can modify the csv by adding/removing rows if needed
# Update the MMA by running the script again and passing the csv file as parameter as shown below:
# PS> .\UpdateMMA.ps1 Upgrade
# If you don't want to check the inventory, then run the script wiht an additional -no-inventory-check
# PS> .\UpdateMMA.ps1 GetInventory & .\UpdateMMA.ps1 Upgrade


# This version of the script requires Powershell version >= 7 in order to improve performance via ForEach-Object -Parallel
# https://docs.microsoft.com/powershell/scripting/whats-new/migrating-from-windows-powershell-51-to-powershell-7?view=powershell-7.1
if ($PSVersionTable.PSVersion.Major -lt 7) 
{
    Write-Host "This script requires Powershell version 7 or newer to run. Please see https://docs.microsoft.com/powershell/scripting/whats-new/migrating-from-windows-powershell-51-to-powershell-7?view=powershell-7.1."
    exit 1
}

$parallelThrottleLimit = 16
$mmaFixVersion = [version]"10.20.18053.0"

function GetVmsWithMMAInstalled
{
    param(
        $fileName
    )

    $vmList = az vm list --show-details --query "[?powerState=='VM running'].{ResourceGroup:resourceGroup, VmName:name}" | ConvertFrom-Json
    
    if(!$vmList)
    {
        Write-Host "Cannot get the VM list, this script can only detect the running VM's"
        return
    }

    $vmsCount = $vmList.Length
    
    $vmParallelThrottleLimit = $parallelThrottleLimit
    if ($vmsCount -lt $vmParallelThrottleLimit) 
    {
        $vmParallelThrottleLimit = $vmsCount
    }

    if($vmsCount -eq 1)
    {
        $vmGroups += ,($vmList[0])
    }
    else
    {
        # split the vm's into batches to do parallel processing
        for ($i = 0; $i -lt $vmsCount; $i += $vmParallelThrottleLimit) 
        { 
            $vmGroups += , ($vmList[$i..($i + $vmParallelThrottleLimit - 1)]) 
        }
    }

    Write-Host "Detected $vmsCount Vm's running in this subscription."
    $hash = [hashtable]::Synchronized(@{})
    $hash.One = 1

    $vmGroups | Foreach-Object -ThrottleLimit $parallelThrottleLimit -Parallel {
        $len = $using:vmsCount
        $hash = $using:hash
        $_ | ForEach-Object {
            $percent = 100 * $hash.One++ / $len
            Write-Progress -Activity "Getting VM Inventory" -PercentComplete $percent
            $vmName = $_.VmName
            $resourceGroup = $_.ResourceGroup
            $responseJson = az vm run-command invoke --command-id RunPowerShellScript --name $vmName -g $resourceGroup --scripts '@UpgradeMMA.ps1' --parameters "functionName=GetMMAVersion" --output json | ConvertFrom-Json
            if($responseJson)
            {
                $mmaVersion = $responseJson.Value[0].message
                if ($mmaVersion) 
                {
                    $extensionName = az vm extension list -g $resourceGroup --vm-name $vmName --query "[?name == 'MicrosoftMonitoringAgent'].name" | ConvertFrom-Json
                    if ($extensionName) 
                    {
                        $installType = "Extension"
                    }
                    else 
                    {
                        $installType = "Installer"
                    }
                    $csvObj = New-Object -TypeName PSObject -Property @{
                        'Name'           = $vmName
                        'Resource_Group' = $resourceGroup
                        'Resource_Type'  = "VM"
                        'Install_Type'   = $installType
                        'Version'        = $mmaVersion
                        "Instance_Id"    = ""
                    }
                    $csvObj | Export-Csv $using:fileName -Append -Force
                } 
            } 
        }
    }
}

function GetVmssWithMMAInstalled
{
    param(
        $fileName
    )

    # get the vmss list which are successfully provisioned
    $vmssList = az vmss list --query "[?provisioningState=='Succeeded'].{ResourceGroup:resourceGroup, VmssName:name}" | ConvertFrom-Json   

    $vmssCount = $vmssList.Length
    Write-Host "Detected $vmssCount Vmss running in this subscription."
    $hash = [hashtable]::Synchronized(@{})
    $hash.One = 1

    $vmssList | Foreach-Object -ThrottleLimit $parallelThrottleLimit -Parallel {
        $len = $using:vmssCount
        $hash = $using:hash
        $percent = 100 * $hash.One++ / $len
        Write-Progress -Activity "Getting VMSS Inventory" -PercentComplete $percent
        $vmssName = $_.VmssName
        $resourceGroup = $_.ResourceGroup

        # get running vmss instance ids
        $vmssInstanceIds = az vmss list-instances --resource-group $resourceGroup --name $vmssName --expand instanceView --query "[?instanceView.statuses[1].displayStatus=='VM running'].instanceId" | ConvertFrom-Json
        if ($vmssInstanceIds.Length -gt 0) 
        {
            $isMMAExtensionInstalled = az vmss extension list -g $resourceGroup --vmss-name $vmssName --query "[?name == 'MicrosoftMonitoringAgent'].name" | ConvertFrom-Json
            if ($isMMAExtensionInstalled ) 
            {
                # check an instance in vmss, if it needs an MMA upgrade. Since the extension is installed at VMSS level, checking for bad version in 1 instance should be fine.
                $responseJson = az vmss run-command invoke --command-id RunPowerShellScript --name $vmssName -g $resourceGroup --instance-id $vmssInstanceIds[0] --scripts '@UpgradeMMA.ps1' --parameters "functionName=GetMMAVersion" --output json | ConvertFrom-Json
                $mmaVersion = $responseJson.Value[0].message
                if ($mmaVersion) 
                {
                    $csvObj = New-Object -TypeName PSObject -Property @{
                        'Name'           = $vmssName
                        'Resource_Group' = $resourceGroup
                        'Resource_Type'  = "VMSS"
                        'Install_Type'   = "Extension"
                        'Version'        = $mmaVersion
                        "Instance_Id"    = ""
                    }
                    $csvObj | Export-Csv $using:fileName -Append -Force
                }
            }
            else 
            {
                foreach ($instanceId in $vmssInstanceIds) 
                {
                    $responseJson = az vmss run-command invoke --command-id RunPowerShellScript --name $vmssName -g $resourceGroup --instance-id $instanceId --scripts '@UpgradeMMA.ps1' --parameters "functionName=GetMMAVersion" --output json | ConvertFrom-Json
                    $mmaVersion = $responseJson.Value[0].message
                    if ($mmaVersion) 
                    {
                        $csvObj = New-Object -TypeName PSObject -Property @{
                            'Name'           = $vmssName
                            'Resource_Group' = $resourceGroup
                            'Resource_Type'  = "VMSS"
                            'Install_Type'   = "Installer"
                            'Version'        = $mmaVersion
                            "Instance_Id"    = $instanceId
                        }
                        $csvObj | Export-Csv $using:fileName -Append -Force
                    }
                }
            }
        }      
    }
}

function Upgrade
{
    param(
        $fileName = "MMAInventory.csv"
    )
    Import-Csv $fileName | ForEach-Object -ThrottleLimit $parallelThrottleLimit -Parallel {
        $mmaVersion = [version]$_.Version
        if($mmaVersion -lt $using:mmaFixVersion)
        {
            if ($_.Install_Type -eq "Extension") 
            {
                if ($_.Resource_Type -eq "VMSS") 
                {
                    # if the extension is installed with a custom name, provide the name using the flag: --extension-instance-name <extension name>
                    az vmss extension set --name MicrosoftMonitoringAgent --publisher Microsoft.EnterpriseCloud.Monitoring --force-update --vmss-name $_.Name --resource-group $_.Resource_Group --no-wait --output none
                }
                else 
                {
                    # if the extension is installed with a custom name, provide the name using the flag: --extension-instance-name <extension name>
                    az vm extension set --name MicrosoftMonitoringAgent --publisher Microsoft.EnterpriseCloud.Monitoring --force-update --vm-name $_.Name --resource-group $_.Resource_Group --no-wait --output none
                }
            }
            else {
                if ($_.Resource_Type -eq "VMSS") 
                {
                    az vmss run-command invoke --command-id RunPowerShellScript --name $_.Name -g $_.Resource_Group --instance-id $_.Instance_Id --scripts '@UpgradeMMA.ps1' --parameters "functionName=UpgradeMMA" --output none
                }
                else 
                {
                    az vm run-command invoke --command-id RunPowerShellScript --name $_.Name -g $_.Resource_Group --scripts '@UpgradeMMA.ps1' --parameters "functionName=UpgradeMMA" --output none
                }
            }
        }
    }
}

function GetInventory
{
    param(
        $fileName = "MMAInventory.csv"
    )

    # create a new file 
    New-Item -Name $fileName -ItemType File -Force
    GetVmsWithMMAInstalled $fileName
    GetVmssWithMMAInstalled $fileName
}

switch ($args.Count)
{
    0 {
        Write-Host "The arguments provided are incorrect."
        Write-Host "To get the Inventory: Run the script as: PS> .\UpdateMMA.ps1 GetInventory"
        Write-Host "To update MMA from Inventory: Run the script as: PS> .\UpdateMMA.ps1 Upgrade"
        Write-Host "To do the both steps together: PS> .\UpdateMMA.ps1 GetInventory & .\UpdateMMA.ps1 Upgrade"
    }
    1 {
        $funcname = $args[0]
        Invoke-Expression "& $funcname"
    }
    2 {
        $funcname = $args[0]
        $funcargs = $args[1]
        Invoke-Expression "& $funcname $funcargs"
    }
}