Logging in .NET Core Windows Forms or WPF Application

Logging in .NET Core Windows Forms or WPF Application

Logging in Forms or desktop appplication NET Core 30 app Logging in NET Core Windows Forms or WPF Application

In this article, we will learn, how to add Logging in .NET Core Windows Forms or WPF Application.

As we know .NET Core has introduced ILogger as a generic interface for logging purposes.

This framework supported interface ILogger can be used across different types of applications like,

  • Desktop or Form applications (.NET Core 3.0 and above )

Unlike .NET Core in WebAPI, the Console app or Forms App doesn’t have dependency injection by default. In ASP.NET WebAPI it was easy configuring ILogger through DI.

Today in this article, we will cover below aspects,

ILogger interface works very nicely with the .NET Core ecosystem and today in this post we will learn how to enable logging in a .NET Forms or Desktop application.

Getting Started -Logging in .NET Core Windows Forms

Here I am using a Forms/Windows .NET Core 3.0 application.

NET Core 30 The WinForms application with DI Logging in NET Core Windows Forms or WPF Application

The below code illustrates how to achieve logging in Desktop applications.

There could be multiple ways of achieving or an even better approach might be available.

Add ILogger using Dependency Injection to Forms App

Below is the example of what we can achieve ultimately for the logger and implement Logging in .NET Core Windows Forms

NET Core 30 The WinForms application with Dependency injection NET Core Logging in NET Core Windows Forms or WPF Application

In the above code, we added a logging ILogger interface to services collection and built the ServiceProvider for the required services.

With that ILogger instance can be DI via Constructor injection as shown above,

The complete sample code is as below,

public partial class Form1 : Form
    {
        private readonly ILogger _logger;
        public Form1(ILogger<Form1> logger)
        {
            _logger = logger;
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                _logger.LogInformation("Form1 {BusinessLayerEvent} at {dateTime}", "Started", DateTime.UtcNow);
                // Perform Business Logic here 
               
                MessageBox.Show("Hello .NET Core 3.1.This is First Forms app in .NET Core");
                _logger.LogInformation("Form1 {BusinessLayerEvent} at {dateTime}", "Ended", DateTime.UtcNow);
            }
            catch (Exception ex)
            {
                //Log technical exception 
                _logger.LogError(ex.Message);
            }
        }

To achieve the above here is below how I updated the Main() method for Service collection for required interfaces.

Application class in Forms application expect static method innovation.

Due to the same reason, I made use of the same class to provide a start-up for First Forms to be injected and then injected all required services through that Forms instance.

        [STAThread]
        static void Main()
        {
            Application.SetHighDpiMode(HighDpiMode.SystemAware);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            var services = new ServiceCollection();
            ConfigureServices(services);
            using (ServiceProvider serviceProvider = services.BuildServiceProvider())
            {
                var form1 = serviceProvider.GetRequiredService<Form1>();
                Application.Run(form1);
            }
        }

ConfigureService() method is added as below to take care of all services required in the App. Add all your DI services to the service collection.

Below I am creating a singleton instance of the Form object and Scoped lifetime instance of the other business objects.

private static void ConfigureServices(ServiceCollection services)
        {
            services.AddSingleton<Form1>()
                    .AddLogging(configure => configure.AddConsole())
                    .AddScoped<IBusinessLayer, CBusinessLayer>()
                    .AddScoped<IDataAccessLayer, CDataAccessLayer>();
        }

We just enabled Console logging using the below code in the above example,

services.AddLogging(configure => configure.AddConsole())

Please add below NuGet packages explicitly to your application.

  • Microsoft.Extensions.DependencyInjection
  • Microsoft.Extensions.Logging
  • Microsoft.Extensions.Logging.Console

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="3.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" />
  </ItemGroup>

Here above using statements internally call dispose and flush out console logs.

I configured the Console Logging by changing the application output type as Console app so that Console logs on the Command prompt can be visible.

Let’s run the application and check to log,

Logging in Forms or desktop appplication NET Core 30 Logging in NET Core Windows Forms or WPF Application

Updated Forms class for DI of ILogger and IBusinessLayer object is as below,

image 1 Logging in NET Core Windows Forms or WPF Application

Dependency Injection Windows Form using Generic Host Builder

Additionally please use Generic Host builder for performing DI for Logging and other business requirements.

Reference:

Can we make the above code better? Please let me know if you have any better suggestions. Please sound off your comments below.

Summary

Today we looked at simple and easy-to-use techniques to enable logging in to a .NET Core Forms application. Unlike .NET Core in WebAPI, the .NET Core Forms app doesn’t have dependency injection, but with small custom changes as mentioned above, we can very much achieve similar functionality.



Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.



10 thoughts on “Logging in .NET Core Windows Forms or WPF Application”

  1. Thanks for this article! I am implementing it in a new project.

    Quick question (I hope is not very basic). How can you see the console logs so tidy and colored? I know to see this only on the Visual Studio output window, but the format is terrible. I also started my exe (winform) from a windows terminal, but the log is not shown there.

    I would appreciate any feedback. Greetings, great work as usual from thecodebuzz.

    1. Hello Sebas- Glad you liked the article. Thank you.
      You can push those comments on console by changing the application type to “Console application” in project properties.

  2. I am trying to do the example I have the next code. And I change the Project Properties -> Application -> Output type to ‘Console Application’ to get the console to display.

    services.AddSingleton().AddLogging(configure => configure.AddConsole());

    public Form1(ILogger logger)
    {
    _logger = logger;
    InitializeComponent();

    }

    private async void BtnSave_Click(object sender, System.EventArgs e)
    {
    _logger.LogError(“Test”);
    }

  3. LEONARDO FRAIETTA

    I’m not able to pass parameters on the .AddLigging method like you are passin in

    .AddLogging(configure => configure.AddConsole())

    1. Hey Leonardo- Thank for the query. Did you add the Nuget package mentioned in the article
      Microsoft.Extensions.DependencyInjection
      Microsoft.Extensions.Logging
      Microsoft.Extensions.Logging.Console.

      That package should provide the required support. Hope it helps

  4. Matthew Conradie

    Thank you. I also had to change the Project Properties -> Application -> Output type to ‘Console Application’ to get the console to display.

    1. Hi Matthew – Thanks for the feedback. yes.. That trick always helps me something I want to verify locally :).

Leave a Comment

Your email address will not be published. Required fields are marked *