Zip and unzip a string of data in memory

I was looking for a way to zip and unzip a file.

Normally, this is not really an issue. There are lots of libraries and NuGet packages available.

But this file was represented to me as a string, some JSON, actually.

So I was looking for a way to convert a string into some zipped format and back. This was harder than expected.

In the end, I wrote a solution myself. Here it is for you to use it, just to save you a lot of time.

Note: This library is available on GitHub. And Visual Studio users can import the NuGet package.

Doorgaan met het lezen van “Zip and unzip a string of data in memory”

Turn your Raspberry Pi into a Personal Assistant using Cortana

Microsoft is constantly updating its latest version of Windows, version 10. For me, as a developer, it’s a wonderful operating system to program for. The UWP apps I build, run on both PC’s, laptops, Windows Surface Hub (up to 84 inches), The Xbox One and even on a Raspberry Pi. Yes, Windows 10 is running on a 35 dollar device.

But before you run to the store to replace your PC, I have to tell you it’s running the core of Windows 10, actually. There is no shell (no menu, no start bar etc.).

So this means you can run one visual (headed) UWP application and multiple background applications. And yes, you will love it!

This is a great interface for kiosk-like devices. And with the latest update (build 15063), it’s easy to add Cortana support.

Cortana is the speech service, available in Windows 10. If you know Siri or Alexa, then you know Cortana. Just ask her a question and she will try to answer it. The answer will be provided by speech or supported by browsers or other visual help.

Let’s take a look on how to enable Cortana on a Raspberry Pi.

Doorgaan met het lezen van “Turn your Raspberry Pi into a Personal Assistant using Cortana”

Ping done easy (by yourself – coders only)

I just connected a headless Raspberry Pi to a wifi adapter but I did not know which IP Address was given. I need that address to make contact with PuTTY.

So I wanted to figure out the IP Address. As a programmer, what should I do? Surf the internet for some nifty tool? Of should I write some code? I have chosen the latter.

So now I ping each port with:

internal class Program
{
    private static void Main(string[] args)
    {
        for (int i = 90; i < 254; i++)
        {
            Console.Write("192.168.0." + i + ": ");
            Console.WriteLine(Ping("192.168.0." + i));
        }
    }
 
    public static bool Ping(string nameOrAddress)
    {
        Ping ping = new Ping();
        try
        {
            var response = ping.Send(nameOrAddress);
            var pinged = (response.Status == IPStatus.Success);
 
            return pinged;
        }
        catch (PingException)
        {
            return false;
        }
    }
}

So start it and take a cup of coffee…

And check the addresses:

ping01

This is simple to use, have fun with it!

 

Getting the token expiration date in Azure Mobile Services

Azure Mobile Services support storing the Oauth user credentials token in the PasswordVault of the OS a client app is running in. This is supported in Windows Universal apps, Xamarin, etc.

See here for the details regarding user credentials from the AMS documentation.

And this is a good thing, now the user does not have to supply the Oauth credentials every time the app is started. We can check if the vault contains the credentials we need and this saves a round trip to the server and an extra input screen. If it is not in the vault, just let the user login using Facebook, Google etc.  and store the token.

But wait: these stored credential tokens are not valid until the end of times. For example, Google credentials are valid for 30+ days. After that, the token stored in the vault is worthless.

Therefor, in the AMS example above a simple check is done by calling the AMS service with a trivial request:

...
try 
{ 
  // Try to return an item now to determine if the cached credential has expired. 
  await App.MobileService.GetTable<TodoItem>().Take(1).ToListAsync();
               // <<-- WHY??? 
} 
catch (MobileServiceInvalidOperationException ex) 
{ 
  if (ex.Response.StatusCode == System.Net.HttpStatusCode.Unauthorized) 
  { 
    // Remove the credential with the expired token. 
    vault.Remove(credential); credential = null; continue; 
   } 
}
...

Here a simple GET is done to check the validity of the token. If it is not valid, it is deleted and the user must login again.

But this is a web call I do not like.

This is done every time user logs in / starts the app, even in an offline scenario!

In an offline scenario I am not even interested in the expiration date…

Is there a better way?

Well, what we get from the Oauth providers, when the user logs in successfully, is a Json Web Token (JWT). And this token can be decoded following the JWT specifications.

This will result in something like:

public class Token
{
    [JsonProperty(PropertyName = "ver")]
    public string Ver { get; set; }
 
    [JsonProperty(PropertyName = "uid")]
    public string Uid { get; set; }
 
    [JsonProperty(PropertyName = "exp")]
    public string Exp { get; set; }
 
    [JsonProperty(PropertyName = "nbf")]
    public string Nbf { get; set; }
 
    [JsonProperty(PropertyName = "aud")]
    public string Aud { get; set; }
}

This token is available on the server as:

App.MobileService.CurrentUser.MobileServiceAuthenticationToken

And the token can be decoded using a Nuget package. The only drawback is that this package is not available on the Universal apps client, only on the Azure Mobile Services server, the backend.

So I wrote this extra API controller:

public class DecodeExpirationController : ApiController
{
  public ApiServices Services { get; set; }
 
  // GET api/DecodeExpiration
  [AuthorizeLevel(AuthorizationLevel.User)]
  public DateTime? Get(string token)
  {
    string adminKey;
 
    if (!Services.Settings.TryGetValue("ADMIN_KEY", out adminKey))
    {
      return null;
    }
 
    try
    {
      var jsonPayload = JWT.JsonWebToken.Decode(token, adminKey, false);
 
      var result = JsonConvert.DeserializeObject<Token>(jsonPayload);
 
      var startOfUtcCount = 
        new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
 
      var expirationDate = startOfUtcCount.
                             AddSeconds(Convert.ToInt32(result.Exp));
 
      return expirationDate;
    }
    catch (JWT.SignatureVerificationException)
    {
      return null;
    }
    catch (Exception ex)
    {
      return null;
    }
  }
}

Note the level of authorization, the user should be logged in by now…

And we can call this WebApi GET on the client:

try
{
  var parameters = new Dictionary<string, string>();
  parameters.Add("token",
    App.MobileService.CurrentUser.MobileServiceAuthenticationToken);
  var result = await App.MobileService.
        InvokeApiAsync<DateTime?>("DecodeExpiration", HttpMethod.Get, parameters);
 
  message = result.HasValue ? result.Value.ToString() : "Nothing returned.";
}
catch (Exception ex)
{
  message = "Exception: " + ex.Message;
}

This should work using with every provider.

The Admin Key is coming from the portal. I have added this appsetting to the configuration of the AMS.

Using this call we get the UTC time of the token expiration date. So store this on the client and check this value every time (give or take a few hours due to correct daylight savings when applicable).

“Don’t shoot me, I’m just the In Process messenger”

In need of an English translation? Please drop me a note.

Voor ons huidige project zochten we naar een goed ontkoppeling tussen de user interface en de communicatie met hardware. Omdat het een WPF applicatie is en we gebruik maken van MVVM draait alles in hetzelfde applicatie.  De hardware willen we real time uitlezen en reageren op het gedrag.

Er werd dus nagedacht over het gebruik van Events. Dat is een prima oplossing voor “Loose coupling”. Maar hierbij is de ontkoppeling maar één kant op. De ‘luisteraar’ kent de verstrekker van de gebeurtenissen want hij moet zich daarop abonneren.

Omdat we MVVMLight gebruiken kregen we de mogelijkheid om nog verder te gaan met ontkoppeling. MVVMLight bezit namelijk ook een Messagebus.

De messagebus kennen we vooral vanuit SOA en Enterprise architectuur:

Maar hier hebben we te maken met messsages die In Process verstuurd worden. Hierbij zijn de volgende klassen te herkennen:

  1. De boodschap, de Message
  2. Diegene die ‘m verstuurt, de Sender
  3. Diegene die zich abonneert op dit type bericht, de Target of algemener, de Receiver
  4. De Messenger

Bij MVVMLight is dit opgelost met een aantal objecten die globaal beschikbaar zijn en via locking threadsafe zijn gemaakt. Hierdoor wordt het mogelijk om overal in de applicatie boodschappen te verzenden en eventueel te ontvangen.

Een boodschap is in het algemeen een overerving  van MessageBase, een standaard klasse beschikbaar in MVVMLight:

public class DeviceMessage : MessageBase
{
  public DeviceMessage(string message)
  {
    Message = message;
  }

  public string Message { get; private set; }

  public override string ToString()
  {
    return "Device message: " + Message;
  }
}

Hier hebben we een DeviceMessage die één property genaamd Message bezit.
Een message wordt verstuurd via de Send methode op de static Messenger:

Messenger.Default.Send<DeviceMessage>
    (new DeviceMessage("Time on device: " + DateTime.Now.ToString()));

Meer is er niet nodig om een boodschap op de Messagebus te zetten. In dit voorbeeld kan ik berichten met een datum/tijd verwachten. Zo kan ik ook vanuit een ViewModel juist een start- of stopcommando doorgeven aan een bepaald apparaat (of beter: een instanciering van iets wat de interface van dat apparaat implementeert). Ik heb geen kennis van de luisteraar, ik weet niet eens of die wel bestaat.

Hoe wordt het bericht ontvangen? Via een constructor of initialisatie heeft een andere partij zich geabonneerd op deze berichten:

Messenger.Default.Register<DeviceMessage>
  (this, true, m => {   Message = m.Message; });

In dit geval wordt de boodschap in op een ViewModel de m.Message uitgelezen en op het scherm getoond (via een bindable property).

Maar er is ook een bonus. De MessageBus is globaal beschikbaar en iedereen kan zich abonneren op berichten. MVVMLight biedt de mogelijkheid om met een Message ook een filtertoken op te nemen.

Messenger.Default.Send<SwitchMessage>
  (new SwitchMessage(this, "AnotherDevice"), "DeviceSwitchToken");

In dit geval kunnen meerdere partijen zich abonneren op een SwitchMessage. Maar door de meegestuurde “DeviceSwitchToken” zal wellicht niet iedereen de SwitchMessage verwerken, ze wachten op zo’n bericht vergezeld met een ander token.

En het is ook mogelijk om zich juist op een scala van berichten te abonneren. Het is mogelijk om alle overervingen van een baseclass te ontvangen:

public class LogProvider : ILogProvider
{
  public void Initialize()
  {
    // log all messages
    Messenger.Default.Register<MessageBase>(this, true, m =>
    {
      Debug.WriteLine(
        String.Format(
           "At {0} we received: {1}", DateTime.Now.ToShortTimeString(), m));
    });
  }
}

Hier heb ik een logger geabonneerd op alle overervingen van MessageBase.

Door de totale ontkoppeling van de zenders en ontvangers kan je het overzicht verliezen. Maar juist door deze logger heb ik een mooie tijdslijn van wat er onderling verstuurd is en kan ik analyseren wat er mis is gegaan. Daarom implementeer ik ook de ToString() zodat ik de messages hun eigen te loggen boodschap kan laten beschrijven.

Ik kan ook als een soort van watchdog een pulse afgeven. Als ik niet de gewenste antwoorden ontvang kan ik ‘alarm slaan’. En dit kan ik doen zonder dat ik de daadwerkelijke implementatie van de te controleren instanties niet ken.

Er zijn in MVVMLight nog een aantal andere boodschappen mogelijk. Ik wil er nog één aanstippen.

MVVMLight kent ook een generic message. Deze bevat standaard een Content property waarin een andere klasse gestopt kan worden. In bovenstaande voorbeelden is steeds gebruik gemaakt van een MessageBase overerving met extra properties. Met de generic oplossing kunnen die properties in de Content geplaatst worden. De Content zier er dan zo uit:

public class SwitchContent
{
  public SwitchContent(int id, string message)
  {
    ID = id;
    Message = message;
  }

  public int ID { get; private set; }

  public string Message { get; private set; }
}

De message wordt een stuk eenvoudiger:

public class GenericSwitchMessage : GenericMessage<SwitchContent>
{
  public GenericSwitchMessage(SwitchContent switchParameter)
        : base(switchParameter)
  {
  }

  public override string ToString()
  {
    return String.Format(
      "Switch message: sender{0}; target={1}", Sender, Target);
  }
}

Het te verzenden bericht wordt nu gecombineerd met de context:

Messenger.Default.Send<GenericSwitchMessage>
  (new GenericSwitchMessage(new SwitchContent (1, "Hallo")));

En het uitluisten ziet er ook wat rustiger uit:

public class LogProvider : ILogProvider
{
  public void Initialize()
  {
    // log all messages
    Messenger.Default.Register<GenericSwitchMessage>(this, true, m =>
    {
      // m.Content.ID
      // m.Content.Message
    });
  }
}

Conclusie:

De MVVMLight Messenger biedt een fraaie oplossing voor de totale ontkoppeling. Er zijn ook andere implementaties beschikbaar (iedere MVVM implementatie lijkt er wel één te bieden) dus het is eenvoudig om er aan te komen en om het eens uit te proberen.

Een WPF StoryBoard starten vanuit het MVVM Viewmodel

 

In need of an English translation? Please drop me a note.

Sinds enige tijd werk ik aan een project waarbij de UI volledige in WPF4 is geschreven. Hierbij heb ik mezelf het doel gesteld om de architectuur volledig op MVVM te baseren.

Dit betekent concreet dat de schermen (de Views) geen code-behind hebben maar via een ViewModel interactie hebben met het Model. Alle schermwijzigingen worden met bindings en commands afgehandeld.

Zelf MVVM implementeren kan vast wel maar er zijn ook veel frameworks: grote, kleine, goede en foute… Uiteindelijk ben ik bij MVVMLight uitgekomen.

Ontwikkelen in WPF blijft door het gebruik van MVVM een feest, ondanks de steile leercurve maar dankzij de strikte scheiding tussen de te tonen data (ViewModel) en de representatie (XAML).

En ik ben ook begonnen met het gebruik van StoryBoards. Dit zijn notaties om de vorm verschijning en plaats van Xaml objecten aan te passen op een tijdslijn. Zo is het mogelijk om animaties in de UI te verwerken die wel degelijk van functioneel nut kunnen zijn.

StoryBoards worden bij voorkeur aan gebeurtenissen gehangen. Als voorbeeld toon ik hier hoe een plaatje langzaam zichtbaar wordt bij het starten van de applicatie door de Opacity in vijf seconden van 0 naar 1 te laten lopen.

Hieronder is de XAML beschreven en de code in het viewmodel. Dit zijn Snippets die zo te combineren zijn met een MvvmLight WPF4 template project.

<Grid x:Name="LayoutRoot"
      Width="284">
  <TextBox FontSize="36"
           FontWeight="Bold"
           Foreground="Purple"
           Text="{Binding WelcomeTitle}"
           VerticalAlignment="Center"
           HorizontalAlignment="Center"
           TextWrapping="Wrap"
           Margin="12,12,42,100" />
  <Image Height="51"
         Name="image"
         Source="Assets\troll-face.png"
         Opacity="0.5"
         Stretch="Uniform"
         HorizontalAlignment="Left"
         Margin="178,182,0,0"
         VerticalAlignment="Top"
         Width="61">
    <Image.Triggers>
      <EventTrigger RoutedEvent="Image.Loaded">
        <BeginStoryboard Name="MyBeginStoryboard">
          <Storyboard>
            <DoubleAnimation Storyboard.TargetProperty="Opacity"
                             From="0"
                             To="1"
                             Duration="0:0:5" />
          </Storyboard>
        </BeginStoryboard>
      </EventTrigger>
    </Image.Triggers>
  </Image>
</Grid>

Er staat een Textbox op de pagina voor de invoer van een string en een plaatje. Dit plaatje bevat een StoryBoard dit wordt afgevuurd als de pagina wordt geladen voor vertoning.

De Textbox is gebonden aan de WelcomeTitle op het ViewModel.

public class MainViewModel : ViewModelBase
{
  public MainViewModel()
  {
    WelcomeTitle = "Hello";
  }

  public const string WelcomeTitlePropertyName = "WelcomeTitle";
  private string _welcomeTitle = string.Empty;
  public string WelcomeTitle
  {
    get
    {
      return _welcomeTitle;
    }
    set
    {
      if (_welcomeTitle == value)
      {
        return;
      }

      _welcomeTitle = value;

      RaisePropertyChanged(WelcomeTitlePropertyName);
    }
  }
}

De uiteindelijke functionaliteit is eenvoudig. Indien de Textbox wordt verlaten zal de Getter van WelcomeTitle uitgevoerd worden.

Het scherm zier er zo uit:

Mijn wens is dat het Troll-plaatje pas getoond wordt als de textbox wordt verlaten en de WelcomeText korter dan drie karakters is.

Maar door de MVVM ‘belemmering’ (ik kan geen (visuele) XAML onderdelen direct vanuit code aanraken en aanspreken) wordt het lastig om StoryBoards aan te spreken. Een Command werkt ook niet want die vuurt juist in de richting van het viewmodel af (bv. indien de gebruiker een knop indruk of via de MVVMLight EventToCommand).

Ik moet iets anders gebruiken en het antwoord is: DataTriggers.

Het is mogelijk om de XAML naar wijzigingen op het ViewModel te laten luisteren en hierop te laten reageren.

Wat heb ik nodig?

  1. Een bindable (boolean) property op het ViewModel. Hiervoor voeg ik de “ShowTroll” property toe aan het ViewModel.
  2. Op het Viewmodel moet de nieuwe property van waarde kunnen veranderen. Dit gebeurt in de Setter van de WelcomeTitle. Als een waarde met een lengte kleiner dan drie karakters voorbij komt, dan wordt de ShowTroll op True gezet.
  3. Een Button in de Xaml. Deze doet op zich niets maar kan wel de Focus krijgen. Als deze aangeraakt wordt, zal de TextBox de focus verliezen en wordt de Setter van WelcomeTitle uitgevoerd. Een dummy dus.
  4. Een DataTrigger op de Image, gekoppeld aan de ShowTroll boolean
  5. Twee StoryBoards. Als de ShowTroll op true wordt gezet, zal de ene afgespeeld worden en anders de andere.

Dit betekent dus dat het viewmodel met een ShowTroll property wordt  uitgebreid en dat deze verandert in de Setter van de WelcomeTitle property:

public class MainViewModel : ViewModelBase
{
  public MainViewModel()
  {
    WelcomeTitle = "Hello";
  }

  public const string WelcomeTitlePropertyName = "WelcomeTitle";
  private string _welcomeTitle = string.Empty;
  public string WelcomeTitle
  {
    get
    {
      return _welcomeTitle;
    }
    set
    {
      if (_welcomeTitle == value)
      {
        return;
      }

      _welcomeTitle = value;
      ShowTroll = (_welcomeTitle.Length < 3); // Force data change
      RaisePropertyChanged(WelcomeTitlePropertyName);
    }
  }

  public const string ShowTrollPropertyName = "ShowTroll";
  private bool _ShowTroll = false;
  public bool ShowTroll
  {
    get
    {
      return _ShowTroll;
    }
    set
    {
      if (_ShowTroll == value)
      {
        return;
      }

      _ShowTroll = value;
      RaisePropertyChanged(ShowTrollPropertyName);
    }
  }
}

En er wordt dus in de Xaml een Button toegevoegd en de Image wordt iets aangepast. Zie dat de Opacity standaard nul (volledige doorzichtig) is. En er zijn twee StoryBoards om de Opacity binnen twee seconden op één of op nul te brengen.

De DataTrigger is aan de ShowTroll property gekoppeld en reageert zowel op True als op False.

<Grid x:Name="LayoutRoot"
      Width="284">
  <TextBox FontSize="36"
           FontWeight="Bold"
           Foreground="Purple"
           Text="{Binding WelcomeTitle}"
           VerticalAlignment="Center"
           HorizontalAlignment="Center"
           TextWrapping="Wrap"
           Margin="12,12,42,100" />
  <Button Content="Button"
          Height="23"
          HorizontalAlignment="Left"
          Margin="31,226,0,0"
          Name="button1"
          VerticalAlignment="Top"
          Width="75" />
  <Image Height="51"
         Name="image"
         Source="Assets\troll-face.png"
         Opacity="0"
         Stretch="Uniform"
         HorizontalAlignment="Left"
         Margin="178,182,0,0"
         VerticalAlignment="Top"
         Width="61">
    <Image.Resources>
      <Storyboard x:Key="TrollBeginStoryboard">
        <DoubleAnimation Storyboard.TargetProperty="Opacity"
                         From="0"
                         To="1"
                         Duration="0:0:2" />
      </Storyboard>
      <Storyboard x:Key="TrollEndStoryboard">
        <DoubleAnimation Storyboard.TargetProperty="Opacity"
                         From="1"
                         To="0"
                         Duration="0:0:2" />
      </Storyboard>
    </Image.Resources>
    <Image.Style>
      <Style>
        <Style.Triggers>
          <DataTrigger Binding="{Binding ShowTroll}"
                       Value="true">
            <DataTrigger.EnterActions>
              <BeginStoryboard>
                <Storyboard>
                  <StaticResource ResourceKey="TrollBeginStoryboard" />
                </Storyboard>
              </BeginStoryboard>
            </DataTrigger.EnterActions>
            <DataTrigger.ExitActions>
              <BeginStoryboard>
                <Storyboard>
                  <StaticResource ResourceKey="TrollEndStoryboard" />
                </Storyboard>
              </BeginStoryboard>
            </DataTrigger.ExitActions>
          </DataTrigger>
        </Style.Triggers>
      </Style>
    </Image.Style>
  </Image>
</Grid>

Hiervoor gebruiken we zowel de EnterActions als de ExitActions.

Dit geeft dus als effect dat als er een langere tekst is ingevoerd, de ‘troll’ niet zichtbaar is.

Maar als de gebruiker een tekst korter dan drie karakters invult, dan wordt binnen twee seconden de Troll zichtbaar.

En indien de tekst weer langer wordt gemaakt, dan is de Troll weer verstopt.

Ik wil in dit voorbeeld aangeven dat het relatief eenvoudig is om complexe UI veranderingen door te voeren door slecht een property op een ViewModel te manipuleren. Hiermee wordt het opeens mogelijk om binnen StoryBoards meerdere objecten te wijzigen. Dit is oogsnoep voor de gebruiker en zo wordt het een visueel feestje voor zowel de ontwikkelaar (of moet ik zeggen: Interactive Designer) en de gebruiker.

Eenvoudig PDF printen in C#

In need of an English translation? Please drop me a note!

Printen in het .Net framework is op zich niet zo lastig. En met de komst van WPF en de bijbehorende XpsDocumentWriter kan bv. handig gebruik gemaakt worden van de FlowDocument klasse en de PrintQueue klasse met bijbehorende CreateXpsDocumentWriter methode. Hiermee kun je zelf je templates opmaken, mergen en printen.

Maar specifiek een aangeboden PDF printen is een stuk lastiger. Met de hand lijkt dit eenvoudig, je start gewoon Adobe Reader of iets dergelijks.

Maar een PDF vanuit code uitprinten is niet eenvoudig. De opmaak binnen PDF’s wordt niet direct door de meeste printers herkend. Op het internet zwerven veel oplossingen rond allemaal met hun eigen voor- en nadelen. Adobe Reader is bv. gratis maar geeft een ‘nag’ screen en er zijn commerciële oplossingen maar die zijn niet bepaald goedkoop.

Voor mijn huidige project heeft het team gekeken naar de mogelijkheid om GhostScript te gebruiken. Dit is een bibliotheek om PDF naar ‘niet-postscript’ om te zetten. We zijn met name geïnteresseerd in PCL, dit kunnen de meeste (HP) laserprinters wel aan. Op GhostScript zit een GNU licentie met beperkt commercieel gebruik.

En wat blijkt, in slechts enkele stappen komt het printen van PDF ook voor .Net ontwikkelaars binnen bereik!

Stap 1: Download GhostScript en installeer deze lokaal. De 32 bits versie is een prettige keuze, vooral in combinatie met de andere benodigdheden. Deze werkt ook met een 64 bits Windows7. Refereer naar de gsdll32.dll in je C# project.

We zijn dus geïnteresseerd in die gsdll32.dll en deze is geschreven in C . Gelukkig heeft Matthew Ephraim al de moeite genomen om deze in C# te verpakken. Deze bibliotheek heet heel toepasselijk GhostScriptSharp. De broncode kan je ophalen bv. op GitHub.

Deze wrapper rond de 32 bits GhostScript dll is heel aardig. Er is via de methode GenerateOutput() de mogelijkheid beschikbaar om een PDF om te zetten naar PCL. Als onderdeel van de instellingen moet wel een ‘Device’ meegegeven worden. Hier heb ik een simpele aanpassing moeten maken op GhostScriptSharp. De GhostscriptDevices enum krijgt nu de extra ljet4 voor PCL support want die ontbrak. Waarom deze in de huidige versie niet aanwezig is, is mij onbekend.

Stap 2: download nu de GhostScriptsharp code, integreer deze in je eigen code en breid de enum even uit met de keuze ‘ljet4’. Zie dat die broncode standaard naar de 32 bits versie van GhostScript refereert.

Als laatste moet nu de, door GhostScript uit de PDF, gegenereerde PCL naar de printer gestuurd worden. Jouw printer dient dus wel PCL te ondersteunen :-).

Hiervoor gebruiken we een voorbeeld op de MSDN van Microsoft zelf. Dit voorbeeld gebruikt de Win32 Spooler Application Programmer Interfaces (APIs) en dit werkt ook prima samen met Windows7. De in het voorbeeld genoemde RawPrinterHelper klasse is prima. Er zitten wel enkele geheugenlekjes in (geen usings op de FileStream en de BinaryReader) dus een kleine aanpassing is gewenst.

Stap 3: Integreer de voorbeeldcode van Microsoft in je project en repareer even de RawPrinterHelper.SendFileToPrinter() methode.

Nu wordt het mogelijk om alles bij elkaar te brengen in één aanroep:

string pdfFileName = "test.pdf";
string tempFileName =
    Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
GhostscriptSettings gss = new GhostscriptSettings
{
  Size = new GhostscriptPageSize() { Native = GhostscriptPageSizes.a4 },
  Device = GhostscriptDevices.ljet4,
  Resolution = new Size(600, 600)
};

GhostscriptSharp.GhostscriptWrapper.GenerateOutput
    (pdfFileName, tempFileName, gss);
RawPrinterHelper.SendFileToPrinter(printerName, tempFileName);
File.Delete(tempFileName);

Eerst stellen we een naam samen voor een tijdelijk bestand. Vervolgens laten we via GhostScript vanuit een aangeboden PDF dit tijdelijk bestand vullen met PCL code (op A4 formaat met een resolutie van 600 dpi). En vervolgens laten we dit PCL bestand ruw naar de printer sturen. En achteraf verwijderen we natuurlijk nog even het tijdelijk bestand.

Dit moet voldoende zijn. Natuurlijk moet deze oplossing uitvoerig getest worden doordat het een heleboel zaken integreert… Maar in onze testopstelling functioneert het heel aardig. Persoonlijk had ik liever niet met een tijdelijk bestand op schijf gewerkt, maar met bijvoorbeeld een memorystream.

amBX lights met TFS 2010, een Deja Vu

Eind 2009 (het was de nacht voor kerstmis, je ziet de kerstboom op de achtergrond) heb ik een artikeltje geplaatst over het aansturen van ledverlichting met Team Foundation Service 2008. Het was een ludieke actie rond eenzelfde oplossing van een collega (gebaseerd op een dure electronica) maar ik gebruikte gewoon een lampensetje van 25 euro gekocht bij een computerzaak tesamen met een gratis DLL. (https://sandervandevelde.wordpress.com/tag/ambx-lights/ )

Deze oplossing was gebaseerd op het aanpassen van het buildscript en wat handig omgaan met WCF. Ik heb destijds nog gekeken of ik het ook aan de praat kreeg met TFS 2010 maar de buildscripts waren inmiddels door Workflow Foundation (WF4) vervangen en het paste dus niet meer op mijn laptopschermpje.

Vandaag heb ik mijn amBX setje uit het vet gehaald voor een ander klusje waarbij de lampen ook hun opwachting mogen maken. Ik kreeg mijn setje zelfs aan de praat op Windows 7 64 bits. Het kan nog steeds in combinatie met de oude 1.10 drivers! En dus dacht ik, er staat nog een klusje open…

Maar nu hebben we de Team Foundation Service API. Haal het even op… Na installatie staan er een hoop assemblies in C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0

Onderstaande oplossing werkt prima. Ik start de app even op en zie de status in de lampen terug.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using amBXLibrary;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Common;

namespace TfsBuildNotify
{
  internal class Program
  {
    private static int Main(string[] args)
    {
      try
      {
        string uri = "http:// s erver. c om:8080/tfs/prd";
        string teamProjectName = "teamprojectname";
        string buildDefinitionName = "builddefinitionname";
        string userName = "username";
        string password = "password";
        string domain = "domainname";
        bool readKey = true;
        using (var TeamProjectCollection =
          new TfsTeamProjectCollection(new Uri(uri),
          new NetworkCredential(userName, password, domain)))
        {
        TeamProjectCollection.Connect(ConnectOptions.IncludeServices);
        TeamProjectCollection.EnsureAuthenticated();
        IBuildServer buildServer =
          (IBuildServer)TeamProjectCollection.GetService(typeof(IBuildServer));
        var buildDefinitions = buildServer.QueryBuildDefinitions(teamProjectName);
        IBuildDefinition myBuildDefinition = null;
        foreach (var buildDefinition in buildDefinitions)
        {
          if (buildDefinition.Name == buildDefinitionName)
          {
            Console.WriteLine(buildDefinition.Name);
            myBuildDefinition = buildDefinition;
            break;
          }
        }
        if (myBuildDefinition != null)
        {
          var builds = buildServer.QueryBuilds(myBuildDefinition);
          // find current build in progress
          IBuildDetail myBuild = (from build in builds
            where build.Status == BuildStatus.InProgress
            select build).FirstOrDefault();
          if (myBuild == null)
          {
            // find last build started
            myBuild = (from build in builds
              orderby build.StartTime descending
              select build).FirstOrDefault();
          }
          if (myBuild != null)
          {
            // Check state of found build
            try
            {
              switch (myBuild.Status)
              {
                case BuildStatus.Failed:
                  amBXWrapper.PlayRed(200, 10);
                  break;
                case BuildStatus.InProgress:
                  amBXWrapper.PlayWhite(200, 10);
                  break;
                case BuildStatus.PartiallySucceeded:
                  amBXWrapper.PlayRed(1000, 5);
                  break;
                case BuildStatus.Stopped:
                  amBXWrapper.PlayRed(1800, 5);
                  break;
                case BuildStatus.Succeeded:
                  amBXWrapper.PlayGreen(1800, 5);
                  break;
                }

                Console.WriteLine("State: " + myBuild.Status.ToString());
              }
              catch (Exception ex)
              {
                throw new ArgumentException("amBX error: " + ex.Message);
              }
            }
            else
            {
              // no build found
              amBXWrapper.PlayWhite(1800, 5);
              Console.WriteLine("Found: None");
            }
          }
          if (readKey)
          {
            Console.ReadKey();
          }
        }
        return 0;
      }
      catch (Exception ex)
      {
        Console.WriteLine("Error: " + ex.Message);
        Console.ReadKey();
        return 1;
      }
    }
  }
}

Eerst haal ik de TeamProjectCollection van de server via mijn credentials. Mocht je tegen de beveiliging van TFS aanlopen, kijk dan eens naar deze blog . Daar staat prima uitgelegd hoe je met de credentials moet omgaan.

Vervolgens haal ik via de buildServer de BuildDefinitions voor ons teamproject op. Hierbij wil ik er speciaal eentje uitpikken…

En van die definitie probeer ik de meest recente build te achterhalen. Eerst kijk ik of er een build “in progress” is. Indien dit niet het geval is, probeer ik de laatst gestarte build te achterhalen.

Achteraf stuur ik de lampen aan nav. de status van de gevonden build. Het is dus een simpele oplossing voor een simpel probleem. De Build class ondersteunt ook events maar daar ben ik niet verder op in gegaan. Ook kan, indien je voldoende rechten hebt, een build beïnvloed worden (start/stop) of zelfs volledig met code aangemaakt worden.

Succes met je eigen builds.

Een Sharp randje aan SQL Server

Afgelopen week is een kopie van onze SQL Server database ‘anoniem gemaakt’.
Dit betekent dat informatie over cliënten niet meer naar die specifieke cliënten
te herleiden is. Ook het willekeurig husselen van de informatie is niet gewenst.
Het feit dat iemand in de database gevonden kan worden, geeft eigenlijk al
informatie prijs over die persoon.

We hebben dus een aantal kolommen in de database gekozen om met random informatie te vullen (oa. achternaam, voornaam, sofinummer). Een ‘random tekst’ generator in SQL was een uitdaging.

Een generator in C# schrijven en toevoegen in SQL Server was ook een uitdaging, maar dat vonden we leuker :-).

The Shining, hakbijl

Uiteindelijk is dit toevoegen heel eenvoudig, in een mum van tijd kan de
mooiste C# code onder SQL Server geschoven worden. Hieronder staan de 11 stappen om dit te bereiken en eventueel weer op te ruimen:


STAP 1;
Kies een nieuw project in SQL Server:

New SQL Server project

Kies voor een SQL Server een database via het dialoog:

Add database reference

Er kan nog een extra melding komen over het toestaan van debuggen via deze
SQL Server. Beantwoordt ook deze vraag naar keuze.

STAP 2;

Voeg hier een User-Defined functie aan toe:

Add User-Defined Function

Er staat nu een lege methode met de uitdagende tekst: // Put  your code here

STAP 3;
Schrijf dus die code:

De code

Deze methode levert een willekeurige tekst met een bepaalde lengte op,
met daarin letters of cijfers. De nul is voor het gemak weggelaten om
voorloopnullen te voorkomen. Let hierbij op de afwijkende types: bv. SqlInt32
ipv. een int.

STAP 4;

Ben je tevreden met de code? Build en Deploy (rechtermuis-klik op project niveau) het project dan:

Build!

STAP 5;

Open nu SQL Server en ga naar de betreffende database. Zie dat in de betreffende database de functie toegevoegd is (bij de scalar value function). Deze is nu (vrijwel zeker) nog niet aan te roepen… Type maar eens:

select dbo.RandomStringFunction(40, 0)

Dit geeft:

Msg 6263, Level 16, State 1, Line 1

Execution of user code in the .NET Framework is disabled. Enable “clr
enabled” configuration option.

De SQL Server staat nu nog niet toe om CLR (C#) code uit te voeren. Dus we
enablen dit:

sp_configure ‘clr enabled’, 1

go

RECONFIGURE

go

STAP 6;

En zie dat het werkt…De functie geeft een fraai antwoord.

Zie overigens ook dat het inlezen van de DLL eenmalig heel traag is. Het
uitvoeren van de C# functie zelf is snel, HEEEL snel. In dit voorbeeld stel ik
tekst of getallen samen uit random gekozen karakters. De seed is
hierbij automatisch gekozen en afgeleid van de huidige datum/tijd.

We gebruiken de functie voor dus het anonimiseren van data waarbij de functie
steeds opnieuw aangeroepen wordt om een veld in een rij te ‘overschrijven’. Nu
bleek dat tientallen regels toch dezelfde waarde kregen. De seed interval is dus
veel langer dan de aanroep van een enkele functie. Een
Thread.Sleep van welgeteld 1 milliseconde was voldoende om dit
probleem te pareren. Dit is overigens nauwelijks meetbaar in de totale
werking.

Toch is dit niet de meest efficiente code. Bij grote aantallen zal die
duizendste seconde wel gaan tellen. In dat geval kan beter eenmalig een lijst
aangemaakt worden. Dan kan de Random.Next meerdere keren aangeroepen worden.
Voor dit voorbeeld doen we het er maar even mee 🙂

STAP 7;

Mocht het wenselijk zijn dan kan het CLR gebruik later weer uit gezet worden:

sp_configure ‘clr enabled’, 0

go

RECONFIGURE

go

STAP 8;
Vanuit Visual Studio is een deployment niet meer mogelijk… Hoe moet
dit automatisch gedeployed en geundeployed worden zonder
gebruik te maken van Visual Studio? Dit kan ook geheel in SQL indien de DLL
beschikbaar is.

Als eerste stap moet de DLL binnen SQL Server opgenomen worden. Plaats de dll
in c:\:

CREATE ASSEMBLY SqlServerRandomProcedure FROM
‘C:\SqlServerRandomProcedure.dll’

Hiermee is de DLL veilig binnen SQL Server opgeslagen, de DLL kan hierna van
schijf verwijderd worden. Hiermee is het ook niet meer mogelijk om de werking
van SQL Server te veranderen door de DLL te veranderen, hackers hebben het
nakijken.

STAP 9;
Vervolgens moet de methode uit de DLL beschikbaar gesteld worden binnen
de database. Creëer hiervoor de betreffende methode:

CREATE FUNCTION [dbo].[RandomStringFunction](@length [int],
@OnlyAlphaNumeric [bit])

RETURNS [nvarchar](4000) WITH EXECUTE AS CALLER

AS

EXTERNAL NAME

[SqlServerRandomProcedure]

.[UserDefinedFunctions].[RandomStringFunction]

STAP 10;
Indien SQL Server inmiddels toestaat om CLR code uit te voeren dan kan
nu de functie aangeroepen worden:

select dbo.RandomStringFunction(4, 0)

(Eventueel moet dus nog die sp_configure voor CLS gebruik uitgevoerd
worden).

STAP 11;

Wil je deze nieuwe functionaliteit na gebruik weer verwijderen? Laat dan eerst de functie vervallen:

DROP FUNCTION [dbo].[RandomStringFunction]

Uiteindelijk kan de DLL uit SQL Server verwijderd worden:

DROP ASSEMBLY SqlServerRandomProcedure

Deze laatste twee stappen zijn ook nodig indien de functie met Visual Studio
gedeployed is.

Hiermee is bewezen dat het echt eenvoudig is om een speciale functie in C# te
schrijven welke in SQL Server aangeroepen kan worden. Dit is dus een enorme
verrijking op de standaard T-SQL mogelijkheden.

Type inference of interferentie?

Met de komst van Visual Studio 2008 en C# 3.0 zijn we weer met een hele golf
aan taalvernieuwingen overspoeld. Waar generics het meest opvallende was bij C# 2.0, is nu toch wel LinQ het nieuwe stokpaardje. Hierbij moet wel vermeld worden dat LinQ niet mogelijk zou zijn zonder de hulp van de mindere goden zoals Lambda expressies, Extension Methods, Anonymous Types en Type Inference.

De laatste uit het rijtje is eigenlijk de simpelste vernieuwing, het makkelijkste te gebruiken maar het meest omstreden.

Hoewel aan Type Inference zelfs een Wikipedia pagina is gewijd, is het concept erg eenvoudig.

C# is als taal Type Safe. Dit betekent dat iedere instantie van een klas
van een bepaald type is en gedurende zijn hele levensduur dat ene type zal
uitbeelden met al zijn beperkingen. Dit uit zich in b.v.

Button mijnButton = new Button();

Ok, en waar blijft dan Type Inference? Nou, met C# 3.0 kunnen we ook
schrijven:

var mijnButton = new Button();

Het keyword var beschrijft toch dat de variabele een Button is want de
compiler kan dat afleiden uit de assignment. Laat het duidelijk zijn: Het is
geen Variant, geen Late binding en ook geen soort van base class waar alles naar
gecast kan worden. Na deze instanciering zal mijnButton alleen het gedrag van
een Button kunnen tonen, het blijft een Type Safe declaratie.

Type Inference is kort door de bocht een verkorte notatie. Prettige
bijkomstigheid is dat pas tijdens het moment van compileren het type echt wordt
vastgesteld. Mocht ik als ontwikkelaar van menig veranderen dan hoef ik alleen
maar de assignment aan te passen.

Waarom is dit in de taal opgenomen? Microsoft had deze notatie nodig voor
LinQ, en speciaal door het introduceren van Anonymous Types. Met C# 3.0 kunnen namelijk ‘on the fly’ nieuwe type safe types gedefinieerd worden. Dus wordt het lastig voor de ontwikkelaar om vooraf alle mogelijke types te declareren terwijl de compiler al lang weet wat het type zal uitbeelden.

Nu blijken er inmiddels drie kampen te zijn ontstaan over zoiets simpels als var.

Ook binnen ons ontwikkelteam is inmiddels de discussie over de reikwijdte van
het gebruik van Type Inference gevoerd.

Zelf ben ik voorstander om het zo veel mogelijk te gebruiken. Het is een nieuwe taaleigenschap die gemakkelijk toegepast kan gaan worden en het leven van een ontwikkelaar weer een stukje makkelijker maakt (minder typen, minder code, sneller refactoren). Ook kan je er niet eens aan ontsnappen zodra de eerste LinQ code ingetyped gaat worden.

Ik weet het, in .Net 1.0 hadden we het ook niet nodig en die
code compileert ook nog steeds prima. En ja, je bent overgeleverd aan de
compiler en editor om te achterhalen welke klasse achter een var schuil gaat.
Maar dat vind ik niet voldoende om Type Inference in de ban te doen, ik heb de
tooling altijd tot mijn beschikking.

Het is ook steeds weer wennen aan de nieuwe taaleigenschappen. Iedere drie jaar is er een kleine revolutie met de introductie van een nieuwe compiler. We zitten dan weer in de, zeg maar, ontkennende fase. Maar na de berusting blijkt dat het helemaal niet nodig om exact te weten welke types aangemaakt of geïnstancieerd wordt. Het is de kunst van het loslaten, de compiler kan het type prima controleren en ik hoef mij alleen maar te concentreren op het gedrag wat de variabele om dat moment moet tonen. Wel moeten variabelenamen nog beschrijvender gekozen worden.

Helaas bleken al onze argumenten voor het toepassen van Type Inference niet voldoende. Het voornaamste tegenargument was dat de code minder leesbaar was buiten Visual Studio…

Hmm, wie gaat code tegenwoordig bekijken met een andere viewer dan Visual Studio? Nou ehh, collega’s die met TeamSystem werken.

En dat is vreemd, Team System is een prachtige aanvulling op Visual Studio en dat wordt als argument naar voren gebracht.

Wat blijkt? Bij het uitvoeren van peer code review worden regelmatig aanpassingen in de code vergeleken met vorige versies en daar heeft Microsoft enkel aardige (difference) viewers voor beschikbaar. Sterker nog, zowel binnen Visual Studio als met de Web Access client van Team System is broncode op eenzelfde manier te vergelijken. Er daarbij is er geen beschikking over Intellisense, zodat het gekozen type niet te zien is, zoals in Visual Studio.

Dit doet mij voorkomen als dat de test (de peer review) het resultaat (de ingetypte code) beïnvloedt, een principe uit de kwantummechanica en gepubliceerd door Werner Heisenberg in 1927.

Peer reviews zijn onmisbaar en broncode moet correct en eenduidig gedrag vertonen. Broncode moet ook transparant en testbaar zijn. Maar het is vreemd dat de manier waarop broncode reviews worden uitgevoerd, invloed heeft op het intypen van diezelfde broncode. Waar bij Star Trek al lang een oplossing is uitgevonden voor deze dualiteit in hun transporters wordt de moderne C# ontwikkelaar teruggeworpen naar 2003.

Kan iemand vertellen of in Visual Studio 2010 eindelijk intellisense in het scherm voor het vergelijken van broncode is gebouwd? Dan hoef ik nog maar twee jaartjes te wachten… Beam me up, ScottGu!