//Build 2017 Day1 – Sessions

Pour cette première journée j’ai participé à plusieurs sessions:

1- Bring your desktop apps to UWP and the Windows Store using the Desktop Bridge

Dans cette session on nous a expliqué le but du bridge => Créer un pont entre l’ancien App model de Windows qui existe depuis les premières versions de celui-ci et le nouveau App model qui existe depuis 2011/2012 avec Windows 8.

Avantages:

  • Simplicité
  • Pas d’élévations de droit lors de l’installation/utilisation
  • Installation sûre (qui ne va pas aller modifier les clés de registre par exemple)
  • Offrir la possibilité d’avoir des MAJ automatiques et différentielles
  • Ouverture à la monétisation simple (via le store)
  • ….

Le fonctionnement est assez simple, il faut fournir un MSI à l’outil, celui-ci va le convertir en APPX (Si la conversion ne marche pas, c’est qu’il faut changer du code qui n’est pas supporté (ou pas encore) par le Bridge)

Le Bridge est en constante évolution avec le support de plus en plus d’API: la règle est simple, toutes les API publiques – non cassées – sont ou seront supportées.

Les dernières nouveautés sont:

  • Support du préinstall
  • Objets com
  • Déclaration de règles firewall
  • Support du wack
  • Support des applications sans MSI (un .exe avec des dll)

La version complète d’office qui sera bientôt dans le store utilise ce même Bridge !

 

2- Bot capabilities, patterns and principles

Cette session est orientée sur les patterns qu’il faut/qu’il ne faut pas utiliser pour créer un bot, exemple :

  • A NE PAS FAIRE => un bot avec un seul dialog (1 question) qui utilise 100 LUIS intents (choses que le bot peut faire) avec 100 différents énoncés == 10000 diférentes choses que l’utilisateur peut dire (ET n possibilités non prévues)
  • A Faire => Guider l’utilisateur, avec des questions précises, avec une UI (questions avec des boutons de réponses)

3- Cortana skills development: Get started

Super nouveauté qui ouvre énormément de  possibilités . Malheureusement inutile en France pour l’instant, Cortana skills n’est disponible qu’aux USA et on a pas d’informations d’infos sur la date de disponibilité dans les autres pays.

Cortana skills permet de déployer des skills (l’équivalent d’un bot) directement dans Cortana (PC, téléphone ou autre device qui supporte Cortana)

Un skill c’est une « unité d’intelligence conversationnelle » qui aide les utilisateurs via un service, ou autrement un Bot qui utilise le channel Cortana (et donc l’UI de cortana) pour interagir et fournir de l’information à un utilisateur.

L’authentification avec un compte d’une organisation est possible, la récupération des données de l’utilisateur aussi (par le service/bot)

On a eu droit à deux démos :

  • Commande d’une pizza Domino’s (sans application installée sur le PC)
  • Recherche d’un collègue pour faire du code review (le bot va chercher de l’information avec Microsoft Graph => scénario avec l’authentification)

Ressources dispo ici

4- Snapshot debugging and profiling in Microsoft Azure: Next generation diagnostics for your in-production cloud apps 

Super session qui montre les futures fonctionnalités de Visual Studio/Azure (qui seront complètement ouverts en preview à la fin de l’été).

  • Snapshots

Cette nouvelle fonctionnalité d’Application Insights permet de prendre un snapshot de l’application en prod quand une exception se déclenche via la télémétrie.

On peut aussi via Visual Studio Enterprise avoir des snappoints ( l’équivalent d’un point d’arrêt mais pour faire un snapshot et non pas arrêter l’exécution du code) et des logpoints (qui nous permettent d’insérer des logs sans redéployer l’application ni écrire du code !)

Les snapshots sont téléchargeable et peuvent être rejoués dans Visual studio.

  • Application Insight Profiler

Outil pour analyser et améliorer les applications déployés dans Azure pour plus détails voir https://azure.microsoft.com/en-us/blog/app-insights-app-map-and-profiler/

//Build 2017 Day1

Cette année la build est de retour à la « maison » à Seattle. Avec @timothelariviere nous couveront les trois jours de la conférence.

Contrairement aux anciennes version de la //Build, cette année la première journée est consacrée à l’IA et Azure

Les annonces de la Keynote:

  • Quelques chiffres:
    • 500 millions de devices sous Windows 10 !
    • 100 millions d’utilisateurs actifs office 365
    • 12 millions d’organisations dans l’Azure Active Directory
    • 90% des TOP 500 entreprises utilisent le Cloud de Microsoft
  • Microsoft passe du Mobile First Cloud First au Intelligent Cloud/Intelligent Edge
  • Azure Iot Edge (fonctionne sur Windows/linux et les petits devices)
  • Plusieurs démos qui démontrent l’utilisation de l’IA : Workplace safety (analyse en temps réel de flux vidéos pour détecter les risques sur un chantier) , Intelligent meetings, Cortana …
  • Azure :
    • Cloud shell : CLI disponible directement dans la version Web (et app) d’azure, sans rien installé !
    • Azure mobile App dispo sous iOS et Android (la version UWP arrive bientôt)
    • Debug de la prod avec des snapshot (super feature)
    • MySQL et PostgresSQL as a service (grosse annonce)
    • Azure Cosmos DB
    • Azure Stack (l’extension d’azure pour avoir un « Azure en local »)
  • Visual Studio 2017 for mac passe en GA avec .Net Core 2.0 en preview !
  • Support des Azure Functions et des logic Apps dans VS 2017
  • Cognitive Services : 4 nouveaux services : Bing custom search, custom Vision Service, Custom Decision Service et Video indexer
  • Bots : Trois nouveaux canaux : Cortana Skills, Skype for Business (ENFIN !) et Bing.
  • AI translation for PowerPoint : plugin de traduction en live d’une présentation PowerPoint

Et pour finir, je vous laisse admirer cette vidéo =>

Hey Cortana, do you speak JavaScript?

In this article I will try to describe every steps to use Cortana with your JavaScript UWP app.

The first step is to create an xml file that represents the Voice Command Definition :

<?xml version="1.0" encoding="utf-8" ?>
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.2">
  <CommandSet xml:lang="fr-fr" Name="VDM_fr-fr">
    <CommandPrefix> VDM, </CommandPrefix>
    <Example> Affiche les dernières VDM </Example>
    
    <Command Name="showlast">
      <Example> Affiche les dernières VDM </Example>
      <ListenFor RequireAppName="BeforeOrAfterPhrase"> Affiche [les] dernières </ListenFor>
      <ListenFor RequireAppName="BeforeOrAfterPhrase"> Affiche [mes] dernières </ListenFor>
      <ListenFor RequireAppName="BeforeOrAfterPhrase"> Ouvre [les] dernières </ListenFor>
      <ListenFor RequireAppName="BeforeOrAfterPhrase"> montre [moi] [les] dernières </ListenFor>
      <Feedback> affichage des dernières VDM </Feedback>
      <Navigate />
    </Command>
    <Command Name="showcategorie">
      <Example> Affiche les VDM de travail</Example>
      <ListenFor RequireAppName="ExplicitlySpecified"> ouvre les {builtin:AppName} [de] {cat}</ListenFor>
      <ListenFor RequireAppName="ExplicitlySpecified"> affiche les {builtin:AppName} [de] {cat}</ListenFor>
      <Feedback> ouverture des VDM de {cat}</Feedback>
      <Navigate />
    </Command>

    <PhraseList Label="cat">
    </PhraseList>
  </CommandSet>
  <CommandSet xml:lang="en-us" Name="VDM_en-us">
    <CommandPrefix> FML </CommandPrefix>
    <Example> Show me the latest </Example>

    <Command Name="showlast">
      <Example> Show me the latest </Example>
      <ListenFor RequireAppName="AfterPhrase"> show [me] the latest </ListenFor>
      <ListenFor RequireAppName="AfterPhrase"> open the latest </ListenFor>
      <ListenFor RequireAppName="AfterPhrase"> display the latest </ListenFor>
      <Feedback>  display of the last FML</Feedback>
      <Navigate />
    </Command>

    <Command Name="showcategorie">
      <Example> Displays the FML of love </Example>
      <ListenFor RequireAppName="ExplicitlySpecified"> Opens the  {builtin:AppName} [of] {cat}</ListenFor>
      <ListenFor RequireAppName="ExplicitlySpecified"> Displays the {builtin:AppName} [of] {cat}</ListenFor>
      <Feedback> opening FML of {cat}</Feedback>
      <Navigate />
    </Command>

    <PhraseList Label="cat">
    </PhraseList>
  </CommandSet>

</VoiceCommands>
  • In this file the root element is the VoiceCommands Element, it’s contains a list of commandSet elements. Each commandSet is for a language.
    • An commandSet contains a list of command (and others things …)
      • A command is a “command” and contains an example, and multiple elements of ListenFor, a feedback element, and an instruction element (navigate in the first sample) that explicitly specifies that this command will navigate to your app.
        • ListenFor is the command phrase, it has a RequireAppName attribute that specifies where the app name can appear in the voice command.
      • A PhraseList that contains multiple item, each Item specifies a word or phrase that can be recognized to initiate the command that references the PhraseList (optional). You can optionnaly load dynamically a list of items from your code.

You have to be very careful, when you write this file! If you don’t respect the structure or If you miss an element, the Cortana API will fall in error without any information*.

The final step.
Instantiate your new XML file of VCD, in your JavaScript code.

In this following code, I call initCortana function to initialize the VCD file using de VoiceCommandDefinitionManager API located in the Windows.ApplicationModel.VoiceCommands namespace.

You have to pass your xml file to the « installCommandDefinitionsFromStorageFileAsync » function. If everything it’s not OK the callback of the promise returns a error and you pass by:

console.error(‘error file vdmvoicecommands.xml’, er);

In this case: check and re check an re re re check your VCD file 🙂

If the file was initialized correctly, you could add a list of items to populate the phrase lists.



    var wap = Windows.ApplicationModel.Package;
    var voiceCommandManager = Windows.ApplicationModel.VoiceCommands.VoiceCommandDefinitionManager;

    var initCortana = function (categories) {
        categories = categories || [];
        return wap.current.installedLocation.getFileAsync("vdmvoicecommands.xml").then(function (file) {
            return voiceCommandManager.installCommandDefinitionsFromStorageFileAsync(file);
        }, function (er) {
            console.error('error file vdmvoicecommands.xml', er);
        }).then(function () {
           var language = window.navigator.userLanguage || window.navigator.language;

            var commandSetName = "VDM_" + language.toLowerCase();
            var commansets = Windows.ApplicationModel.VoiceCommands.VoiceCommandDefinitionManager.installedCommandDefinitions;
            if (commansets.hasKey(commandSetName)) {
                var vcd = commansets.lookup(commandSetName);
                var phraseList = [];
                categories.forEach(function (c) {
                    phraseList.push(c.title);
                });
                return vcd.setPhraseListAsync("cat", phraseList).then(function () {
                    console.log("VCD loaded !");
                 }, function (er) {
                    console.error('error set phraseList', er);
                })
            } else {
                console.warning("VCD not installed yet?");
            }
        }, function (ee) {
            console.error("installCommandDefinitionsFromStorageFileAsync error", ee);
        });
    }

Now you have to handle the activation event that will get sent to your app, and parse arguments.

  app.addEventListener("activated", function (args) {
        var appLaunchVoiceCommand = activation.ActivationKind.voiceCommand || 16;
        if (args.detail.kind === appLaunchVoiceCommand) {
            return handleVoiceCommand(args);
        }
    });

The handleVoiceCommand function parse the args passed from the activated app event and do the navigation to the right place

    var app = WinJS.Application;
    var commands = {
        "showlast": function (commandresult) {
            return WinJS.Navigation.navigate(VDM.Pages.VDMList, { viewType: 'last', viewLabel: WinJS.Resources.getString('appbar_views_last') });
        },
        "showcategorie": function (commandresult) {
            var categorie = commandresult.semanticInterpretation.properties.cat[0];
            return WinJS.Navigation.navigate(VDM.Pages.VDMList, { viewType: categorie.toLowerCase(), viewLabel: categorie });
        }
    }
    var handleVoiceCommand = function(args) {
        if (args.detail && args.detail.detail) {
            var voicecommand = args.detail.detail[0];
            if (voicecommand) {
                var result = voicecommand.result;

                if (result) {
                    var commandname = result.rulePath ? result.rulePath[0] : '';
                    var properties = result.semanticInterpretation ? result.semanticInterpretation.properties : {};
                    console.log("voice activation (" + commandname + ") confidence: " + result.rawConfidence, result);
                    var cmd = commands[commandname];
                    if (cmd) {
                        return cmd(result).then(function () {
                            VDM.Utils.loadMainAds();
                        });
                    }
                }

            }
        }
    }
    app.addEventListener("activated", function (args) {
        var appLaunchVoiceCommand = activation.ActivationKind.voiceCommand || 16;
        if (args.detail.kind === appLaunchVoiceCommand) {
            return handleVoiceCommand(args);
        }
    });

Let’s talk more with the app (with appService)

If you need a deeper integration with Cortana, you could also « talk » with her using an app service.

An app service is a Background task that Cortana could call when you use a command. You will have to explicitely declare which service Cortana must call in your command file.

    <Command Name="getFML">
      <Example> tell me a FML </Example>
      <ListenFor RequireAppName="ExplicitlySpecified"> tell me a {builtin:AppName} </ListenFor>
      <Feedback> Here an FML </Feedback>
      <VoiceCommandService Target="FMLVoiceCommandService"/>
    </Command>

Now let’s implement the Application Service. You must add it to your application manifest by pointing to JavaScript file, and give it the name you use in the command file :

 <uap:Extension Category="windows.personalAssistantLaunch"/>
 <uap:Extension Category="windows.appService" StartPage="js/voiceCommandService.js">
    <uap:AppService Name="FMLVoiceCommandService"/>
 </uap:Extension>

Beware the visual studio appxmanifest editor, it removes this entry if anything changes in it (like a upgrade of version when you generate a new appx package) this bug will certainly be corrected in the update 1 of Visual Studio.

Now let’s create the javascript file and implement the service itself.

When you are using JavaScript App Services are a lot like independant web workers. You can import all the JS file you need to run your code by using importScripts

importScripts("/WinJS/js/base.js");
importScripts("/js/FML.API.js");

The service is loaded by cortana, so when is loaded the doWork function is called.
If the Windows.UI.WebUI.WebUIBackgroundTaskInstance.current.triggerDetails is an instance of Windows.ApplicationModel.AppService.AppServiceTriggerDetails, we can get voice command used to launch this task and do things like:

  • Send an waiting response message
  • displays items
  • Send a final response message
var appService = Windows.ApplicationModel.AppService;
var backgroundTaskInstance = Windows.UI.WebUI.WebUIBackgroundTaskInstance.current;
var details = backgroundTaskInstance.triggerDetails;
var deferral = backgroundTaskInstance.getDeferral();

if (details instanceof appService.AppServiceTriggerDetails) {
    voiceServiceConnection = voiceCommands.VoiceCommandServiceConnection.fromAppServiceTriggerDetails(details);
    voiceServiceConnection.addEventListener("voiceCommandCompleted", onVoiceCommandCompleted);

    voiceServiceConnection.getVoiceCommandAsync().then(function completed(voiceCommand) {

    // here you can check the voiceCommand, call an API (or read a file) and send messages to Cortana UI

            var userMessage = new voiceCommands.VoiceCommandUserMessage();
                    userMessage.spokenMessage = "I'm Cortana and I read this awesome message";
                    userMessage.displayMessage = "I'm Cortana and I read this awesome message";
            var response = voiceCommands.VoiceCommandResponse.createResponse(userMessage);
            return voiceServiceConnection.reportSuccessAsync(response);

    });
}

The displayMessage string must not exceed 256 character

And now, with this, you can ask Cortana: « hey cortana, tell me a FML »