Search code examples
c#.netloggingsystem.diagnostics

How do you use System.Diagnostics.TextWriterTraceListener to log to a file in C#? Are my configuration files broken?


I'm new to C# and am trying to add the ability to log messages to a file - I've been trying to figure it out for a few hours, but, I'm not very good at this.

I don't know very much about assemblies, solutions, App.config, .csproj, etc., and all of this extremely basic information is way over my head.

Here's my Program.cs:

using System.Diagnostics;

namespace Main;

class Program
{
  static void Main(string[] args)
  {
    try
    {
      Trace.AutoFlush = true;
      Trace.TraceInformation("Application started.");
      Trace.WriteLine("Hello World!");
      Trace.Flush();
      Trace.Close();
    }
    catch (Exception ex)
    {
      Console.WriteLine("Exception: " + ex.Message);
    }
  }
}

Whenever I run the program with dotnet run, the log file isn't created.

If I compile the project with dotnet publish, the log file still isn't created, and I have no idea why.

Here's my App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <trace autoflush="true">
      <listeners>
        <add name="logListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="C:\Users\tyler\src\windows-audit-monitor\trace.log" />
        <add name="consoleListener" type="System.Diagnostics.ConsoleTraceListener"/>
      </listeners>
    </trace>
  </system.diagnostics>
</configuration>

Here's my app.csproj file:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <ApplicationManifest>app.manifest</ApplicationManifest>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0-windows</TargetFramework>
    <PublishSingleFile>true</PublishSingleFile>
    <PublishTrimmed>true</PublishTrimmed>
    <SelfContained>true</SelfContained>
    <RuntimeIdentifier>win-x64</RuntimeIdentifier>
    <RootNamespace>Main</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <Configuration>Release</Configuration>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.3" />
    <PackageReference Include="NetMQ" Version="4.0.1.12" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
  </ItemGroup>

</Project>

Here's my app.manifest:

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

I have no idea which very, very, very basic step I screwed up, and know that this is all very shameful.

I already have some other code that's working, but maybe it'd make sense for me to start over with a tutorial so I can make sure I'm using the right build toolchain and configuration files...

I mainly work in Python, Go, Java, Ruby, bash, and PowerShell but am really, really, really bad at C#....


Solution

  • I'd consider going with the Microsoft.Extensions.Logging framework when writing code for .net7, possibly using an extension for logging to file:

    Add a Package reference for a logging provider that supports many useful options for logging to files <PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />

    Add using statement to the top of your code

    using Serilog;

    Create a logger and write sample message:

    Log.Logger = new LoggerConfiguration()
      .MinimumLevel.Information()
      .WriteTo.File(@"c:\log\LoggingSample.log")
      .CreateLogger();
    Log.Logger.Information("Hello world");