Partilhar via


Resolver problemas com o agente do Log Analytics para Windows

Este artigo fornece ajuda na solução de erros que você pode enfrentar com o agente do Log Analytics para Windows no Azure Monitor e sugere possíveis soluções para resolvê-los.

Ferramenta de solução de problemas do Log Analytics

O agente do Log Analytics para a Ferramenta de Solução de Problemas do Windows é uma coleção de scripts do PowerShell projetados para ajudar a localizar e diagnosticar problemas com o agente do Log Analytics. Ele é incluído automaticamente com o agente após a instalação. Executar a ferramenta deve ser o primeiro passo para diagnosticar um problema.

Usar a ferramenta de solução de problemas

  1. Abra o prompt do PowerShell como administrador na máquina em que o agente do Log Analytics está instalado.

  2. Vá para o diretório onde a ferramenta está localizada:

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

  3. Execute o script principal usando este comando:

    .\GetAgentInfo.ps1

  4. Selecione um cenário de solução de problemas.

  5. Siga as instruções no console. Observe que as etapas de logs de rastreamento exigem intervenção manual para interromper a coleta de logs. Com base na reprodutibilidade do problema, aguarde a duração do tempo e selecione "s" para interromper a coleta de logs e prosseguir para a próxima etapa.

    O local do arquivo de resultados é registrado após a conclusão e uma nova janela do explorador destacando-o é aberta.

Instalação

A Ferramenta de Solução de Problemas é incluída automaticamente após a instalação da compilação 10.20.18053.0 do Log Analytics Agent e posteriores.

Cenários abrangidos

A Ferramenta de Solução de Problemas verifica os seguintes cenários:

  • O agente não está relatando dados ou dados de pulsação estão faltando.
  • A implantação da extensão do agente está falhando.
  • O agente está falhando.
  • O agente está consumindo alta CPU ou memória.
  • Falhas na experiência de instalação e desinstalação.
  • Os logs personalizados têm problemas.
  • O OMS Gateway tem problemas.
  • Os contadores de desempenho têm problemas.
  • Os logs do agente não podem ser coletados.

Nota

Execute a Ferramenta de Solução de Problemas quando tiver um problema. Ter os logs inicialmente ajudará nossa equipe de suporte a solucionar seu problema mais rapidamente.

Fontes importantes de solução de problemas

Para ajudar na solução de problemas relacionados ao agente do Log Analytics para Windows, o agente registra eventos no Log de Eventos do Windows, especificamente em Aplicativo e Serviços\Operations Manager.

Problemas de conectividade

Se o agente estiver se comunicando por meio de um servidor proxy ou firewall, poderão existir restrições que impeçam a comunicação do computador de origem e do serviço Azure Monitor. Se a comunicação for bloqueada devido a uma configuração incorreta, o registro em um espaço de trabalho poderá falhar ao tentar instalar o agente ou configurar o agente pós-instalação para relatar a outro espaço de trabalho. A comunicação do agente pode falhar após o registro bem-sucedido. Esta seção descreve os métodos para solucionar esse tipo de problema com o agente do Windows.

Verifique se o firewall ou proxy está configurado para permitir as seguintes portas e URLs descritas na tabela a seguir. Confirme também se a inspeção HTTP não está habilitada para o tráfego da Web. Ele pode impedir um canal TLS seguro entre o agente e o Azure Monitor.

Recursos do agente Portas Direção Inspeção de HTTPS direto
*.ods.opinsights.azure.com Porta 443 De Saída Sim
*.oms.opinsights.azure.com Porta 443 De Saída Sim
*.blob.core.windows.net Porta 443 De Saída Sim
*.agentsvc.azure-automation.net Porta 443 De Saída Sim

Para obter as informações de firewall necessárias para o Azure Government, consulte Azure Government management. Se você planeja usar o Azure Automation Hybrid Runbook Worker para se conectar e se registrar no serviço de Automação para usar runbooks ou soluções de gerenciamento em seu ambiente, ele deve ter acesso ao número da porta e às URLs descritas em Configurar sua rede para o Runbook Worker Híbrido.

Há várias maneiras de verificar se o agente está se comunicando com êxito com o Azure Monitor:

  • Habilite a avaliação de integridade do agente do Azure Log Analytics no espaço de trabalho. No painel Integridade do agente, exiba a coluna Contagem de agentes que não respondem para ver rapidamente se o agente está listado.

  • Execute a consulta a seguir para confirmar que o agente está enviando uma pulsação para o espaço de trabalho para o qual está configurado para reportar. Substitua <ComputerName> pelo nome real da máquina.

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

    Se o computador estiver se comunicando com êxito com o serviço, a consulta deverá retornar um resultado. Se a consulta não retornou um resultado, primeiro verifique se o agente está configurado para relatar para o espaço de trabalho correto. Se estiver configurado corretamente, avance para o passo 3 e pesquise o Registo de Eventos do Windows para identificar se o agente está a registar o problema que pode estar a impedi-lo de comunicar com o Azure Monitor.

  • Outro método para identificar um problema de conectividade é executando a ferramenta TestCloudConnectivity . A ferramenta é instalada por padrão com o agente na pasta %SystemRoot%\Program Files\Microsoft Monitoring Agent\Agent. Em um prompt de comando elevado, vá para a pasta e execute a ferramenta. A ferramenta devolve os resultados e realça onde o teste falhou. Por exemplo, talvez estivesse relacionado a uma determinada porta ou URL que foi bloqueada.

    Captura de tela que mostra os resultados de execução da ferramenta TestCloudConnection.

  • Filtre o log de eventos do Operations Manager por Módulos de Serviço de Integridade, HealthService e Service Connector de fontes de eventos e filtre por Aviso e Erro de Nível de Evento para confirmar se ele gravou eventos da tabela a seguir. Se estiverem, revise as etapas de resolução incluídas para cada evento possível.

    ID do Evento Origem Description Resolução
    2133 & 2129 Serviço de Estado de Funcionamento Falha na conexão com o serviço do agente. Esse erro pode ocorrer quando o agente não pode se comunicar diretamente ou por meio de um firewall ou servidor proxy para o serviço Azure Monitor. Verifique as configurações de proxy do agente ou se o firewall ou proxy de rede permite o tráfego TCP do computador para o serviço.
    2138 Módulos de serviço de integridade O proxy requer autenticação. Configure as configurações de proxy do agente e especifique o nome de usuário/senha necessário para autenticar com o servidor proxy.
    2129 Módulos de serviço de integridade Falha na conexão. Falha na negociação TLS. Verifique as configurações de TCP/IP do adaptador de rede e as configurações de proxy do agente.
    2127 Módulos de serviço de integridade Falha no envio de dados recebidos código de erro. Se acontecer apenas periodicamente durante o dia, pode ser uma anomalia aleatória que pode ser ignorada. Monitore para entender com que frequência isso acontece. Se isso acontecer com frequência ao longo do dia, primeiro verifique a configuração da rede e as configurações de proxy. Se a descrição incluir o código de erro HTTP 404 e for a primeira vez que o agente tentar enviar dados para o serviço, incluirá um erro 500 com um código de erro 404 interno. O código de erro 404 significa "não encontrado", o que indica que a área de armazenamento para o novo espaço de trabalho ainda está sendo provisionada. Na próxima nova tentativa, os dados serão gravados com êxito no espaço de trabalho, conforme o esperado. Um erro HTTP 403 pode indicar um problema de permissão ou credenciais. Mais informações estão incluídas com o erro 403 para ajudar a solucionar o problema.
    4000 Conector do Serviço Falha na resolução de nomes DNS. A máquina não conseguiu resolver o endereço de internet usado quando enviou dados para o serviço. Esse problema pode ser configurações de resolvedor de DNS em sua máquina, configurações de proxy incorretas ou um problema temporário de DNS com seu provedor. Se isso acontecer periodicamente, pode ser causado por um problema transitório relacionado à rede.
    4001 Conector do Serviço Falha na conexão com o serviço. Esse erro pode ocorrer quando o agente não pode se comunicar diretamente ou por meio de um firewall ou servidor proxy para o serviço Azure Monitor. Verifique as configurações de proxy do agente ou se o firewall ou proxy de rede permite o tráfego TCP do computador para o serviço.
    4002 Conector do Serviço O serviço retornou o código de status HTTP 403 em resposta a uma consulta. Verifique com o administrador do serviço a integridade do serviço. A consulta será repetida mais tarde. Este erro é escrito durante a fase inicial de registro do agente. Você verá um URL semelhante a https:// workspaceID.oms.opinsights.azure.com/AgentService.svc/AgentTopologyRequest><. Um código de erro 403 significa "proibido" e pode ser causado por um ID ou chave do espaço de trabalho digitado incorretamente. A data e a hora também podem estar incorretas no computador. Se o tempo for +/- 15 minutos da hora atual, a integração falhará. Para corrigir esse problema, atualize a data e/ou hora do seu computador Windows.

Questões relacionadas com a recolha de dados

Depois que o agente é instalado e relata para seu espaço de trabalho configurado ou espaços de trabalho, ele pode parar de receber configuração e coletar ou encaminhar desempenho, logs ou outros dados para o serviço, dependendo do que está habilitado e direcionado ao computador. Você precisa determinar:

  • É um tipo de dados específico ou todos os dados que não estão disponíveis no espaço de trabalho?
  • O tipo de dados é especificado por uma solução ou especificado como parte da configuração de coleta de dados do espaço de trabalho?
  • Quantos computadores são afetados? É um único computador ou vários computadores que se reportam ao espaço de trabalho?
  • Estava a funcionar e parou a uma determinada hora do dia, ou nunca foi recolhido?
  • A consulta de pesquisa de log que você está usando está sintaticamente correta?
  • O agente já recebeu sua configuração do Azure Monitor?

A primeira etapa na solução de problemas é determinar se o computador está enviando um evento de pulsação.

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

Se a consulta retornar resultados, você precisará determinar se um determinado tipo de dados não é coletado e encaminhado para o serviço. Esse problema pode ser causado pelo agente não receber a configuração atualizada do serviço ou algum outro sintoma que impede o agente de operar normalmente. Execute as etapas a seguir para solucionar problemas adicionais.

  1. Abra um prompt de comando elevado no computador e reinicie o serviço do agente digitando net stop healthservice && net start healthservice.

  2. Abra o log de eventos do Operations Manager e procure as IDs de evento 7023, 7024, 7025, 7028 e 1210 do HealthService da fonte de eventos. Esses eventos indicam que o agente está recebendo com êxito a configuração do Azure Monitor e está monitorando ativamente o computador. A descrição do evento para o ID de evento 1210 também especificará na última linha todas as soluções e Insights incluídos no escopo do monitoramento no agente.

    Captura de ecrã que mostra uma descrição do ID de Evento 1210.

  3. Aguarde alguns minutos. Se você não vir os dados esperados nos resultados da consulta ou na visualização, dependendo se estiver exibindo os dados de uma solução ou Insight, no log de eventos do Operations Manager, procure por Fontes de eventos HealthService e Health Service Modules. Filtre por Aviso e Erro de Nível de Evento para confirmar se gravou eventos da tabela a seguir.

    ID do Evento Origem Description Resolução
    8000 HealthService Esse evento especificará se um fluxo de trabalho relacionado ao desempenho, evento ou outro tipo de dados coletados não pode ser encaminhado para o serviço para ingestão no espaço de trabalho. A ID de evento 2136 do HealthService de origem é gravada junto com esse evento e pode indicar que o agente não consegue se comunicar com o serviço. Possíveis razões podem ser a configuração incorreta das configurações de proxy e autenticação, interrupção de rede ou o firewall de rede ou proxy não permite tráfego TCP do computador para o serviço.
    10102 e 10103 Módulos de serviço de integridade O fluxo de trabalho não pôde resolver a fonte de dados. Esse problema pode ocorrer se o contador de desempenho especificado ou instância não existe no computador ou está incorretamente definido nas configurações de dados do espaço de trabalho. Se este for um contador de desempenho especificado pelo usuário, verifique se as informações especificadas seguem o formato correto e existem nos computadores de destino.
    26002 Módulos de serviço de integridade O fluxo de trabalho não pôde resolver a fonte de dados. Esse problema pode ocorrer se o log de eventos do Windows especificado não existir no computador. Este erro pode ser ignorado com segurança se não se espera que o computador tenha este registo de eventos registado. Caso contrário, se este for um log de eventos especificado pelo usuário, verifique se as informações especificadas estão corretas.

Problemas de certificado fixo com agentes de monitoramento da Microsoft mais antigos - Alterações recentes

Visão geral da alteração da autoridade de certificação raiz

A partir de 30 de junho de 2023, o back-end do Log Analytics não aceitará mais conexões do MMA que façam referência a um certificado raiz desatualizado. Esses MMAs são versões mais antigas anteriores à versão de inverno de 2020 (Log Analytics Agent) e anteriores ao SCOM 2019 UR3 (SCOM). Qualquer versão, Pacote: 10.20.18053 / Extensão: 1.0.18053.0, ou superior não terá problemas, bem como qualquer versão acima do SCOM 2019 UR3. Qualquer agente mais antigo do que isso quebrará e não estará mais trabalhando e carregando para o Log Analytics.

O que exatamente está mudando?

Como parte de um esforço de segurança contínuo em vários serviços do Azure, o Azure Log Analytics mudará oficialmente da Raiz da CA do Baltimore CyberTrust para a Raiz da CA G2 Global da DigiCert. Essa alteração afetará as comunicações TLS com o Log Analytics se o novo certificado Raiz da CA DigiCert Global G2 estiver ausente do sistema operacional ou se o aplicativo estiver fazendo referência à antiga CA raiz de Baltimore. Isso significa que o Log Analytics não aceitará mais conexões do MMA que usam essa antiga autoridade de certificação raiz depois que ela for aposentada.

Produtos da solução

Você pode ter recebido a notificação de alteração de quebra mesmo se você não tiver instalado pessoalmente o Microsoft Monitoring Agent. Isso ocorre porque vários produtos do Azure aproveitam o Microsoft Monitoring Agent. Se estiver a utilizar um destes produtos, poderá ser afetado à medida que estes aproveitam o Agente do Windows Log Analytics. Para os produtos com links abaixo, pode haver instruções específicas que exigirão que você atualize para o agente mais recente.

Identificação e Remidiação de Agentes de Quebra

Para implantações com um número limitado de agentes, é altamente recomendável atualizar seu agente por nó por meio destas instruções de gerenciamento.

Para implantações com vários nós, escrevemos um script que detetará quaisquer MMAs afetados por assinatura e, posteriormente, os atualizará para a versão mais recente. Esses scripts precisam ser executados sequencialmente, começando com UpdateMMA.ps1 e depois UpgradeMMA.ps1. Dependendo da máquina, o script pode demorar um pouco. O PowerShell 7 ou superior é necessário para ser executado para evitar um tempo limite.

UpdateMMA.ps1 Este script passará por VMs em suas assinaturas, verificará se há MMAs existentes instalados e, em seguida, gerará um arquivo .csv de agentes que precisam ser atualizados.

UpgradeMMA.ps1 Este script usará o . CSV gerado em UpdateMMA.ps1 para atualizar todos os MMAs de quebra.

Ambos os scripts podem demorar um pouco para serem concluídos.

# 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"
    }
}