Felsöka problem med Log Analytics-agenten för Windows

Den här artikeln innehåller hjälp med felsökningsfel som kan uppstå med Log Analytics-agenten för Windows i Azure Monitor och föreslår möjliga lösningar för att lösa dem.

Felsökningsverktyg för Log Analytics

Log Analytics-agenten för Windows-felsökningsverktyget är en samling PowerShell-skript som är utformade för att hjälpa dig att hitta och diagnostisera problem med Log Analytics-agenten. Den ingår automatiskt i agenten vid installationen. Att köra verktyget bör vara det första steget för att diagnostisera ett problem.

Använda felsökningsverktyget

  1. Öppna PowerShell-prompten som administratör på den dator där Log Analytics-agenten är installerad.

  2. Gå till katalogen där verktyget finns:

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

  3. Kör huvudskriptet med hjälp av det här kommandot:

    .\GetAgentInfo.ps1

  4. Välj ett felsökningsscenario.

  5. Följ anvisningarna i konsolen. Observera att spårningsloggar kräver manuella åtgärder för att stoppa logginsamlingen. Baserat på problemets reproducerbarhet väntar du på varaktigheten och väljer "s" för att stoppa loggsamlingen och fortsätter till nästa steg.

    Platsen för resultatfilen loggas när den är klar och ett nytt utforskarfönster som markerar den öppnas.

Installation

Felsökningsverktyget ingår automatiskt vid installationen av Log Analytics Agent-versionen 10.20.18053.0 och senare.

Scenarier som omfattas

Felsökningsverktyget kontrollerar följande scenarier:

  • Agenten rapporterar inte data eller så saknas pulsslagsdata.
  • Distributionen av agenttillägget misslyckas.
  • Agenten kraschar.
  • Agenten förbrukar hög CPU eller minne.
  • Fel vid installation och avinstallation.
  • Anpassade loggar har problem.
  • OMS Gateway har problem.
  • Prestandaräknare har problem.
  • Det går inte att samla in agentloggar.

Kommentar

Kör felsökningsverktyget när du får ett problem. Om du har loggarna från början kan supportteamet felsöka problemet snabbare.

Viktiga felsökningskällor

För att hjälpa till med felsökningsproblem relaterade till Log Analytics-agenten för Windows loggar agenten händelser till Windows-händelseloggen, särskilt under Program och tjänster\Operations Manager.

Anslutningsproblem

Om agenten kommunicerar via en proxyserver eller brandvägg kan det finnas begränsningar som förhindrar kommunikation från källdatorn och Azure Monitor-tjänsten. Om kommunikationen blockeras på grund av felkonfiguration kan registreringen med en arbetsyta misslyckas vid försök att installera agenten eller konfigurera agenten efter installationen så att den rapporterar till en annan arbetsyta. Agentkommunikationen kan misslyckas efter lyckad registrering. I det här avsnittet beskrivs metoderna för att felsöka den här typen av problem med Windows-agenten.

Kontrollera att brandväggen eller proxyn är konfigurerad för att tillåta följande portar och URL:er som beskrivs i följande tabell. Bekräfta också att HTTP-inspektionen inte är aktiverad för webbtrafik. Det kan förhindra en säker TLS-kanal mellan agenten och Azure Monitor.

Agentresurs Portar Riktning Kringgå HTTPS-inspektion
*.ods.opinsights.azure.com Port 443 Utgående Ja
*.oms.opinsights.azure.com Port 443 Utgående Ja
*.blob.core.windows.net Port 443 Utgående Ja
*.agentsvc.azure-automation.net Port 443 Utgående Ja

Brandväggsinformation som krävs för Azure Government finns i Azure Government-hantering. Om du planerar att använda Azure Automation Hybrid Runbook Worker för att ansluta till och registrera dig med Automation-tjänsten för att använda runbooks eller hanteringslösningar i din miljö måste den ha åtkomst till portnumret och url:erna som beskrivs i Konfigurera nätverket för Hybrid Runbook Worker.

Det finns flera sätt att kontrollera om agenten kommunicerar med Azure Monitor:

  • Aktivera Azure Log Analytics Agent Health-utvärderingen på arbetsytan. Från instrumentpanelen För agenthälsa visar du kolumnen Antal agenter som inte svarar för att snabbt se om agenten visas.

  • Kör följande fråga för att bekräfta att agenten skickar ett pulsslag till den arbetsyta som den är konfigurerad att rapportera till. Ersätt <ComputerName> med datorns faktiska namn.

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

    Om datorn kommunicerar med tjänsten bör frågan returnera ett resultat. Om frågan inte returnerade något resultat kontrollerar du först att agenten är konfigurerad för att rapportera till rätt arbetsyta. Om den är korrekt konfigurerad fortsätter du till steg 3 och söker i Windows-händelseloggen för att se om agenten loggar problemet som kan hindra den från att kommunicera med Azure Monitor.

  • En annan metod för att identifiera ett anslutningsproblem är genom att köra verktyget TestCloud Anslut ivity. Verktyget installeras som standard med agenten i mappen %SystemRoot%\Program Files\Microsoft Monitoring Agent\Agent. Från en upphöjd kommandotolk går du till mappen och kör verktyget. Verktyget returnerar resultatet och markerar var testet misslyckades. Till exempel kanske det var relaterat till en viss port eller URL som blockerades.

    Screenshot that shows TestCloudConnection tool execution results.

  • Filtrera Operations Manager-händelseloggen efter händelsekällor Hälsotjänst moduler, hälsotjänst och tjänst Anslut eller och filtrera efter varning och fel på händelsenivå för att bekräfta om den har skrivit händelser från följande tabell. Om så är fallet granskar du de lösningssteg som ingår för varje möjlig händelse.

    Händelse-ID Source beskrivning Åtgärd
    2133 & 2129 Hälsotjänst Anslut till tjänsten från agenten misslyckades. Det här felet kan inträffa när agenten inte kan kommunicera direkt eller via en brandvägg eller proxyserver till Azure Monitor-tjänsten. Kontrollera proxyinställningarna för agenten eller att nätverksbrandväggen eller proxyn tillåter TCP-trafik från datorn till tjänsten.
    2138 Hälsotjänst moduler Proxy kräver autentisering. Konfigurera proxyinställningarna för agenten och ange det användarnamn/lösenord som krävs för att autentisera med proxyservern.
    2129 Hälsotjänst moduler Anslutningen misslyckades. TLS-förhandling misslyckades. Kontrollera TCP/IP-inställningar för nätverkskort och proxyinställningar för agenten.
    2127 Hälsotjänst moduler Det gick inte att skicka data mottagen felkod. Om det bara sker regelbundet under dagen kan det vara en slumpmässig avvikelse som kan ignoreras. Övervaka för att förstå hur ofta det händer. Om det händer ofta under dagen kontrollerar du först nätverkskonfigurationen och proxyinställningarna. Om beskrivningen innehåller HTTP-felkod 404 och det är första gången agenten försöker skicka data till tjänsten, innehåller den ett 500-fel med en inre 404-felkod. 404-felkoden betyder "hittades inte", vilket anger att lagringsområdet för den nya arbetsytan fortfarande etableras. Vid nästa återförsök skrivs data till arbetsytan som förväntat. Ett HTTP-fel 403 kan tyda på ett problem med behörighet eller autentiseringsuppgifter. Mer information ingår i 403-felet för att felsöka problemet.
    4000 Tjänstanslutning DNS-namnmatchningen misslyckades. Datorn kunde inte matcha den Internetadress som användes när den skickade data till tjänsten. Det här problemet kan vara DNS-matchningsinställningar på datorn, felaktiga proxyinställningar eller ett tillfälligt DNS-problem med din provider. Om det sker regelbundet kan det orsakas av ett tillfälligt nätverksrelaterat problem.
    4001 Tjänstanslutning Anslut till tjänsten misslyckades. Det här felet kan inträffa när agenten inte kan kommunicera direkt eller via en brandvägg eller proxyserver till Azure Monitor-tjänsten. Kontrollera proxyinställningarna för agenten eller att nätverksbrandväggen eller proxyn tillåter TCP-trafik från datorn till tjänsten.
    4002 Tjänstanslutning Tjänsten returnerade HTTP-statuskod 403 som svar på en fråga. Kontakta tjänstadministratören om tjänstens hälsotillstånd. Frågan kommer att försöka igen senare. Det här felet skrivs under agentens inledande registreringsfas. Du ser en URL som liknar https:// workspaceID.oms.opinsights.azure.com/AgentService.svc/AgentTopologyRequest>.< En 403-felkod betyder "förbjuden" och kan orsakas av ett feltypat arbetsyte-ID eller nyckel. Datum och tid kan också vara felaktiga på datorn. Om tiden är +/- 15 minuter från aktuell tid misslyckas registreringen. Åtgärda problemet genom att uppdatera datum och/eller tid för din Windows-dator.

Problem med datainsamling

När agenten har installerats och rapporterar till sin konfigurerade arbetsyta eller arbetsytor kan den sluta ta emot konfiguration och samla in eller vidarebefordra prestanda, loggar eller andra data till tjänsten beroende på vad som är aktiverat och riktat mot datorn. Du måste fastställa följande:

  • Är det en viss datatyp eller alla data som inte är tillgängliga på arbetsytan?
  • Anges datatypen av en lösning eller anges den som en del av konfigurationen av datainsamlingen för arbetsytan?
  • Hur många datorer påverkas? Är det en enda dator eller flera datorer som rapporterar till arbetsytan?
  • Fungerade det och slutade det vid en viss tidpunkt på dagen, eller har det aldrig samlats in?
  • Är loggsökningsfrågan som du använder syntaktiskt korrekt?
  • Har agenten någonsin fått sin konfiguration från Azure Monitor?

Det första steget i felsökningen är att avgöra om datorn skickar en pulsslagshändelse.

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

Om frågan returnerar resultat måste du avgöra om en viss datatyp inte samlas in och vidarebefordras till tjänsten. Det här problemet kan orsakas av att agenten inte tar emot uppdaterad konfiguration från tjänsten eller något annat symptom som hindrar agenten från att fungera normalt. Utför följande steg för att ytterligare felsöka.

  1. Öppna en upphöjd kommandotolk på datorn och starta om agenttjänsten genom att ange net stop healthservice && net start healthservice.

  2. Öppna Operations Manager-händelseloggen och sök efter händelse-ID:t7023, 7024, 7025, 7028 och 1210 från Event SourceHealthService. Dessa händelser indikerar att agenten tar emot konfigurationen från Azure Monitor och att de aktivt övervakar datorn. Händelsebeskrivningen för händelse-ID 1210 anger också på den sista raden alla lösningar och insikter som ingår i övervakningsomfånget för agenten.

    Screenshot that shows an Event ID 1210 description.

  3. Vänta några minuter. Om du inte ser förväntade data i frågeresultatet eller visualiseringen, beroende på om du visar data från en lösning eller Insight, från Operations Manager-händelseloggen, söker du efter HändelsekällorHealthService och Hälsotjänst Moduler. Filtrera efter varning och fel på händelsenivå för att bekräfta om det har skrivit händelser från följande tabell.

    Händelse-ID Source beskrivning Åtgärd
    8000 HealthService Den här händelsen anger om ett arbetsflöde som rör prestanda, händelse eller annan datatyp som samlas in inte kan vidarebefordras till tjänsten för inmatning till arbetsytan. Händelse-ID 2136 från källan HealthService skrivs tillsammans med den här händelsen och kan indikera att agenten inte kan kommunicera med tjänsten. Möjliga orsaker kan vara felkonfiguration av proxy- och autentiseringsinställningarna, nätverksavbrott eller att nätverksbrandväggen eller proxyn inte tillåter TCP-trafik från datorn till tjänsten.
    10102 och 10103 Hälsotjänst moduler Arbetsflödet kunde inte matcha datakällan. Det här problemet kan inträffa om den angivna prestandaräknaren eller instansen inte finns på datorn eller är felaktigt definierad i arbetsytans datainställningar. Om det här är en användardefinerad prestandaräknare kontrollerar du att den angivna informationen följer rätt format och finns på måldatorerna.
    26002 Hälsotjänst moduler Arbetsflödet kunde inte matcha datakällan. Det här problemet kan inträffa om den angivna Windows-händelseloggen inte finns på datorn. Det här felet kan ignoreras på ett säkert sätt om datorn inte förväntas ha den här händelseloggen registrerad. Om det här är en användarspecifik händelselogg kontrollerar du annars att den angivna informationen är korrekt.

Problem med fästa certifikat med äldre Microsoft-övervakningsagenter – icke-bakåtkompatibel ändring

Översikt över rotcertifikatutfärdarändring

Från och med den 30 juni 2023 accepterar Log Analytics-serverdelen inte längre anslutningar från MMA som refererar till ett outdate-rotcertifikat. Dessa MMA:er är äldre versioner före versionen av Winter 2020 (Log Analytics Agent) och före SCOM 2019 UR3 (SCOM). Alla versioner, Bundle: 10.20.18053 /Extension: 1.0.18053.0, eller senare, har inga problem, samt någon version över SCOM 2019 UR3. Alla agenter som är äldre än den kommer att brytas och inte längre fungerar och laddas upp till Log Analytics.

Vad exakt förändras?

Som en del av en pågående säkerhetsinsats för olika Azure-tjänster kommer Azure Log Analytics officiellt att byta från Baltimore CyberTrust CA Root till DigiCert Global G2 CA Root. Den här ändringen påverkar TLS-kommunikationen med Log Analytics om det nya Rotcertifikatutfärdarcertifikatet DigiCert Global G2 saknas i operativsystemet, eller om programmet refererar till den gamla Baltimore Root CA. Det innebär att Log Analytics inte längre accepterar anslutningar från MMA som använder den här gamla rotcertifikatutfärdare när den har dragits tillbaka.

Lösningsprodukter

Du kan ha fått meddelandet om icke-bakåtkompatibel ändring även om du inte har installerat Microsoft Monitoring Agent personligen. Det beror på att olika Azure-produkter utnyttjar Microsoft Monitoring Agent. Om du använder någon av dessa produkter kan du påverkas när de använder Windows Log Analytics-agenten. För dessa produkter med länkar nedan kan det finnas specifika instruktioner som kräver att du uppgraderar till den senaste agenten.

Identifiera och återskapa icke-bakåtkompatibla agenter

För distributioner med ett begränsat antal agenter rekommenderar vi starkt att du uppgraderar din agent per nod via dessa hanteringsinstruktioner.

För distributioner med flera noder har vi skrivit ett skript som identifierar eventuella berörda icke-bakåtkompatibla MMA:er per prenumeration och sedan uppgraderar dem till den senaste versionen. Dessa skript måste köras sekventiellt, från och med UpdateMMA.ps1 och sedan UpgradeMMA.ps1. Beroende på datorn kan skriptet ta en stund. PowerShell 7 eller senare krävs för att köras för att undvika en timeout.

UpdateMMA.ps1 Det här skriptet går igenom virtuella datorer i dina prenumerationer, söker efter befintliga MMA:er installerade och genererar sedan en .csv-fil med agenter som behöver uppgraderas.

UpgradeMMA.ps1 Det här skriptet använder . CSV-fil som genereras i UpdateMMA.ps1 för att uppgradera alla icke-bakåtkompatibla MMA:er.

Båda dessa skript kan ta ett tag att slutföra.

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