Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / programming / algorithm

Using Notepad++ Plugin to Debug Algorithms

4.78/5 (6 votes)
23 Apr 2022GPL34 min read 11.2K   169  
A standard Notepad++ plugin that allows you to use an external DLL containing an encoding algorithm to be tried and tested

Introduction

Sometimes, I have an idea, an algorithm. Sometimes, that algorithm is related to cryptography or encoding and I want to try it directly without having to write an interface... because an algorithm is fun, and the interface is not.

So I thought: why don't I use Notepad++ as an interface? That's why I ended up writing a plugin for Notepad++ (which I'll address as Npp from here on). Then I modified it (the Npp plugin), so that it allows his plugins too... Weird, right? So, now, when I want to test an algorithm, I need two things:

  1. the Npp plugin presented here
  2. a new DLL containing the algorithm I want to test, defined in a class inheriting a very simple interface (defined in the Npp plugin)

Background

This Npp plugin was created by using the Npp plugin template v0.94.00:
https://github.com/kbilsted/NotepadPlusPlusPluginPack.Net/releases/ and then fixing a couple features.

The Notepad++ version used was Npp 8.3.3, 64bit.

Using the Code

The backbone of this plugin is made by the standard plugin classes, automatically generated by the plugin template. These classes may be found in the 'PluginInfrastructure' folder.

The main part is made of the very simple interface IEncoder, and the way it is used in Main.cs.

The Interface is this one:

C#
public interface IEncoder
    {
    string Name { get; }
    bool NeedPassword { get; }
    string Encode(string cleartext, string pass);
    string Decode(string encodedtext, string pass);
    }

Encode and decode are the methods I have to implement to test my algorithm (the parameter 'pass' may be an empty string if password is not needed);
'Name' is, obviously, the algorithm name, that will be used to create menu entries in Npp;
'NeedPassword', if true will open a small box asking for password (both upon encoding and upon decoding).

All you need to test an algorithm is to perform one of these two actions:

  • create (as already explained before) a new ClassLibrary DLL, containing at least a class inheriting from this interface, and put it together with the plugin DLL...
  • or, if you are really lazy, add that class directly inside this Npp plugin

An example of a class inheriting from 'IEncoder' interface is provided in the 'Encoders' folder: 'EncoderBase64.cs':

C#
class EncoderBase64 : IEncoder
    {
    public string Name => "Base64";
    public bool NeedPassword => false;

    public string Encode(string cleartext, string pass)
        {
        byte[] data = Encoding.UTF8.GetBytes(cleartext);
        string result = Convert.ToBase64String(data);
        return result;
        }

    public string Decode(string encodedtext, string pass)
        {
        byte[] data = Convert.FromBase64String(encodedtext);
        string result = Encoding.UTF8.GetString(data);
        return result;
        }
    }

I used the Base64 as an example because it is an encoding algorithm already provided by .NET Framework. As you can see, it is very simple.

Now, how are you going to use/test it ?

  1. Go to the Npp plugins folder: 'C:\Program Files\Notepad++\plugins'.
  2. Create a new folder (named, for example, 'Encoders').
  3. Copy the 'Encoders.dll' in that folder.
  4. Then, optionally, you may put here the algorithm DLL (one or mImage 1any) that contains the mentioned class inheriting from 'IEncoder'.
  5. Open Notepad++.

In the plugins menu, you should find an entry, called 'Encodings', that will contain two entries for every encoding algorithm you created (both the ones in external DLLs and the ones that you lazily put inside the Encodings DLL);

Image 2

The two entries will be named Toxxxxx and Fromxxxxx (where xxxxx is the name of the algorithm, defined in the Name property of the interface.
These two entries will trigger the Encode and Decode methods defined in the interface.

Points of Interest

In the Main.cs, there is the CommandMenuInit method that is called at plugin startup and that is used to initialize the provided encoders and create the respective menus.

C#
internal static void CommandMenuInit()
    {
    AddEncoders();
    AddExternalEncoders();
    }

The first method called AddEncoders will search for classes inheriting IEncoder inside the current assembly, while the other one AddExternalEncoders will search for the same classes, but in all, the external DLLs in the same folder.

The AddEncoders method:

C#
static void AddEncoders(Assembly assem = null)

uses reflection to find the mentioned classes in a given assembly (and when the parameter assem is null, it uses the current assembly as default).

The method that returns the desired classes is GetChildClasses, defined inside the ReflectionUtils class.

In this way, you don't need to declare the encoders used, but you simply need to implement them and then put them somewhere: reflection will find them for you.

Once an encoder (class inheriting from IEncoder) is found, then two entries are added to the Npp menu:

C#
static void AddEncoder(IEncoder encoder)
    {
    PluginBase.SetCommand(countCmd++, $"To{encoder.Name}", 
          () => { ExecuteConversion(encoder.Encode, encoder.NeedPassword); });
    PluginBase.SetCommand(countCmd++, $"From{encoder.Name}", 
          () => { ExecuteConversion(encoder.Decode, encoder.NeedPassword); });
    }

When one of these menu entries is clicked, the ExecuteConversion method is called:

  1. It gets the Npp main window content + optionally asks for a password,
  2. sends this data to the Encoding or Decoding method of your algorithm, and
  3. replaces the main window's content with the result of the algorithm.
C#
string originalfilecontent = GetFileContent();
string password = askPass ? UserInterfaceUtils.InputStringBox
                  ("Insert password", null, true) : "";
string modifiedfilecontent = converter(originalfilecontent, password);
SetFileContent(modifiedfilecontent);

History

  • 24th April, 2022: First version

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)