Cancelling Console.Read

Console.ReadLine and other read methods block the current thread until the user actually write something in the console. Sometimes you want to cancel the read operation when a condition is met. For instance, you can cancel the read operation after a few seconds, or after receiving an event.

Windows provides a function to cancel an IO request: CancelIoEx. To use it, you must get the handle of the IO stream. In our case, it's the handle of the console input stream. You can get this handle by using GetStdHandle and the STD_INPUT_HANDLE constant. By combining the two functions, you can easily cancel a read request. Once the request is canceled, Console.Read throws an exception that you should handle. Depending on the read method used, you must catch the InvalidOperationException or the OperationCanceledException.

The following code start a timer of 10 seconds and call Console.Read. If the user doesn't write anything, the timer cancel the IO request:

class Program
{
    const int STD_INPUT_HANDLE = -10;

    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern IntPtr GetStdHandle(int nStdHandle);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool CancelIoEx(IntPtr handle, IntPtr lpOverlapped);

    static void Main(string[] args)
    {
        // Start the timeout
        var read = false;
        Task.Delay(10000).ContinueWith(_ =>
        {
            if (!read)
            {
                // Timeout => cancel the console read
                var handle = GetStdHandle(STD_INPUT_HANDLE);
                CancelIoEx(handle, IntPtr.Zero);
            }
        });

        try
        {
            // Start reading from the console
            Console.WriteLine("Do you want to continue [Y/n] (10 seconds remaining):");
            var key = Console.ReadKey();
            read = true;
            Console.WriteLine("Key read");
        }
        // Handle the exception when the operation is canceled
        catch (InvalidOperationException)
        {
            Console.WriteLine("Operation canceled");
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Operation canceled");
        }
    }
}

Documentation:

Detecting console closing in .NET

In a console application I developped, I use FiddlerCore to intercept the http requests of an application. FiddlerCore modifies the network settings of Windows. So, before closing the application, you must restore the original network settings. In .NET you can register the Ctrl+C and Ctrl+Break signals with Console.CancelKeyPress. This is the classic way of closing a console application. You can also close the console itself. which will of course kill your application. However, the CancelKeyPress event doesn't handle the closing of the console. Thus, the cleanup code won't run in this case.

Windows lets you register to the console events (Ctrl+C, Ctrl+Break and also the close event) using SetConsoleCtrlHandler. At the beginning of your code, you can call SetConsoleCtrlHandler, so you will be able to cleanup your changes. Here's the complete code:

class Program
{
    // https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms686016.aspx
    [DllImport("Kernel32")]
    private static extern bool SetConsoleCtrlHandler(SetConsoleCtrlEventHandler handler, bool add);

    // https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms683242.aspx
    private delegate bool SetConsoleCtrlEventHandler(CtrlType sig);

    private enum CtrlType
    {
        CTRL_C_EVENT = 0,
        CTRL_BREAK_EVENT = 1,
        CTRL_CLOSE_EVENT = 2,
        CTRL_LOGOFF_EVENT = 5,
        CTRL_SHUTDOWN_EVENT = 6
    }

    static void Main(string[] args)
    {
        // Register the handler
        SetConsoleCtrlHandler(Handler, true);

        // Wait for the event
        while (true)
        {
            Thread.Sleep(50);
        }
    }

    private static bool Handler(CtrlType signal)
    {
        switch (signal)
        {
            case CtrlType.CTRL_BREAK_EVENT:
            case CtrlType.CTRL_C_EVENT:
            case CtrlType.CTRL_LOGOFF_EVENT:
            case CtrlType.CTRL_SHUTDOWN_EVENT:
            case CtrlType.CTRL_CLOSE_EVENT:
                Console.WriteLine("Closing");
                // TODO Cleanup resources
                Environment.Exit(0);
                return false;

            default:
                return false;
        }
    }
}

Generate an HTML form from an object in TypeScript

In the previous post about TypeScript decorators, I used decorators to quickly add validation rules. In this post, we'll use another features of the decorators. TypeScript can automatically add the type of the property to the metadata. Let's see how we can use this information and other custom attributes to automatically generate a form from a class.

The idea is to be able to use the following code:

class Person {
    @editable()
    @displayName("First Name")
    public firstName: string;
    @editable()
    @displayName("Last Name")
    public lastName: string;
    @editable()
    public dateOfBirth: Date;
    @editable()
    public size: number;
}

var author = new Person();
author.firstName = 'Gérald';
generateForm(document.body, author);

Generated form

Let's configure TypeScript to enable decorators and metadata.

  • experimentalDecorators allows to use the decorators in your code.
  • emitDecoratorMetadata instructs the compiler to add a metadata design:type for each property with a decorator.

The project.json should contains the 2 attributes:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
  }
}

The compiler will translate the TypeScript class to JavaScript, and decorates the properties with the required, displayName and design types. Here's an extract of the generated code:

Person = /** @class */ (function () {
    function Person() {
    }
    __decorate([
        editable(),
        displayName("First Name"),
        __metadata("design:type", String) // Added by emitDecoratorMetadata: true
    ], Person.prototype, "firstName", void 0);
    // ...
    return Person;
}());

Let's declare the editable and displayName decorators. You can look at the previous post to get a better understanding of TypeScript decorators.

function editable(target: any, propertyKey: string) {
    let properties: string[] = Reflect.getMetadata("editableProperties", target) || [];
    if (properties.indexOf(propertyKey) < 0) {
        properties.push(propertyKey);
    }

    Reflect.defineMetadata("editableProperties", properties, target);
}

function displayName(name: string) {
    return function (target: any, propertyKey: string) {
        Reflect.defineMetadata("displayName", name, target);
    }
}

Now, you can use the metadata to generate the form. You have to find the editable properties, get their display name to create the label, and their type to create the right input type. For instance, you have to use <input type="number"/> for a property of type number, and <input type="checkbox"/> for a property of type boolean. Then, you have to bind the inputs to the model, so changes in the UI are propragated to the model. The input event should be ok for that.

function generateForm(parentElement: HTMLElement, obj: any) {
    const form = document.createElement("form");

    let properties: string[] = Reflect.getMetadata("editableProperties", obj) || [];
    for (let property of properties) {
        const dataType = Reflect.getMetadata("design:type", obj, property) || property;
        const displayName = Reflect.getMetadata("displayName", obj, property) || property;

        // create the label
        const label = document.createElement("label");
        label.textContent = displayName;
        label.htmlFor = property;
        form.appendChild(label);

        // Create the input
        const input = document.createElement("input");
        input.id = property;
        if (dataType === String) {
            input.type = "text";
            input.addEventListener("input", e => obj[property] = input.value);
        } else if (dataType === Date) {
            input.type = "date";
            input.addEventListener("input", e => obj[property] = input.valueAsDate);
        } else if (dataType === Number) {
            input.type = "number";
            input.addEventListener("input", e => obj[property] = input.valueAsNumber);
        } else if (dataType === Boolean) {
            input.type = "checkbox";
            input.addEventListener("input", e => obj[property] = input.checked);
        }

        form.appendChild(input);
    }

    parentElement.appendChild(form);
}

You can now use the code at the beginning of the post, and it should work:

var author = new Person();
author.firstName = 'Gérald';
generateForm(document.body, author);

Conclusion

Decorators and metadata are very similar to what C# provides out of the box with attributes. It allows you to enrich the code with additional information, and get those information at runtime. In the previous post, I created a generic validation system. Today, I write a generic form generator in a few lines of code. They are lots of possibilities! If you are familiar with reflection in C#, I think you already have hundreds of ideas 😃

Load native libraries from a dynamic location

Today, I had to deal with an uncommon need. In short, the idea is to download a native library (dll) into a temporary directory (not in the application folder), and use its methods. The content of the dll is known, so I want to use the DllImport attribute to easily call the methods of the dll.

The application must work on Windows 10, so I can use a function introduced in Windows 8 AddDllDirectory. This function allows to indicate the paths where the native libraries are. So, you can download the dll and use the AddDllDirectory function to add its path for dll loading.

const uint LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000;

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool SetDefaultDllDirectories(uint DirectoryFlags);

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern int AddDllDirectory(string NewDirectory);

void Initialize()
{
    var downloadDirectory = "temp";
    DownloadDll(downloadDirectory);

    // Indicate to search libraries in
    // - application directory
    // - paths set using AddDllDirectory or SetDllDirectory
    // - %windows%\system32
    SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);

    // Add the directory of the native dll
    AddDllDirectory(downloadDirectory);

    // Use the native dll
    MyMethod();
}

[DllImport("mydll.dll")]
public static extern int MyMethod();

More information about the kernel32 methods:

Comparing files using Visual Studio Code

In the previous post, I showed you how to use Visual Studio to compare 2 files. I also use Visual Studio Code from time to time. And, as every great IDE, Visual Studio Code also have a great diff tool. As with Visual Studio, you can use it to compare 2 versions of the same file if you use a source control. But you can also compare 2 files from your file system.

Comparing files using the User Interface

  1. Open the 2 files in Visual Studio Code
  2. Right click on one file and click "Select for compare"

  1. Right click on the other file and click "Compare file file1 with file2"

You should see the result:

Comparing files using the command line

  • Using Visual Studio Code
"%ProgramFiles%\Microsoft VS Code\bin\code" --diff file1.cs file2.cs
  • Using Visual Studio Code Insiders
"%ProgramFiles%\Microsoft VS Code Insiders\bin\code-insiders" --diff file1.cs file2.cs