Category: watch2

Watch2- part 2- first fast implementation

The first attempt to writing the code was very fast – and, surely, not testable. (Speedy Gonzales would be proud!)

Some observations:

1. If you start any process inside a console application, you should intercept the cancel signal and stop the process.
This is done by using the CancelKeyPress event of the Console class.
This is important because the user can cancel the process by pressing Ctrl+C.
(Because who doesn’t love a good Ctrl+C in the morning?)

Console.CancelKeyPress += delegate {
    // call methods to clean up
    Kill(proc);
};

2. If you want to stop the dotnet watch after it detects a change in the file system, you cannot. You need to kill the process and start it again. So, you need to kill the process and start it again.
(It’s like a phoenix, it must die to be reborn!)

3. Spectre.Console is a really good library to create console applications with a lot of features. I used it to create messages with different colors and styles.
(Because plain text is so last century.)

4. The code is very simple and easy to understand. I used the Process class to start the dotnet watch process and the Console class to write messages to the console.
(Simple and easy, just like making a cup of coffee… if you have a coffee machine.)

This is the final code:

using Spectre.Console;
using System.Diagnostics;
Process? proc = null;
Console.CancelKeyPress += delegate {
    // call methods to clean up
    Kill(proc);
};
bool shouldWait = false;
while (true)
{
    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.FileName = "dotnet";
    startInfo.Arguments = "watch " + string.Join(' ', args);
    //startInfo.LoadUserProfile = true;
    startInfo.WorkingDirectory = Environment.CurrentDirectory;

    startInfo.RedirectStandardOutput = true;
    startInfo.RedirectStandardInput = true;
    startInfo.RedirectStandardError = true;
    startInfo.UseShellExecute = false;
    startInfo.CreateNoWindow = true;

    proc = new Process();
    proc.StartInfo = startInfo;
    proc.OutputDataReceived += (sender, e) =>
    {
        if (shouldWait)
        {
            shouldWait = false;
            Kill(proc);
            Thread.Sleep(15_000);
            return;

        }
        var line = e.Data;
        if (line == null) return;
        if (line.Contains("dotnet watch"))
        {
            if (line.Contains("Started"))
            {
                Console.Clear();
            }
            if (line.Contains("Building"))
            {

            }
        }

        if (line.Contains(": error "))
        {
            AnsiConsole.MarkupLineInterpolated($"->[bold red]:cross_mark: {e.Data}[/]");
            return;
        }
        if (line.Contains("Waiting for a file to change before"))
        {
            Console.WriteLine("wain");
            shouldWait = true;

        }

        Console.WriteLine("->" + e.Data);


    };
    proc.ErrorDataReceived += (sender, e) =>
    {
        if (e.Data != null)
        {
            AnsiConsole.MarkupLineInterpolated($"->[bold red]:cross_mark: {e.Data}[/]");
            return;

        }
    };

    AnsiConsole.MarkupLineInterpolated($"[bold green]Starting...[/]");
    proc.Start();
    Console.Clear();
    proc.BeginOutputReadLine();
    proc.BeginErrorReadLine();
    await proc.WaitForExitAsync();
}

static void Kill(Process? proc)
{
    if (proc == null) return;
    if (proc.HasExited) return;
    proc.Kill(true);
    proc.Close();
    proc = null;
}

Watch2–part 1–idea

I frequently use .NET Watch for two main reasons:

  1. Running .NET applications during development.

  2. Executing tests.

Seriously, if you haven’t tried .NET Watch, you’re missing out. It’s like having a personal assistant who never sleeps compiling code . For more info, check out Microsoft’s documentation  at https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-watch

But, like all good things, it comes with a couple of quirks:

  1. The console output scrolls faster than a cat on a hot tin roof, making it hard to keep up. A Console.Clear (or cls command) would be a lifesaver to reset the console after each file change.

  2. Running dotnet watch for both the application and tests at the same time is like trying to juggle flaming torches—compilation conflicts galore! You’ll often find yourself stopping one of the watches to keep things from going up in flames.

To tackle these issues, I whipped up a simple .NET tool, named Watch2.  This little gem can clear the console and run the watch command with an optional delay. It’s built with .NET Core and can be installed as a global tool.

For more laughs and details, visit the NuGet package page  at https://www.nuget.org/packages/watch2 .

Andrei Ignat weekly software news(mostly .NET)

* indicates required

Please select all the ways you would like to hear from me:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.