martedì 29 marzo 2016

Log Tail in Windows

Domandandomi se ci fosse un comando simile a tail -f in Windows mi sono imbattuto in questo comando PowerShell:

Get-Content myfile.log -Wait

Proprio ora a Build 2016 hanno annunciato una shell bash nativa per Windows 10. Straordinario

lunedì 28 marzo 2016

Come utilizzare le API WinRT di Windows 10 in una applicazione desktop console C#

Sono entusiasta delle possibilità offerte dalle api WinRT di Windows 10 nelle applicazioni UWP, peccato usarle solo in app "sandboxed"
In realtà la maggior parte di queste API si possono utilizzare anche in applicazioni classiche desktop.
Vediamo ad esempio come utilizzare le librerie OCR in un programma a riga di comando che prende in ingresso un file contenente un'immagine e genera un file .txt con il risultato.

Con Visual Studio 2015 genera un nuovo progetto Visual C#->Windows->Classic Desktop->Console Application OCRConsole
  • Con il pulsante destro sul progetto fai Unload Project
  • Con il pulsante destro sul progetto fai Edit OCRConsole.csproj
  • Aggiungi <TargetPlatformVersion>10.0</TargetPlatformVersion> sotto <TargetFrameworkVersion>
  • Con il pulsante destro sul progetto fai Reload Project
  • Add Reference->Browse Windows.winmd da C:\Program Files (x86)\Windows Kits\10\UnionMetadata
  • Add Reference->Browse System.Runtime.WindowsRuntime da C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\System.Runtime.WindowsRuntime.dll. Nelle proprietà di System.Runtime.WindowsRuntime setta "Copy Local=False"
  • Se ottieni in compilazione un errore del tipo 'await' requires that the type 'Windows.Foundation.IAsyncOperation' have a suitable GetAwaiter method., verifica che il codice inizi con using System; Verifica anche che nel progetto il percorso System.Runtime.WindowsRuntime.dll sia assoluto

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Globalization;
using Windows.Graphics.Imaging;
using Windows.Media.Ocr;
using Windows.Storage;

namespace OCRConsole
{
    class Program
    {
        static private OcrEngine ocrEngine;
        static private string filePath;

        static async Task OCRAsync()
        {
            // Do any async anything you need here without worry
            // Load image from install folder.
            var file = await StorageFile.GetFileFromPathAsync(filePath);
            using (var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
            {
                // Create image decoder.
                var decoder = await BitmapDecoder.CreateAsync(stream);
                // Load bitmap.
                var bitmap = await decoder.GetSoftwareBitmapAsync();
                // Extract text from image.
                OcrResult result = await ocrEngine.RecognizeAsync(bitmap);
                // Display recognized text.
                File.WriteAllText(Path.ChangeExtension(filePath, "txt"), result.Text, Encoding.Default);
               
            }
        }

        static void Main(string[] args)
        {
            if (args.Length != 1)
            {
                Console.WriteLine("Usage: OCRConsole <filepath>");
                return;
            }

            filePath = args[0];
            if (!File.Exists(filePath))
            {
                Console.WriteLine("The file {0} doesn't exist", filePath);
                return;
            }
           
            // Init OCR engine with Italian language.
            ocrEngine = OcrEngine.TryCreateFromLanguage(new Language("it"));
            OCRAsync().GetAwaiter().GetResult();
           
        }
    }
}

Una volta per ottenere questo risultato ci voleva un SDK apposito, tonnellate di codice C++ e qualche giorno di sviluppo.