NewRelic.Agents.DotNet.psm1

Using module '.\NewRelic.Agents.psm1'
Using module '.\NewRelic.Download.psm1'
Using module '.\NewRelic.Configuration.psm1'

<#
.Synopsis
    Installs the New Relic .Net Agent
.Description
    Installs the New Relic .Net Agent
.Example
    Install-NRDotNetAgent -LicenseKey <LicenseKey>
    Installs, licenses and starts the New Relic .Net agent
.Example
    Install-NRDotNetAgent -LicenseKey <LicenseKey> -Version '10.27.0'
    Installs, licenses and starts the New Relic .Net agent version 10.27.0
.Parameter LicenseKey
    New Relic License Key that links the agent to the account
.Parameter Version
    If provided, attempts to install a specific version of the agent otherwise falls back to the default managed by New Relic
.Parameter InstrumentAll
    Installs for non IIS apps to be instrumented like windows services
#>

Function Install-NRDotNetAgent {
    [CMDLetBinding()]
    Param (
        [Parameter (Mandatory = $true)]
        [string] $LicenseKey,
        [Parameter (Mandatory = $false)]
        [string] $Version = '',
        [Parameter (Mandatory = $false)]
        [switch] $InstrumentAll
    )
    # Must run as an admin to install and start the service...
    Confirm-RunAsAdmin | Out-Null

    if ($Version -ne '') {
        Write-Output "Using Version: $Version"
        $AgentRootURL = "https://download.newrelic.com/dot_net_agent/previous_releases/$Version/"
        $AgentName = "NewRelicDotNetAgent_$Version`_x64.msi"
    }
    else {
        # Use Default version updated by New Relic
        $AgentRootURL = 'https://download.newrelic.com/dot_net_agent/latest_release/'
        $AgentName = 'NewRelicDotNetAgent_x64.msi'
    }

    $localPath = Get-TempDownload -DownloadURL "$AgentRootURL$AgentName" -FileName $AgentName

    # Install and Wait
    Write-Output "Installing Agent: $AgentName"
    if ($InstrumentAll) {
        $arguments = "/qn /i $localPath NR_LICENSE_KEY=$LicenseKey INSTALLLEVEL=50"
    }
    else {
        $arguments = "/qn /i $localPath NR_LICENSE_KEY=$LicenseKey INSTALLLEVEL=1"
    }
    Start-Process 'C:\Windows\System32\msiexec.exe' -ArgumentList $arguments -wait

    # Remove Temp Agent File
    Write-Output "Cleaning up Agent Files: $localPath"
    Remove-Item $localPath -Force

    # Write output when finished
    Write-Output 'Finished Install'
}

<#
.Synopsis
    Gets details on the New Relic .Net agent running on the machine.
.Description
    Gets details on the New Relic .Net agent running on the machine.
.Example
    Get-NRDotNetAgent
    Returns details on the .Net agent
#>

Function Get-NRDotNetAgent {
    [CMDLetBinding()]
    Param (
    )
    $agentDetails = Get-InstalledSoftwareFromRegistry -Name 'New Relic .NET Agent*'

    # Validate Agent is present
    if ($null -eq $agentDetails) {
        Throw "DotNet Agent installation not found"
    }

    return [PSCustomObject]@{
        Name    = $agentDetails.DisplayName
        Version = $agentDetails.DisplayVersion
    }
}

<#
.Synopsis
    Updates the New Relic .Net Agent
.Description
    Updates the New Relic .Net Agent to a specific version
.Example
    Update-NRDotNetAgent -Version '10.27.0'
    Checks the existing agent version and if it doesn't match updates to 10.27.0
.Parameter Version
    Installs a specific version of the agent. Please review the release notes before updating.
#>

Function Update-NRDotNetAgent {
    [CMDLetBinding(SupportsShouldProcess = $true)]
    Param (
        [Parameter (Mandatory = $true)]
        [string] $Version
    )
    # Must run as an admin to install and start the service...
    Confirm-RunAsAdmin | Out-Null

    if ($Version -ne '') {
        Write-Output "Using Version: $Version"
        $AgentRootURL = "https://download.newrelic.com/dot_net_agent/previous_releases/$Version/"
        $AgentName = "NewRelicDotNetAgent_$Version`_x64.msi"
    }
    else {
        # Use Default version updated by New Relic
        $AgentRootURL = 'https://download.newrelic.com/dot_net_agent/latest_release/'
        $AgentName = 'NewRelicDotNetAgent_x64.msi'
    }

    $agentDetails = Get-NRDotNetAgent

    if ($agentDetails.Version -like "$Version*") {
        Write-Output "Version $Version already installed..."
    }
    else {
        Write-Output "Currently running version: $($agentDetails.Version)"
        if ($PSCmdlet.ShouldProcess('New Relic .Net Agent', "Update to $Version")) {
            # Download Agent
            $localPath = Get-TempDownload -DownloadURL "$AgentRootURL$AgentName" -FileName $AgentName

            # Install and Wait
            Write-Output "Installing Agent: $AgentName"
            Start-Process 'C:\Windows\System32\msiexec.exe' -ArgumentList "/qn /i $localPath" -wait

            # Remove Temp Agent File
            Write-Output "Cleaning up Agent Files: $localPath"
            Remove-Item $localPath -Force

            # Write output when finished
            Write-Output 'Finished Updating'
        }
    }
}

<#
.Synopsis
    Disables the New Relic .NET Agent log forwarding feature in its xml configuration file.
.Description
    Disables the New Relic .NET Agent log forwarding feature in its xml configuration file. The feature is controlled by the <forwarding> element in the newrelic.config file.
.Example
    Disable-NRDotNetAgentLogForwarding -ResetIIS
.Parameter ResetIIS
    Resets the IIS process if supplied
#>

Function Disable-NRDotNetAgentLogForwarding {
    [CMDLetBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    Param (
        [Parameter (Mandatory = $true)]
        [switch] $ResetIIS
    )
    # Must run as an admin to update configuration and restart services...
    Confirm-RunAsAdmin

    # Get Current Configuration as XML
    $agentConfig = Get-NRDotNetAgentConfig

    # Configure New Relic XML namespace manager
    $nsmgr = New-Object System.Xml.XmlNamespaceManager($agentConfig.NameTable)
    $newRelicNamespaceURI = "urn:newrelic-config"
    $nsmgr.AddNamespace("ns", $newRelicNamespaceURI)

    # Determine if config already has <applicationLogging> element
    $existingAppLoggingNode = $agentConfig.SelectSingleNode("/ns:configuration/ns:applicationLogging", $nsmgr)
    if ($existingAppLoggingNode) {
        Write-Output 'Found existing applicationLogging node in New Relic .NET Agent configuration and disabling forwarding option'
        $existingForwardingNode = $agentConfig.SelectSingleNode("/ns:configuration/ns:applicationLogging/ns:forwarding", $nsmgr)
        if($existingForwardingNode) {
            # Found existing <forwarding> element, set enabled to false
            $existingForwardingNode.SetAttribute("enabled", "false")
        }
        else {
            # Create <forwarding> element, disable it, and append to applicationLogging element -> <forwarding enabled="false">
            $forwardingNode = $agentConfig.CreateElement("forwarding", $newRelicNamespaceURI)
            $forwardingNode.SetAttribute("enabled", "false")
            $existingAppLoggingNode.AppendChild($forwardingNode);
        }
    }

    # No <applicationLogging> element was found, create it and disable forwarding
    else {
        Write-Output 'Creating new applicationLogging node in New Relic .NET Agent configuration and disabling forwarding option'
        # Create <applicationLogging> element and enable it -> <applicationLogging enabled="true">
        $applicationLoggingNode = $agentConfig.CreateElement("applicationLogging", $newRelicNamespaceURI)
        $applicationLoggingNode.SetAttribute("enabled", "true")

        # Create <forwarding> element, disable it, and append to applicationLogging element -> <forwarding enabled="false">
        $newForwardingNode = $agentConfig.CreateElement("forwarding", $newRelicNamespaceURI)
        $newForwardingNode.SetAttribute("enabled", "false")
        $applicationLoggingNode.AppendChild($newForwardingNode);

        # Append applicationLogging element to root <configuration> element
        $root = $agentConfig.SelectSingleNode("/ns:configuration", $nsmgr)
        $root.AppendChild($applicationLoggingNode)
    }

    # Save configuration changes
    if ($PSCmdlet.ShouldProcess('New Relic .NET Agent Configuration', 'Save')) {
        $agentConfig.Save("$env:ALLUSERSPROFILE\New Relic\.NET Agent\newrelic.config")
    }


    # Restart Agent to pick up settings
    Restart-Service 'newrelic-infra'

    # Restart IIS (if requested)
    if ($ResetIIS) {
        $IIS = Get-WindowsOptionalFeature -Online -FeatureName “IIS-WebServer”
        if($IIS.State -eq "Enabled") {
            Write-Output 'Restarting IIS as requested'
            Start-Process "iisreset.exe" -NoNewWindow -Wait
        }
        else {
            Write-Output 'IIS was not restarted because the feature was not enabled'
        }
    }
}