Trying to get log4net working with PowerShell (with a log4net config file in the mix)

freeBSD picture freeBSD · Nov 21, 2012 · Viewed 8k times · Source

I have been struggling with getting log4net working with PowerShell. I have the following PowerShell code that pulls in log4net with a configuration file and then attempts to make a simple log file entry but which errors out.

Clear-History
Clear-Host
#
Write-Host "BEGIN: Importing module psm_logger.psm1"
Import-Module "C:\Users\Administrator\Desktop\ps\IIS\psm_logger.psm1" -Force
Write-Host "BEGIN: log4net configuration definition"
$log = New-Logger -Configuration "C:\Users\Administrator\Desktop\ps\IIS\logging\log4net.config" -Dll "C:\Users\Administrator\Desktop\ps\IIS\logging\log4net.dll"
Write-Host "END: log4net configuration definition"
Write-Host "BEGIN: log4net configuration DEBUG definition"
#$log.DebugFormat("Logger configuration file is : '{0}'", (Resolve-Path "C:\Users\Administrator\Desktop\ps\IIS\logging\log4net.config"))
Write-Host "END: log4net DEBUG configuration definition"
#======================
$ThisHostname = $env:COMPUTERNAME
#======================
Write-Host "BEGIN: Module/Snapin import/addition"
Write-Host ""
$log.Info("BEGIN: Module/Snapin import/addition")
#======================

The above referenced psm_logger.psm1 file contains:

function New-Logger
{
#Write-Host "BEGIN: New-Logger"
<#
.SYNOPSIS
      This function creates a log4net logger instance already configured
.OUTPUTS
      The log4net logger instance ready to be used
#>
     [CmdletBinding()]
     Param
     (
          [string]
          # Path of the configuration file of log4net
          $Configuration,
          [Alias("Dll")]
          [string]
          # Log4net dll path
          $log4netDllPath
     )
     Write-Verbose "[New-Logger] Logger initialization"
     $log4netDllPath = Resolve-Path $log4netDllPath -ErrorAction SilentlyContinue -ErrorVariable Err
     if ($Err)
     {
          throw "Log4net library cannot be found on the path $log4netDllPath"
     }
     else
     {
          Write-Verbose "[New-Logger] Log4net dll path is : '$log4netDllPath'"
          [void][Reflection.Assembly]::LoadFrom($log4netDllPath) | Out-Null
          # Log4net configuration loading
          $log4netConfigFilePath = Resolve-Path $Configuration -ErrorAction SilentlyContinue -ErrorVariable Err
          if ($Err)
          {
               throw "Log4Net configuration file $Configuration cannot be found"
          }
          else
          {
               Write-Verbose "[New-Logger] Log4net configuration file is '$log4netConfigFilePath' "
               $FileInfo = New-Object System.IO.FileInfo($log4netConfigFilePath)
               [log4net.Config.XmlConfigurator]::Configure($FileInfo)
               $script:MyCommonLogger = [log4net.LogManager]::GetLogger("root")
               Write-Verbose "[New-Logger] Logger is configured"
               return $MyCommonLogger
          }
     }
}

The configuration file for log4net looks like:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" **requirePermission="false"**/>
    </configSections>
    <log4net>
        <appender name="LogFileAppender" type="log4net.Appender.FileAppender">
            <param name="File" value="C:\Users\Administrator\Desktop\ps\IIS\LOGS\LogTest2.txt" />
            <param name="AppendToFile" value="true" />
            <layout type="log4net.Layout.PatternLayout">
                <param name="Header" value="[Header]\r\n" />
                <param name="Footer" value="[Footer]\r\n" />
                <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n" />
            </layout>
        </appender>
        <root>
            <level value="ALL" />
            <appender-ref ref="LogFileAppender" />
        </root>
    </log4net>
</configuration>

When run the output AND error produced is:

BEGIN: Importing module psm_logger.psm1 BEGIN: log4net configuration definition END: log4net configuration definition BEGIN: log4net configuration DEBUG definition END: log4net DEBUG configuration definition BEGIN: Module/Snapin import/addition

Method invocation failed because [System.Object[]] doesn't contain a method named 'Info'. At C:\Users\Administrator\Desktop\ps\IIS\IIS_localLogs.ps1:18 char:10 + $log.Info <<<< ("BEGIN: Module/Snapin import/addition") + CategoryInfo : InvalidOperation: (Info:String) [], RuntimeException + FullyQualifiedErrorId : MethodNotFound

Any help would be greatly appreciated!

(FYI: I originally got this code from a best practices blog entry here: http://blog.octo.com/en/powershell-v2-my-best-practices/ which I found very helpful)

Answer

freeBSD picture freeBSD · Nov 21, 2012

Found the solution...

The config file was corrupted by the presence of some asterisks towards the top. Removing those fixed the issue. Thank you to anybody who may have started to look at this and I hope this helps somebody else in the future.

The configuration file now looks like:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" requirePermission="false"/>
    </configSections>
    <log4net>
        <appender name="LogFileAppender" type="log4net.Appender.FileAppender">
            <param name="File" value="C:\Users\Administrator\Desktop\ps\IIS\LOGS\LogTest2.txt" />
            <param name="AppendToFile" value="true" />
            <layout type="log4net.Layout.PatternLayout">
                <param name="Header" value="[Header]\r\n" />
                <param name="Footer" value="[Footer]\r\n" />
                <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n" />
            </layout>
        </appender>
        <root>
            <level value="ALL" />
            <appender-ref ref="LogFileAppender" />
        </root>
    </log4net>
</configuration>