Friday, 27 December 2024

Terminating a process running on local port using Powershell

Developers who work with frontend and backend often switching between tools get a message that a certain process is holding a port. For example, using the dotnet command, you can get a message that the address is already in use. Note - you usually must decide if you really want to terminate the process running on a certain port, but if you are sure that you just want to close the process and free up the local port for its use, it would be nice to have a way of
just closing the process running on that local port. A typical output would be:

 System.IO.IOException: Failed to bind to address http://127.0.0.1:5000: address already in use.

We can locate which process is using te port, that is, the local port, and then terminate the process. This will free up the local port so we can use it. Here is a Powershell function that will find the process running at a local port, if any, given by a specied port number.


<#
.SYNOPSIS
Stops the process using the specified local port 

.DESCRIPTION
This function finds the process, if any, using the specified port and stops it.
In case there are no process, the function exits.

.PARAMETER portId
The port number to check for the process

.RETURNS int
If successful, returns 0. If not, returns -1.

.EXAMPLE
Terminate-Port -portId 5000
#>
function Terminate-Port {
    param (
        [Parameter(Mandatory = $true)]
        [int]$portId
    )

    # Get the process ID (PID) using the specified port 
    try {
        Write-Host "Looking for processing running using local port: $portId"
        $connection = Get-NetTCPConnection -LocalPort $portId -ErrorAction Stop
        if ($connection) {
            Write-Output "Port $portId is in use by process ID $($connection.OwningProcess | Select-Object -Unique)."
        } else {
            Write-Output "Port $portId is not in use."
            return 0 | Out-Null
        }
    } catch {
        Write-Output "An error occurred: $_"
        return -1 | Out-Null
    }

    $processId = $connection.OwningProcess

    if ($processId -and $processId -gt 0) {
        $process = Get-Process -Id $processId
        if ($process) {
            # Stop the process
            try {
                Stop-Process -Id $processId -Force
                Write-Host "Process running at port $portId was terminated."
                return 0 | Out-Null
            } catch {
                Write-Host "Could not stop process. Reason: $error"
            }
        }
    }

    Write-Host "No process found using port $portId."
    return -1 | Out-Null
}



To terminate , we just run the command

 Terminate-Port -portId 5000


Screenshots of the function being run: BEFORE the command Terminate-Port is run and AFTER. Note that the process running at the given portId was terminated and then the local port is freed up again.
AFTER

Monday, 23 December 2024

Custom spans in C#

This article will look more into Spans in C# and demonstrate how you can create a custom Span yourself.

Span<T> and ReadOnlySpan<T> were introduced in 2018 with C# 7.2 and .NET Core 2.1.

These types provide a way to work with contiguous regions of memory safely and efficiently, without copying data.

They are particularly useful for performance-critical applications, as they allow for slicing and accessing memory without the overhead of array bounds checking.

The introduction of spans marked a significant improvement in how .NET handles memory, offering developers more control and flexibility.

I have added a Github repo for the code shown in this article here:
https://github.com/toreaurstadboss/CustomSpan

ref struct and provide methods for supplying either a reference to an object or in more usual case, an arry. Inside the ref struct, with two fields :

    private readonly ref T _reference;
    private readonly int _length;

To provide support for passing in an array and a start index and length in the constructor of the ref struct


public CustomSpan(T[] array, int start, int length)
{
    ArgumentNullException.ThrowIfNull(array);
    if (!typeof(T).IsValueType && array.GetType() != typeof(T[]))
    {
        // Covariance guard
        throw new ArgumentException($"Covariance between types {typeof(T).FullName} and {array.GetType().FullName} is not supported in CustomSpan");
    }

#if TARGET_64BIT
    if ((ulong)(uint)start + (ulong)(uint)length > (ulong)(uint)array.Length)
    {
        throw new IndexOutOfRangeException("The index was out of bounds for the array");
    }
#else
    if ((uint)start + (uint)length > (uint)array.Length)
    {
        throw new IndexOutOfRangeException("The index was out of bounds for the array");
    }
#endif

    _reference = ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)start); //nint - native integer
    _length = length;
}


MemoryMarshal class inside System.Runtime.InteropServices contains helper methods such as GetArrayDataReference, which returns a reference to the 0-th element of an array. As we can see, array variance checks are done in the method. The Unsafe class inside System.Runtime.CompilerServices provides a method Add which is used to add an element offset to a reference, handy for getting the offset. As we see, there are no copying of memory blocks, only a reference to the first element of the array and start, the offset. The length variable specified here just defines the length to use for bounds checking. Note that we must handle also if the code executes inside 32-bits and 64-bits environments. We finally return a reference to the array given by an offset provided the value start. The (nint) used here is native integer. We also want to provide an indexer, so we can retrieve a value directly. We also provide a writable indexer too, in the method GetWritable. This is not considered good practice regarding encapsulation, just to demonstrate how you could do it.


// Read-only indexer
public ref readonly T this[int index]
{
    get
    {
        if ((uint)index >= (uint)_length)
        {
            throw new IndexOutOfRangeException();
        }
        return ref Unsafe.Add(ref _reference, index);
    }
}

// Read-write indexer
public ref T GetWritable(int index)
{
    if ((uint)index >= (uint)_length)
    {
        throw new IndexOutOfRangeException();
    }
    return ref Unsafe.Add(ref _reference, index);
}


We also provide a method that returns a readonly span from the custom span.


    public ReadOnlySpan<T> AsReadOnlySpan()
    {
        return MemoryMarshal.CreateReadOnlySpan(ref _reference, _length);
    }

To use this CustomSpan, demo code is shown below:


void Main(){

    var nums = Enumerable.Range(0, 1000).ToArray(); 
    var spanOfNums = new CustomSpan<int>(nums, 500, 500); 
    var twentyToFifty = spanOfNums.Slice(20, 5);
    
    Console.WriteLine("Output of the twentytoFifty span:");
    twentyToFifty.PrintArrayContents(); //prints 520..525


    for (int i = 0; i < twentyToFifty.Length; i++)
    {
        twentyToFifty.GetWritable(i) = (int) Math.Pow((double)twentyToFifty[i], 2); //mutates the Span contents - squares the elements , using GetWritable
    }
    
    Console.WriteLine("\nOutput of the mutated twentytoFifty span:");
    twentyToFifty.PrintArrayContents();
}


The output looks like this:


Output of the twentytoFifty span:
520
521
522
523
524

Output of the mutated twentytoFifty span:
270400
271441
272484
273529
274576



Usually, you would use the built-in spans in C#, as they contain the necessary functionality you need. This article was just a dive into how Spans are implemented, the code for Spans are available on the .NET source code web site :

https://source.dot.net https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Span.cs,d2517139cac388e8

Monday, 16 December 2024

SpeechService in Azure AI Text to Speech

This article will present Azure AI Text To Speech service. The code for this article is available to clone from Github repo here:

https://github.com/toreaurstadboss/SpeechSynthesis.git

The speech service uses AI trained speech to provide natural speech and ease of use. You can just provide text and get it read out aloud. An overview of supported languages in the Speech service is shown here:

https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support?tabs=stt

Azure AI Speech Synthesis DEMO

You can create a TTS - Text To Speech service using Azure AI service for this. This Speech service in this demo uses the library Nuget Microsoft.CognitiveServices.Speech.

This repo contains a simple demo using Azure AI Speech synthesis using Azure.CognitiveServices.SpeechSynthesis.
It provides a simple way of synthesizing text to speech using Azure AI services. Its usage is shown here:

The code provides a simple builder for creating a SpeechSynthesizer instance.

using Microsoft.CognitiveServices.Speech;

namespace ToreAurstadIT.AzureAIDemo.SpeechSynthesis;

public class Program
{
    private static async Task Main(string[] args)
    {
        Console.WriteLine("Your text to speech input");
        string? text = Console.ReadLine();

        using (var synthesizer = SpeechSynthesizerBuilder.Instance.WithSubscription().Build())
        {
            using (var result = await synthesizer.SpeakTextAsync(text))
            {
                string reasonResult = result.Reason switch
                {
                    ResultReason.SynthesizingAudioCompleted => $"The following text succeeded successfully: {text}",
                    _ => $"Result of speeech synthesis: {result.Reason}"
                };
                Console.WriteLine(reasonResult);
            }
        }

    }

}

The builder looks like this:
using Microsoft.CognitiveServices.Speech;

namespace ToreAurstadIT.AzureAIDemo.SpeechSynthesis;

public class SpeechSynthesizerBuilder
{

    private string? _subscriptionKey = null;
    private string? _subscriptionRegion = null;

    public static SpeechSynthesizerBuilder Instance => new SpeechSynthesizerBuilder();

    public SpeechSynthesizerBuilder WithSubscription(string? subscriptionKey = null, string? region = null)
    {
        _subscriptionKey = subscriptionKey ?? Environment.GetEnvironmentVariable("AZURE_AI_SERVICES_SPEECH_KEY", EnvironmentVariableTarget.User);
        _subscriptionRegion = region ?? Environment.GetEnvironmentVariable("AZURE_AI_SERVICES_SPEECH_REGION", EnvironmentVariableTarget.User);
        return this;
    }

    public SpeechSynthesizer Build()
    {
        var config = SpeechConfig.FromSubscription(_subscriptionKey, _subscriptionRegion);
        var speechSynthesizer = new SpeechSynthesizer(config);
        return speechSynthesizer;
    }
}

Note that I observed that the audio could get chopped off in the very end. It might be a temporary issue, but if you encounter it too, you can add an initial pause to avoid this:

   string? intialPause = "     ....     "; //this is added to avoid the text being cut in the start