Category Archives: C#

Creating a Game in Blazor – Part 4 – Platform and Collision

I’ve recently been creating a JetSet Willy clone in Blazor. I use the term clone loosely – I’m actually not creating a clone or anything like it – I’m simply replicating some aspects of the game (moving, jumping, platforms, collision, etc.).

This is the fourth post in the series that started here. In this post, I’m going to add a platform – so far we’ve been walking on the air.

As with previous posts, the code for this can be found here on GitHub.

In order to do this, we’ll need to do a bit of refactoring, and to introduce a crude collision concept. Let’s start with the refactoring and platform display:

We’re introducing the concept of a base GameObject, from which, Platform, Player, and NPC inherit. We’re dispensibg of IPlayer, and instead, adapting World to manage the elements in the world:

    public class World : IWorld
    {
        private readonly IEnumerable<GameObject> _gameObjects;

        public World(IEnumerable<GameObject> gameObjects)
        {
            _gameObjects = gameObjects;
        }

        public Player Player
        {
            get => (Player)_gameObjects.First(a => a.GameObjectType == GameObjectType.Player);
        }

        public IEnumerable<GameObject> Platforms 
        {  
            get => _gameObjects.Where(a => a.
                GameObjectType == GameObjectType.Platform);
        }

        public void ApplyPhysics()
        {   
            foreach (var gameObject in _gameObjects)
            {
                gameObject.Update();
            }            

        }
        
    }

We’re not dealing with NPCs in this post, but we are dealing with platforms. The new Platform class currently looks like this:

    public class Platform : GameObject
    {
        public Platform(int width, int height, int left, int top)
        {
            Width = width;
            Height = height;
            Left = left;
            Top = top;
            GameObjectType = GameObjectType.Platform;
        }

        public override void Update()
        {
            //throw new System.NotImplementedException();
        }
    }

We’ll no doubt come back to this, but essentially, all we’re doing is maintaining a collection of GameObjects with a specific type.

For now, we’ll inject the properties of the World in through Program.cs:

    public class Program
    {
        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("#app");

            builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
            builder.Services.AddSingleton<IWorld, World>(srv =>
            {
                var platform = new Platform(
                    50, 10, 0, WorldSettings.FLOOR);

                var player = new Player(17, 21, new[] { platform })
                {
                    GameObjectType = GameObjectType.Player,
                };

                var world = new World(new GameObject[] { player, platform });                
                return world;
            });            
            builder.Services.AddSingleton<IControls, Controls>();
            builder.Services.AddSingleton<IGraphics, Graphics>();

            await builder.Build().RunAsync();
        }
    }

As you can see, we build the Platform and Player and then build the world. Finally, we adapt Game.razor to display the platforms:

@page "/"
@using System.Timers
@using BlazorGame.GameLogic
@inject IEnumerable<GameObject> GameObjects
@inject IControls Controls
@inject IWorld World
@inject IGraphics Graphics

<div @onkeydown="HandleKeyDown" @onkeyup="HandleKeyUp" @onkeydown:preventDefault 
    style="background-color: #000000; width: 80vw; height: 80vh; margin: auto"
    tabindex="0" @ref="mainDiv">
    <div style="color: white; top: @(World.Player.Top)px; left: @(World.Player.Left)px; width: @(World.Player.Width)px; height: @(World.Player.Height)px; overflow: hidden; position: relative">
        <img 
            src="/images/Willy-Sprite-Sheet.png" 
            style="margin: 0 @(Graphics.PlayerOffset)px; transform: scaleX(@(Graphics.PlayerDirection))" />
    </div>

    @foreach (var platform in World.Platforms)
    {
        <div style="position: relative; top:@(platform.Top)px; left:@(platform.Left)px; width:@(platform.Width)px; height:@(platform.Height)px; border: 1px solid #FFFFFF; background-color: #FFFFFF"></div>
    }
</div>

Finally, we need to ensure that our player lands on the platform (and doesn’t simply drop through). For now, we’ll pass the World into Player and perform the logic there:

        public override void Update()
        {
            _forceUp -= WorldSettings.GRAVITY;

            Top -= _forceUp;

            Console.WriteLine($"Top: {Top}, Left: {Left}, Width: {Width}");

            var platform = _gameObjects.FirstOrDefault(a =>
                a.Top <= Top &&
                a.Left <= Left + Width &&
                a.Left + a.Width >= Left + Width &&
                a.GameObjectType == GameObjectType.Platform);
            
            if (platform != null)
            {
                Top = platform.Top;
                _forceUp = 0;
            }
            
            if (Left <= 0 && _forceRight < 0) 
                _forceRight = 0;
            else if (_forceRight != 0)
                _direction = _forceRight;            

            Left += _forceRight;
            
        }

It’s not quite finished yet, but we now have a platform that we can walk on, and fall off:

What’s Next?

In the next post, I’ll try to introduce an NPC (not quite sure where I can get the graphics from yet, so it might just be a rectangle or something).

Creating a Game in Blazor – Part 3 – Graphics

In this post I started writing a game in Blazor. In this last post, I covered how we could use the keyboard to move an object around, and how we could apply gravity.

In this post, we’re going to refactor, and we’re going to replace the word test with something approximating Willy.

Refactor

Just because we’re writing a game in Blazor is no reason not to use the IoC container in order to better structure the code. I’m not going to cover all of the refactoring here; however, the changes are here.

We’ve added a sub-directory called GameLogic which contains all the relevant classes:

At some point in the future, we may separate this directory into its own project; but for now, we have four classes:

Controls – this handles the user input.

Graphics – this will handle the manipulation of the graphics.

Player – this handles behaviour of the player.

World – this deals with the things such as collisions, gravity, etc.

WorldSettings – these are just a list of variables that control how things move. In the original game, there was a POKE that meant you could jump so high that you went into the next room.

I won’t cover what’s actually in these classes – it’s essentially what was in the main Razor file. I will cover the change to the razor file itself:

@page "/"
@using System.Timers
@using BlazorGame.GameLogic
@inject IPlayer Player
@inject IControls Controls
@inject IWorld World

<div @onkeydown="HandleKeyDown" @onkeyup="HandleKeyUp" @onkeydown:preventDefault 
    style="background-color: #000000; width: 80vw; height: 80vh; margin: auto"
    tabindex="0" @ref="mainDiv">
    <div style="color: white; top: @(Player.Top)px; left: @(Player.Left)px; width: 20px; position: relative">test</div>
</div>

@code {

    private ElementReference mainDiv;    
    private Timer _timer;

    private void HandleKeyUp(KeyboardEventArgs e) =>
        Controls.KeyUp(e.Code);    

    private void HandleKeyDown(KeyboardEventArgs e) =>    
        Controls.KeyDown(e.Code);    

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await mainDiv.FocusAsync();
        }
    }

    protected override Task OnInitializedAsync()
    {
        _timer = new Timer();
        _timer.Interval = 16;
        _timer.Elapsed += TimerElapsed;
        _timer.AutoReset = true;
        _timer.Enabled = true;        

        return base.OnInitializedAsync();
    }

    private void TimerElapsed(Object source, System.Timers.ElapsedEventArgs e)
    {
        Update();
        Draw();
    }

    private void Update()
    {
        World.ApplyPhysics();
    }

    private void Draw() => 
        this.StateHasChanged();    

}

This is much more terse than before, and delegates most of its functionality to the classes that we described above. You’ll see at the top that we @inject those classes into the page.

Finally, the classes are registered in Program.cs:

        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("#app");

            builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
            builder.Services.AddSingleton<IWorld, World>();
            builder.Services.AddSingleton<IPlayer, Player>();
            builder.Services.AddSingleton<IControls, Controls>();

            await builder.Build().RunAsync();
        }

This is by no means the last refactoring that we’ll do, but it’s perhaps the last one that will make it into its own section of a post.

Graphics

For the graphics, I spent a while trying to get various graphics libraries to work cross platform. I finally realised that, not only did I not need a graphics library, but that I’d solved this issue before – well, more or less. The answer was to use CSS to animate the image. The very first step was to add a sprite sheet; which I got from here, and since Jet Set Willy is the same character as manic miner (with just one pixel difference in the hat), I managed to add a sprite sheet:

The next change was to alter the HTML in Game.razor slightly:

<div @onkeydown="HandleKeyDown" @onkeyup="HandleKeyUp" @onkeydown:preventDefault 
    style="background-color: #000000; width: 80vw; height: 80vh; margin: auto"
    tabindex="0" @ref="mainDiv">
    <div style="color: white; top: @(Player.Top)px; left: @(Player.Left)px; width: 16px; height: 17px; overflow: hidden; position: relative">
        <img 
            src="/images/Willy-Sprite-Sheet.png" 
            style="margin: 0 @(Graphics.PlayerOffset)px; transform: scaleX(@(Graphics.PlayerDirection))" />
    </div>
</div>

There’s a few things to unpick here. Let’s start with the interaction between the div and the img. Essentially, we’re using the div as a window into the image; similar to this:

Both the margin and transform are set to bound properties of a new Graphics class, which we’ll come to in a second; but first, let’s see the other change to this file:

    private void Update()
    {
        World.ApplyPhysics();
        if (Player.IsWalking)
        {
            Graphics.CyclePlayer();
        }
    }

This allows us to change the bound variables that we mentioned earlier.

Now that we’ve seen the changes to the main razor file, let’s see the new Graphics class:

    public class Graphics : IGraphics
    {
        private readonly IPlayer _player;
        private int _playerOffset = 0;
        private DateTime _lastUpdate = DateTime.MinValue;

        public Graphics(IPlayer player)
        {
            _player = player;
        }

        public int PlayerOffset => _playerOffset;

        public int PlayerDirection =>
            _player switch
            {
                { IsWalkingLeft: true } => -1,
                { IsWalkingRight: true } => 1,
                _ => 0
            };
        
        public void CyclePlayer()
        {
            if (_lastUpdate.AddMilliseconds(100) > DateTime.Now) return;

            if (_playerOffset > -48)
                _playerOffset -= 16;
            else
                _playerOffset = 0;

            _lastUpdate = DateTime.Now;
        }
    }

This is essentially a utility, or helper class. It encapsulates details about the graphics that are displayed, and uses the Player class to do so. Most of it is relatively self-explanatory, with the possible exception of CyclePlayer which moves the offset that we mentioned earlier no more frequently that every 100ms.

That’s pretty much it; we now have a walking Willy:

What’s Next?

In the next post, we’ll try to add a platform, and some collision logic.

References

https://www.spriters-resource.com/fullview/113060/

https://gunnarpeipman.com/csharp-reading-embedded-files/

https://www.hanselman.com/blog/how-do-you-use-systemdrawing-in-net-core

https://www.davidguida.net/blazor-gamedev-part-11-improved-assets-loading/

https://stackoverflow.com/questions/493296/css-display-an-image-resized-and-cropped

Creating a Game in Blazor – Part 1 – Moving Objects

By now, writing games in frameworks that were clearly not designed for such things is becoming something of a habit for me. Here I created a poor-man’s version of Trans-Am (the hugely popular Spectrum game) in React, and here I attempted something along the lines of Daley Thompson’s Decathlon in Vue. I even created a catch game and a snake game in a .Net console app.

In this post, I’m going to attempt to create a game in Blazor. I’m hoping I can get a vague approximation of a platform game, such as Jet Set Willy. Obviously, this will not be as advanced (nor will I be able to offer a helicopter ride as a prize for finishing, as the creators originally did), but I can hopefully get some semblance of something moving across the screen, and the ability to jump over obstacles.

For part one, we’ll just explore how we would move an object. To start, let’s create a default Blazor client side application.

If you’d like to see the finished product from this post, you’ll find it here.

We’ll start in the Counter.razor file. We’ll simply replace the existing code with the following:

@page "/counter"

<h1>Counter</h1>

<button class="btn btn-primary" @onclick="IncrementLeft">Across</button>
<button class="btn btn-primary" @onclick="IncrementTop">Down</button>

<div style="top: @(top)px; left: @(left)px; position: absolute">test</div>

@code {
private int top = 0;
private int left = 0;

private void IncrementLeft()
{
left += 10;
}

private void IncrementTop()
{
top += 10;
}

}

All we’re really doing here is binding the position of the div to the variables left and top and then changing them on the button presses. Each time they are updated, they trigger a refresh of the screen.

You should now see the word test (very vaguely) in the top left hand corner of the screen. Pressing the Across and Down buttons move the text – if you move it far enough, you should be able to see it clearly against the white background.

Tidy Up

Now that this is working, let’s remove some of the cruft – our game doesn’t need a menu, or a FetchData screen; the following files can be removed:

Index.razor
NavMenu.razor
FetchData.razor

In Counter.razor we can change the routing:

@page "/"

Finally, change the code in MainLayout.razor to the following:

@inherits LayoutComponentBase

<div class="page">
<div class="main">
<div class="content px-4">
@Body
</div>
</div>
</div>

What’s left is just the counter screen: which can now be renamed to something more appropriate – I’ve changed mine to Game.razor.

What’s Next

We now have something moving around the screen – the next step will be to make this work using key presses, and add an actual platform for our game.

Mutation Testing

Some time ago, I heard Dan Clarke from the Unhandled Exception podcast mention Mutation testing – the latest episode on this can be found here. I thought this definitely warranted some investigation.

If you skip to the bottom of this post, you’ll see some links to the official docs for Stryker, and to a video that details exactly how to use it.

What is Mutation Testing

The hypothesis here is that, if you’ve written a test, you can test that test by changing an element of the code under test – if the change breaks your test then your test is valid, if it does not, then your test is not.

I’m not completely sure I accept this theory, but I can see its uses. In this post, I’m experimenting with a Calculator class.

Installation

For the purpose of this, I’ll assume that you have some code to test. If you don’t, then you can download the code that I used my my tests here.

You’ll need a terminal window – you can use Windows Terminal, or any other terminal window of your choice; I’ve recently started using the Developer Power Shell (it’s kind of the Visual Studio equivalent of the VS Code Terminal):

The first thing you’ll need to do (unless you’re using other .Net Tools in your project) is to install the manifest:

dotnet new tool-manifest

To install Stryker, use the following command:

dotnet tool install dotnet-stryker

Tests and Usage

The tool cannot work without tests – remember that the purpose of it is to tell you if the tests are useful, not if the tests are there (although you do get some coverage stats from it). Here’s my code:

   public static class Calculator
    {
        public static decimal Add(decimal x, decimal y) =>
            x + y;

        public static decimal Subtract(decimal x, decimal y) =>
            x - y;

    }

And here’s the tests that I have:

        [Fact]
        public void Calculator_Add_ReturnsCorrect()
        {
            // Arrange            

            // Act
            decimal result = CalculatorApp.Calculator.Add(3, 6);

            // Assert
            Assert.Equal(9, result);
        }

As you can see, we’re looking at, at most, 50% test coverage. Let’s run the mutation tool and see what happens:

If you open the URL, you’ll get a coverage report, including any mutants that survived (we’ll come back to the later):

What this is telling us is that we don’t have particularly good test coverage, but what we do have has not survived mutation.

Let’s fill out the test coverage to 100%:

        [Fact]
        public void Calculator_Subtract_ReturnsCorrect()
        {
            // Arrange            

            // Act
            decimal result = CalculatorApp.Calculator.Subtract(1, 0);

            // Assert
            Assert.Equal(1, result);

        }

Admittedly, this took some gaming of the system, but when you run this, it survives:

Why did that test survive, by the first one didn’t? And what does ‘survived’ mean? Well, you can actually get it to tell you what it does during the mutation by selecting the file in question, and clicking “Expand All”:

What this tells you is that it replaced the code in the Subtract method with 1 (i.e. just return 1), and with x + y, (rather than x – y). The mutation would be ‘killed’ if, upon this change, at least one test failed. All I had to do was to find a test that would survive both scenarios (hence 1 – 0.

Summary

Stryker looks like a really cool and useful tool, but it definitely has its limitations. It identifies test coverage, and any test coverage that isn’t definitive (where there is no assert statement, or where the assert statement is ambiguous; for example, asserting that an exception is not thrown).

I’ve still to run it on a reasonable sized code-base; which I fully intend to do, but I’m not sure that I’d necessarily build this into a CI/CD pipeline (unless you genuinely fear that your developers are gaming the code-coverage stats).

I also have reservations as to whether a code base with 100% test coverage, and 0 surviving mutants is a healthy one, or one in a straight-jacket. Having said that, I definitely think this is a useful tool – it gives you information about your code base that you didn’t have before.

References

https://www.youtube.com/watch?v=DiIFM4Iluzw

https://stryker-mutator.io/docs/stryker-net/Introduction/

Receiving a Message Using Azure.Messaging.ServiceBus

Azure.Messaging.ServiceBus is the latest SDK library that allows you to interface with Azure Service Bus.

In this post I wrote about receiving a message in Azure Service Bus using the Microsoft.Azure.ServiceBus library. Here, I’ll cover the method of receiving a message using Azure.Messaging.ServiceBus.

The first step is to create a ServiceBusClient instance:

_serviceBusClient = new ServiceBusClient(connectionString);

Once you’ve created this, the subsequent classes are created from there. This library draws a distinction between a message receiver and a message processor – the latter being event driven.

Receiving a Message

To receive a message:

            var messageReceiver = _serviceBusClient.CreateReceiver(QUEUE_NAME);            
            var message = await messageReceiver.ReceiveMessageAsync();

            //string messageBody = Encoding.UTF8.GetString(message.Body);
            string messageBody = message.Body.ToString();

It’s worth noting here that it is no longer necessary to decode the message body explicitly.

Processing a Message

This is the new version of registering a handler for the event, and it has a few additional features. Let’s see the code:

            var processor = _serviceBusClient.CreateProcessor(QUEUE_NAME);
            processor.ProcessMessageAsync += handleMessage;
            processor.ProcessErrorAsync += ExceptionHandler;

            await processor.StartProcessingAsync();                        

            await Task.Delay(2000);
            await processor.StopProcessingAsync();

We won’t worry too much about the events themselves for now, but the important events are StartProcessingAsync and StopProcessingAsync. Note that here we have a 2 second delay – this means that we will receive messages for two seconds, and then stop; obviously the start and stop don’t need to be in the same method.

References

https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-get-started-with-queues

Add Evaluation to ML.NET Model

I’ve recently been playing around with ML.NET. I’ve documented some of my escapades here.

One thing that I found was that, when trying to work out how effective the model created from the data was, I was manually rifling through the data that I had: having to essentially compare each result. As a result, I created EvaluateMLNet. It’s a small NuGet package that essentially does this for you.

Step 1 – Import the package

If you follow the previous post, you’ll find yourself in a position where you have a Model project and a ConsoleApp project:

In order to use the package, start by importing the NuGet package into the ConsoleApp project:

Install-Package EvaluateMLNet

Step 2 – Add the data

The next stage is to have some data to test your model against. Add this to your ConsoleApp project, and remember to set the Copy if Newer or Copy Always on the file.

Step 3 – Code

The main program will look something like this to begin with:

        static void Main(string[] args)
        {
            // Create single instance of sample data from first line of dataset for model input
            ModelInput sampleData = new ModelInput()
            {
                Season = @"2019-2020",
                Time = @"7:00pm",
                Home_team_name = @"Liverpool",
                Away_team_name = @"Norwich City",
                Referee = @"Michael Oliver",
                Stadium_name = @"Anfield (Liverpool)",
            };

            // Make a single prediction on the sample data and print results
            var predictionResult = ConsumeModel.Predict(sampleData);

            Console.WriteLine($"Season: {sampleData.Season}");
            Console.WriteLine($"Time: {sampleData.Time}");
            Console.WriteLine($"Home_team_name: {sampleData.Home_team_name}");
            Console.WriteLine($"Away_team_name: {sampleData.Away_team_name}");
            Console.WriteLine($"Referee: {sampleData.Referee}");
            Console.WriteLine($"Stadium_name: {sampleData.Stadium_name}");
            Console.WriteLine($"\n\nPredicted home_team_score: {predictionResult.Score}\n\n");
            Console.WriteLine("=============== End of process, hit any key to finish ===============");
            Console.ReadKey();
        }

Instead of that, start by extracting the Predict method – that is everything after:

// Make a single prediction on the sample data and print results

This should give you:

        static void Main(string[] args)
        {
            // Create single instance of sample data from first line of dataset for model input
            ModelInput sampleData = new ModelInput()
            {
                Season = @"2019-2020",
                Time = @"7:00pm",
                Home_team_name = @"Liverpool",
                Away_team_name = @"Norwich City",
                Referee = @"Michael Oliver",
                Stadium_name = @"Anfield (Liverpool)",
            };

            PredictData(sampleData);
        }

        private static float PredictData(ModelInput sampleData)
        {
            // Make a single prediction on the sample data and print results
            var predictionResult = ConsumeModel.Predict(sampleData);

            Console.WriteLine($"Season: {sampleData.Season}");
            Console.WriteLine($"Time: {sampleData.Time}");
            Console.WriteLine($"Home_team_name: {sampleData.Home_team_name}");
            Console.WriteLine($"Away_team_name: {sampleData.Away_team_name}");
            Console.WriteLine($"Referee: {sampleData.Referee}");
            Console.WriteLine($"Stadium_name: {sampleData.Stadium_name}");

            return predictionResult.Score;
        }

Note that we’re also returning the result of the prediction. In fact, that method only needs to return the result of the prediction – the Console.WriteLines are unnecessary.

Finally, replace the Main method with the following:

        static void Main(string[] args)
        {
            var runEvaluation = new RunEvaluation();
            var resultStats = runEvaluation.Run<ModelInput, float>("my-data-file.csv",
                "Predicted_field_name", PredictData, 0);

            Console.WriteLine("Results");
            Console.WriteLine("Total evaluated results: {0}", resultStats.EvaluatedCount);
            Console.WriteLine("Total success results: {0}", resultStats.SuccessCount);
            Console.ReadLine();            
        }

A few comments about this code:

1. The “Predicted_field_name” is the name of the field in the class ModelInput. It’s very likely to have a capitalised first letter.
2. My data is predicting a float – if yours is not then you’ll need to change this.
3. The margin of error here is 0; that means that a prediction is only considered a success where it’s within the same integer; for example, if the prediction was 1.3, then 1 and 2 would be considered a success, but 0 and 3 would not.

That’s it, the output will give you something like this:

Summary

I realise that this is feeding a very niche crowd, but hopefully it’ll save someone a Saturday afternoon.

Downloading from an SFTP site using SSH.Net

I’ve done this a few times, and have failed to document it, and so each time it’s a pain. To be clear, if you’re downloading from FTP, you should have a look here: it’s an excellent, and simple code snippet that will do the job for you.

However, this won’t work with SFTP. Having looked into this, it looks like there’s basically two options: Chilkat if you have some money to spend, and SSH.NET if you don’t. I actually implemented Chilkat before realising it was commercial – it’s a much easier experience, and it’s commercially supported. I’m not being paid by them to say this, and you can easily get by with SSH.NET (in fact, that’s the subject of this post); but there are advantages to going with a commercial option.

Using SSH.NET

The latest version of SSH was released in 2016. There does appear to be an update being worked on, but the NuGet package (at the time of writing) is from 2016:

Install-Package SSH.NET

There’s some pretty good documentation on the GitHub site, and the two links in the references offer wrapper implementations. What’s here is not really any better than what’s there, but I hadn’t seen a post with the code in (plus, I like to have these things documented in my own words).

Client

The first thing you’ll need for each call is a client; I’ve separated mine into a method:

SftpClient GetClient()
{
    var connectionInfo = new PasswordConnectionInfo(url, port, username, password);

    var client = new SftpClient(connectionInfo);
    client.Connect();
    return client;
}

If you’re not sure what your port is, it’s probably 22, although I can’t help with the rest. We’re going to cover 5 basic methods here: List, Upload, Download, Read and Delete.

List

        IEnumerable<SftpFile> ListFiles(string directory)
        {
            using var client = GetClient();
            try
            {                
                return client.ListDirectory(directory);
            }
            catch (Exception exception)
            {
                // Log error
                throw;
            }
            finally
            {
                client.Disconnect();
            }
        }

There’s not much to explain here – ListDirectory returns a list of SftpFiles. The parameter directory is the directory on the remote server; if you want to access the base directory, then directory = “.”. It’s worth looking at the finally block, though. You should disconnect the client when you’re done.

Upload

        void UploadFile(string localPath, string remotePath)
        {
            using var client = GetClient();
            try
            {
                using var s = File.OpenRead(localPath);
                client.UploadFile(s, remotePath);
            }
            catch (Exception exception)
            {
                // Log error
                throw;
            }
            finally
            {
                client.Disconnect();
            }
        }

Again, not much here: simply creating a stream, and passing it to client.UploadFile().

Download

This is basically the reverse of UploadFile. In this case, we create the stream locally and download to it:

        void DownloadFile(string remotePath, string localPath)
        {
            using var client = GetClient();
            try
            {
                using var s = File.Create(localPath);
                client.DownloadFile(remotePath, s);
            }
            catch (Exception exception)
            {
                // Log error
                throw;
            }
            finally
            {
                client.Disconnect();
            }
        }

Read

The Read functionality is, perhaps, the most trivial, and the most useful:

        string ReadFile(string remotePath)
        {
            using var client = GetClient();
            try
            {                
                return client.ReadAllText(remotePath);
            }
            catch (Exception exception)
            {
                // Log error
                throw;
            }
            finally
            {
                client.Disconnect();
            }
        }

Depending on your use case, this might be all you need.

Delete

Finally, the Delete method:

        void DeleteFile(string remotePath)
        {
            using var client = GetClient();
            try
            {
                client.DeleteFile(remotePath);
            }
            catch (Exception exception)
            {
                // Log error
                throw;
            }
            finally
            {
                client.Disconnect();
            }
        }

Summary

You might be wondering what the purpose of these wrapper functions are: they do little more than call the underlying SSH library. The only reason I can give, other than that it provides some reusable documentation, is that one day the new version of SSH might be out (or you may choose to switch the Chilkat). Having already done the opposite, I can attest to how much easier that is, if you’re not picking through the main code trying to extract pieces of SSH.NET.

References

https://github.com/dotnet-labs/SftpService/blob/master/SFTPService/SftpService.cs

https://github.com/jorgepsmatos/SftpClientDemo/blob/master/Sftp.cs

Add Storage Queue Message

I’ve written quite extensively in the past about Azure, and Azure Storage. I recently needed to add a message to an Azure storage queue, and realised that I had never written a post about that, specifically. As with many Azure focused .Net activities, it’s not too complex; but I do like to have my own notes on things.

If you’ve arrived at this post, you may find it’s very similar to the Microsoft documentation.

How to add a message

The first step is to install a couple of NuGet packages:

Install-Package Microsoft.Azure.Storage.Common
Install-Package Microsoft.Azure.Storage.Queue

My preference for these kinds of things is to create a helper: largely so that I can mock it out for testing; however, even if you fundamentally object to the concept of testing, you may find such a class helpful, as it keeps all your code in one place.

 public class StorageQueueHelper
{
        private readonly string _connectionString;
        private readonly string _queueName;

        public StorageQueueHelper(string connectionString, string queueName)
        {
            _connectionString = connectionString;
            _queueName = queueName;
        }

        public async Task AddNewMessage(string messageBody)
        {
            var queue = await GetQueue();

            CloudQueueMessage message = new CloudQueueMessage(messageBody);
            await queue.AddMessageAsync(message);
        }

        private async Task<CloudQueue> GetQueue()
        {
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(_connectionString);
            CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
            CloudQueue queue = queueClient.GetQueueReference(_queueName);
            await queue.CreateIfNotExistsAsync();

            return queue;
        }
}

The class above works for a single queue, and storage account. Depending on your use case, this might not be appropriate.

The GetQueue() method here is a bit naughty, as it actually changes something (or potentially changes something). Essentially, all it’s doing is connecting to a cloud storage account, and then getting a reference to a queue. We know that the queue will exist, because we’re forcing it to (CreateIfNotExistsAsync()).

Back in AddNewMessage(), once we have the queue, it’s trivial to simply create the message and add it.

References

https://docs.microsoft.com/en-us/azure/storage/queues/storage-tutorial-queues

An ADR Visual Studio Tool – Part 7 – Adding a Context Menu Item

In my previous post I continued with my little series on writing an extension for Visual Studio by completing the functionality to view existing ADRs within the solution. You can see the first post here

In this post, we’ll cover the process of adding a command to the solution and project context menu. Having completed the screen that will show existing ADRs, we now want to allow the user to right-click on a project or solution and select to add a new ADR:

The first step is to add the command; fortunately, this is a pre-made template, so just select to add a new item (ironically), and pick Command:

This will create you a menu item that will appear under the Tools menu by default, and will display a message box when selected:

There are two things that we need to change about this command: the text (we don’t want it to read “Invoke AddAdrCommand”), and the location (we want it to be available from the right-click context menu of a project). Both of those things are changed in the file AdrPackage.vsct (if your project is called Aardvark, this will be named AardvarkPackage.vsct).

If you have a look in that file, you’ll see something called MyMenuGroup; which is referenced in three places. The first defines what it is:

This is where you can change the command text (as I have above).

The second, where it is:

This initially looks like this:

<Parent guid="guidSHLMainMenu" id="IDM_VS_MENU_TOOLS" />

Which adds the menu to the top level Tools menu; change it to:

<Parent guid="guidSHLMainMenu" id="IDM_VS_CSCD_PROJECT_ADD" />

As I have.

There are other options here.

The third is the ID Symbol:

If you decide to change the name of MyMenuGroup, you will need to do so in all three places above.

Getting the Context of the Current Project

Now that we’ve moved the menu to the context menu, we’ll need to find which project we’re in by accessing the DTE Service – this is retrieved by calling the command:

            var dte = await package.GetServiceAsync(typeof(DTE)).ConfigureAwait(false) as DTE2;

You can then find out what’s selected by accessing the selected hierarchy:

            UIHierarchy uih = (UIHierarchy)dte.Windows.Item(
                EnvDTE.Constants.vsWindowKindSolutionExplorer).Object;
            Array selectedItems = (Array)uih.SelectedItems;

Here’s the full code of the Execute method, to display the selected project:

        private async void Execute(object sender, EventArgs e)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);

            var dte = await package.GetServiceAsync(typeof(DTE)).ConfigureAwait(false) as DTE2;

            UIHierarchy uih = (UIHierarchy)dte.Windows.Item(
                EnvDTE.Constants.vsWindowKindSolutionExplorer).Object;
            Array selectedItems = (Array)uih.SelectedItems;
            foreach (UIHierarchyItem selectedItem in selectedItems)
            {
                // Show a message box to prove we were here
                VsShellUtilities.ShowMessageBox(
                    this.package,
                    selectedItem.Name,
                    "Selected Project",
                    OLEMSGICON.OLEMSGICON_INFO,
                    OLEMSGBUTTON.OLEMSGBUTTON_OK,
                    OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
            }
        }

We’re not far off now – there’s a few little issues, but the main thing that’s left is that we’re not actually adding anything – just displaying a message. The next step is to get it to actually add a file, but we’ll come to that in the next post.

The code for this project can be found here.

References

https://docs.microsoft.com/en-us/visualstudio/extensibility/internals/guids-and-ids-of-visual-studio-toolbars?view=vs-2017

https://docs.microsoft.com/en-us/visualstudio/extensibility/internals/guids-and-ids-of-visual-studio-menus?view=vs-2017

https://stackoverflow.com/questions/51967027/vsix-project-context-menu

https://michaelscodingspot.com/visual-studio-2017-extension-development-tutorial-part-3-add-context-menu-get-selected-code/

https://social.msdn.microsoft.com/Forums/sqlserver/en-US/be61c3bb-aac2-48ea-88ad-883a38b526e2/how-to-add-a-command-button-to-the-project-add-submenu-in-a-vsct-file?forum=vsx

https://stackoverflow.com/questions/52489541/problem-with-dte2-for-running-commands-in-visual-studio

https://docs.microsoft.com/en-us/visualstudio/extensibility/walkthrough-accessing-the-dte-object-from-an-editor-extension?view=vs-2019

https://www.mztools.com/articles/2014/MZ2014009.aspx