Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

Windows 8 : Protocole d’activation personnalisé (CPA)

[new:30/11/2012]Le protocole d’activation personnalisé est un mécanisme propre à Windows 8 pour permettre le lancement d’une application WinRT comme s’il s’agissait d’un site Web, par une URL. Un peu code “mailto:” ou “http:” qui déclenchent les applications correspondantes lorsqu’ils sont exécutés. Vos applications peuvent utiliser ce mécanisme !

Devenir gestionnaire pour un nom de schéma

Le mécanisme consiste à permettre à une application de s’inscrire auprès de l’OS pour devenir gestionnaire par défaut d’un nom de schéma, d’une URI particulière.

Les applications conçues pour le bureau classique autant que les applications Windows Store peuvent utiliser ce mécanisme. Je n’ai pas testé avec une application WPF, mais au minimum le protocole fonctionne lorsqu’il invoqué depuis une telle application (avec un shellexecute sur le nom de protocole comme nous le verrons plus loin avec la boîte “exécuter” de Windows).

Si l’utilisateur confirme que l’application est bien gestionnaire par défaut de l’URI spécifiée, alors à chaque invocation de cette dernière ce sera cette application qui sera exécutée (avec la possibilité, comme toute URI, de lui passer des paramètres). La confirmation est demandée lorsque le protocole est appelé depuis IE ou Chrome par exemple. Lorsqu’il y a appel direct cette confirmation n’est pas demandée ce qui rend le mécanisme aussi transparent que l’association des extensions de fichier sous Win32.

Bien entendu il est conseillé d’enregistrer une application pour un schéma en rapport direct avec les services qu’elle rend. Si une application s’enregistre pour “mailto:” par exemple, l’utilisateur s’attendra à voir une fenêtre de saisie d’un nouvel e-mail s’ouvrir et non une page de publicité ou la création d’une fiche client…

Le CPA doit ainsi être vu comme une sorte d’amélioration du système d’enregistrement des extensions de fichier, revu à la “sauce Web”, c’est à dire qu’ici il ne s’agit plus de double-cliquer sur un nom de fichier dans l’explorateur de Windows pour lancer une application mais de permettre à cette dernière d’être exécutée depuis n’importe où (donc d’autres applications) sous la forme d’une simple URI… Fantastique non ?

Comment faire ?

C’est toujours la question qui se pose avec ces nouveautés, c’est bien sympathique dans l’esprit, mais comment mettre en œuvre la fonctionnalité ? Et comme toujours, la meilleure réponse consiste à montrer un peu de code… Et c’est ce que je vais faire !

Une app Windows Store minimale

Je vais partir d’une application Windows Store “vierge”, c’est à dire le modèle “blank”.

La première chose à faire après avoir créé le projet et de le modifier très légèrement afin d’extraire par refactoring (avec Resharper c’est bien entendu plus facile) la partie qui s’assure que l’application est créée et activée. A la base ce code se trouve dans OnLaunched de App.Xaml.cs.

Au passage il sera simplifié pour devenir :

        private void EnsureAppIsCreatedAndActivated()
        {
            Frame frame;
            Window.Current.Content = frame = (Window.Current.Content as Frame) ?? new Frame();
            if (frame.Content==null)
                if (!frame.Navigate(typeof(MainPage)))
                    throw new Exception("Failed to create initial page");
            Window.Current.Activate();
        }

 

La méthode OnLaunched ne fait donc plus qu’un appel à cette nouvelle méthode, ce qui permettra de l’appeler aussi depuis un autre point d’entrée que nous verrons plus bas.

Se déclarer gestionnaire de Protocole personnalisé

La partie la plus importante de l’exemple intervient ici : nous devons déclarer à l’OS que notre application prend en compte la gestion de CPA.

Il suffit pour cela de double-cliquer sur le manifeste et d’aller dans l’onglet “Declarations” (comme pour s’intégrer à la chaîne de recherche, ce que je vous ai présenté dans un précédent billet).

image

Une fois “Protocol” sélectionné l’affichage du détail de celui-ci apparait à droite :

image

L’information la plus importante est “Name”, c’est le nom de schéma par lequel l’application pourra être appelée.

Comme il est possible que deux applications entrent en conflit sur ce nom (il n’y a pas de réservation comme un nom de domaine…) Windows affichera la liste des applications ayant la même URI, cette liste sera complétée par le logo et le “display name”, d’où la nécessaire prudente de spécifier ces informations.

Il n’y a pour l’instant aucune “norme” ni aucun répertoire centralisé pour les noms de protocoles personnalisés, et cela ne semble pas prévu. Je vous conseille ainsi d’éviter les noms qui auront toutes les chances d’être choisis par de nombreux développeurs… Evitez d’emblée ces noms et tentez une approche par le nom de votre société ou celui de l’un de vos site Web (sur lequel il y aura la promotion de votre applications par exemple pour être cohérent). Vous aurez beaucoup moins de chance que votre application et son protocole n’entrent en conflit avec d’autres applications.

Comme il est possible de récupérer l’URI entière, avec ses paramètres éventuels donc, tentez une approche de type “NomDeSociétéOuSiteNomDApplication”, par exemple EnaxosAppliTest. Dans l’exemple de code j’ai choisi “MyCPA”, un truc à éviter en production donc !

Attention ! Même s’il n’existe pas de répertoire centrale pour les noms de CPA, les noms suivants sont déjà réservés par Microsoft et il ne faut pas les utiliser faute de voir son application se faire rejeter à la validation du Windows Store… La liste actuelle est la suivante : Application.manifest, Application.reference, Batfile, BLOB, Cerfile,Chm.file, Cmdfile, Comfile, Cplfile, Dllfile, Drvfile, Exefile, Explorer.AssocActionId.BurnSelection,Explorer.AssocActionId.CloseSession, Explorer.AssocActionId.EraseDisc, Explorer.AssocActionId.ZipSelection,Explorer.AssocProtocol.search-ms, Explorer.BurnSelection, Explorer.CloseSession, Explorer.EraseDisc,Explorer.ZipSelection, FILE, Fonfile, Hlpfile, Htafile, Inffile , Insfile, InternetShortcut, Jsefile, Lnkfile,Microsoft.PowerShellScript.1, MS-accountpictureprovider, Ms-appdata, Ms-appx, MS-AUTOPLAY, Msi.Package,Msi.Patch, Ms-windows-store, Ocxfile, Piffile, Regfile, Scrfile, Scriptletfile, Shbfile, Shcmdfile, Shsfile, SMB,Sysfile, Ttffile, Unknown, userTileProvider,vbefile, Vbsfile, Windows.gadget, Wsffile, Wsfile, Wshfile.

Attention ! Le nom du CPA doit respecter des règles. Je n’ai pas trouvé (mal cherché ?) la liste exhaustive de ces dernières mais mes tests m’ont prouvé qu’il ne faut absolument pas utiliser de majuscules… Dans l’exemple de ce billet le protocole ne s’appelle donc pas “MyCPA”, mais “mycpa”. Sinon il y a une erreur de compilation…

Gérer l’activation via le protocole

Techniquement la déclaration du manifeste suffit pour que notre application puisse désormais être activée via son CPA.

Mais il reste à le matérialiser dans notre code pour que l’utilisateur puisse bénéficier de ce service (l’utilisateur ou les autres applications qui voudront lancer la vôtre).

Comme on peut le voir sur la capture précédente il existe des champs que je n’ai pas saisi comme “Executable, Entry Point et Start Page”. Ces indications supplémentaires, comme il est facile de le comprendre, vous permettent d’aiguiller l’utilisateur vers une page donnée de votre application lorsqu’elle est activée via le CPA (ou de déclencher un traitement particulier).

Dans App.Xaml.cs la méthode “OnLaunched” est “override”, car la classe application fournit une méthode virtuelle pour le lancement. De la même façon elle fournit une méthode virtuelle pour les activations via le CPA. En réalité la méthode virtuelle OnActivated est centrale, la façon dont l’application a été activée peut être connue par les arguments passés. C’est de cette façon qu’ici nous allons détecter l’activation par le CPA et extraire l’URI passée pour la stocker dans une variable statique de l’application en vu de son exploitation :

       public static string CPAValue { get; private set; }
        
        protected override void OnActivated(IActivatedEventArgs args)
        {
            if (args.Kind == ActivationKind.Protocol)
            {
                var protocolActivatedEventArgs = args as ProtocolActivatedEventArgs;
                if (protocolActivatedEventArgs != null)
                    CPAValue = protocolActivatedEventArgs.Uri.ToString() ?? "null";
            }
            EnsureAppIsCreatedAndActivated();
        }

 

Il y a bien entendu d’autres façon plus subtiles d’utiliser l’URI passée que de la stocker dans une variable statique. Ce n’est qu’un exemple simplificateur pour le besoin du billet.

La partie visuelle

En réalité l’exemple s’arrête là. Nous avons enregistré le protocole personnalisé de notre application dans l’OS, nous avons surchargé la méthode OnActivated pour récupérer cette activation spéciale et la valeur de l’URI, tout est déjà fonctionnel. Ce que vos applications feront du CPA qu’elles auront déclaré est totalement libre !

Mais pour les besoins de l’exemple je vais ajouter un visuel minimaliste à l’application et surtout un moyen de vérifier que nous avons bien récupéré l’URI.

Pour cela j’ajoute quelques éléments visuels pour donner “vie” à la page noire qui sinon s’affichera par défaut et je place un TextBlock et un bouton pour afficher l’URI.

Le code du bouton (codé dans le code-behind, pas de MVVM dans cet exemple !) est ultra simple :

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            txtURI.Text = App.CPAValue ?? "Rien!";
        }

 

Sur le clic du bouton je récupère le contenu de la variable statique CPAValue créée dans App.Xaml.cs avec un test de nullité qui affichera “Rien !” si l’URI n’est pas définie.

C’est terminé… Reste à voir comment cela fonctionne.

CPA en Action

Je vais choisir d’exécuter l’application dans le simulateur. Dans un premier temps l’application sera donc juste lancée par l’environnement de Debug de Visual Studio. Je vais cliquer sur le bouton et voici l’affichage que j’obtiendrai :

image

Il n’y a rien…

En effet il ne faut pas confondre exécution et activation ! Lorsque mon application est lancée (OnLaunched côté événements) elle n’est pas activée par le CPA mais par l’OS de façon classique. Il faudrait d’ailleurs tester les particularités du tombstoning pour savoir s’il faut ou non rétablir le contexte utilisateur par exemple (ce qui n’est pas fait ici).

Je vais donc fermer l’application totalement (par ALT-F4) et passer par le bureau classique pour invoquer non plus mon application (qui s’appelle CPATest.exe) mais son protocole en lui passant des paramètres…

image

Les connaisseurs reconnaîtront Classic Shell, un utilitaire open source dont j’ai parlé dans ses colonnes et qui permet de retrouver un bouton “démarrer” à la Windows 7 sur le bureau classique de Windows 8, quelque chose d’indispensable à mon sens.

Si vous n’utilisez pas cet outil, vous pouvez exécuter une application en invoquant la boîte de dialogue “run” qui existe toujours (je n’utilise plus Windows 8 sans le Classic Shell et j’avoue que je ne pourrais plus dire comment la manip doit être faite en mode “out of the box” … mais vous trouverez j’en suis sûr !).

Bref j’ai tapé “mycpa:coucou” et j’ai ensuite validé. On remarquera que je n’appelle pas mon exécutable dont, à la limite, je ne connais pas le nom… J’appelle le nom de mon protocole, “mycpa”. Il est suivi du symbole deux points comme “ftp:” “http:” “mailto:” etc, puisque de facto c’est bien un nouveau protocole que j’ai créé ! Les deux points sont suivis d’un texte quelconque (les paramètres acceptés par mon protocole). Comme l’exemple ne gère pas du tout les paramètres et ne cherche pas à les extraire, c’est toute la chaîne qui va être réceptionnée tel quel par l’application et affichée sans modification ni traitement, et là quand on clique sur le bouton”Lire URI” nous obtenons l’affichage suivant :

image

Incroyable non ?

Plus bluffant encore, exécutez Chrome ou IE et dans la barre d’adresse internet tapez “mycpa:via le web” et, surprise le dialogue suivant apparait :

image

La capture est assez mauvaise car dans le simulateur tout est affiché très petit (mon bureau Windows qui est simulé est très large). Mais on peut lire que IE nous demande de confirmer l’exécution de “CPATest” (cette fois c’est le nom de l’exécutable). Si on valide (et qu’on clique sur le bouton permettant de connaître le contenu de l’URI passée) :

image

Notre application devient même une adresse Web qui pourrait être bookmarkée… Génial.

Conclusion

Voici un mécanisme à la fois totalement nouveau, très ouvert, fort simple à implémenter, qui ouvre de réelles perspectives pour la programmation sous WinRT.

S’il est normal de se poser des questions sur l’avenir de Windows 8, comme de tout nouvel OS et même tout nouveau logiciel en général, et s’il est légitime de s’interroger aussi sur le devenir de WinRT sur les PC ou les tablettes, je pense qu’on peut affirmer que Microsoft a réellement produit quelque chose de neuf et de novateur, bourré de bonnes idées.

Il serait vraiment injuste de juger WinRT et Modern UI uniquement sur le battage “grand public” ou sur une simple guerre “pro ou anti Ipad/IPhone”.

Apple à toujours volé tous ces concepts aux autres, Apple à volé tous ses designs (vous connaissez certainement cette comparaison entre l’electro-ménager Braun et le design des appareils Apple, confondant non ?), Microsoft innove réellement. Tant sur le design que sur le fond.

Que ceux qui sont encore dans la gurutisation de Steve Jobs osent comparer réellement ce que nos “steve à nous” ont créé. Il n’y a pas photo.

Si, il y en a plusieurs même. Une au hasard :

Braun or Apple?

Si vous préférez l’innovation, la vraie, aux copies… Alors…

Stay Tuned !

blog comments powered by Disqus