Appel d’application tierce : et si on contournait les standards web ?

En informatique industrielle, les actions web standards ne sont pas forcément adaptées aux contraintes utilisateurs. Il est donc parfois sensé, au sein d’environnements spécifiques, d’avoir recours à une tierce application pour gagner du temps ou plus simplement pour faire face à de fortes contraintes liées à ces environnements et aux besoins client.

Au travers de cet article, nous laisserons apparaître qu’il existe une réelle plus-value à appeler une application console développée en C# « .exe » via une application Node.js (1).  

La preuve par l’exemple

Précision du contexte

L’action d’une tierce application peut s'avérer utile afin d’interagir directement sur l'environnement système comme pour :

  • La réutilisation d’une application spécifique déjà développée (lors d’une migration de client lourd vers un client léger en milieu industriel par exemple)
  • Contourner un standard web comme l’assistant d’impression

Nous partons sur ce deuxième point, à partir d’une application Node.js chargeant une page web dans un environnement Microsoft. Nous lancerons par le simple clic d’un élément HTML « button » une impression silencieuse(2).

Mise en place d’une impression silencieuse

Dans notre cas d’utilisation, nous faisons le choix de développer une application console en .Net, avec C# utilisant une librairie libre de droit pour permettre l’impression de document en tâche de fond sans action utilisateur « impression silencieuse ». Dans cette solution, ici développée à l’aide de Visual Studio pour l’exemple, nous pouvons très facilement tester et éprouver l’efficacité de notre développement.

Vu que nous avons la main, il est d’une bonne pratique de maîtriser au maximum notre petit projet : gérer au mieux nos exceptions, nos retours, lui associer un projet connexe de test, ainsi qu’un logger pour nos actions de succès, erreurs, etc. Une fois notre application console compilée, testée et satisfaisante, il est temps de l’utiliser dans notre application. A noter ici, que l’utilisation d’une tierce application ou d’une bibliothèque va annuler la portabilité de notre application car elles sont dépendantes du système d’exploitation pour lequel elles ont été développées (.dll…).

Mise en place d’une application web monopage

Imaginons que nous avons développé une application web monopage (Single Page Application ou SPA dans le jargon) qui listerait dans un tableau des fichiers au format « .pdf ». Notre applicatif web aurait alors pour but de lancer l’impression silencieuse du ou des documents sélectionnés à la suite du clic sur le bouton d’impression de l’interface utilisateur. Pour cela nous utiliserons notre application console (développée en .Net et ajoutée aux assets de notre web app) par l’intermédiaire d’un service en utilisant le module natif de Node.js : « child _process », et plus précisément sa méthode « execFile() ».

  • execFile(file[,args][,options][,callback])». [cf : Node.js .org ]

Quelle que soit la puissance de votre serveur, un seul thread ne peut prendre en charge qu'un flux limité d'instructions à exécuter. Le fait que Node.js soit « monothread », c’est-à-dire que le processus ne s'exécute que dans un seul thread, ne signifie pas que nous ne pouvons pas profiter de plusieurs processus (forking). En effet Node.js est conçu pour créer des applications distribuées avec de nombreux nœuds, d’où son nom « Node ». Ici, l’API « child_process » permet de créer et contrôler de nouveaux processus enfants Node.js. Sa méthode fork() par exemple permettra la communication entre ces différents processus au travers de messages (Node.js étant un environnement d'exécution JavaScript asynchrone et orienté événement).

Dans notre cas, nous utiliserons la méthode execFile() qui permettra d’exécuter un fichier dans un nouveau processus enfant, qui le cas échéant ne fermera, ni ne bloquera le processus parent en cas d’erreurs ou de problèmes liés à notre application tierce (note importante : sous Windows, certains fichiers s’exécutant avec le support de shell, nous utiliserons la méthode homologue exec() qui passe par l’utilisation d’un shell pour exécuter le programme. Pour en savoir plus sur le processus). Cette méthode exécutera alors notre application tierce, en lui transmettant :

  • Un paramètre qui spécifie le chemin où se trouve le programme à exécuter [executablePath]
  • Si besoin les arguments [pathFile, documentName, pathLog]
  • Et une fonction de rappel [callback()].

Si l’application externe existe (ici notre application console d’impression silencieuse), la fonction de callback sera appelée.

const child_process = require('child_process'); // NOTE Variables for example const executablePath = './assets/exe/SlientPrintCSharp.exe'; const documentName = 'Silent Print PDF Example'; const pathFile = './assets/pdf/silent-print-example.pdf'; const pathLog = './assets/log/silent-print_Log.txt'; // NOTE Call Child_process child_process.execFile( executablePath, [pathFile, documentName, pathLog], (err, stdout, stderr) => { if (err != null) { console.error('execFile error: show log for more details.', err); } else { console.info('execFile success'); } } );

Cette méthode est idéale pour exécuter un programme en dehors du processus principal de l’application et pour faire appel à un application tierce légère traitant une petite volumétrie de données ou entraînant des actions système diverses. A noter que ce module « child_process » présente également une version « Sync » de ses méthodes spawn, exec, execFile tels que : spawnSync, execSync, execFileSync. 

Ces fonctions de blocage synchrone attendront la fin du processus enfant, ce qui peut être potentiellement utile pour des scripts bien spécifiques mais il vaut mieux éviter les demandes synchrones effectuées sur le thread principal d'une application au risque d’entraîner des situations de blocage de l’interface utilisateur.

Pour aller plus loin sur l’appel d’application tierce

Si l’appel à une application tierce vous intéresse, je vous invite à vous documenter sur les différentes manières de les utiliser au travers des différentes API Node.js, car il est vraiment possible de faire beaucoup de choses très utiles. Toutefois, exécuter un programme tiers n’est pas la seule pratique intéressante que nous aurions pu utiliser au travers de Node.js, surtout au sein d’un environnement Microsoft.

Le chargement d’une bibliothèque de liens dynamiques (DLL) pour interagir sur des fonctionnalités ou des appareils connectés à notre ordinateur en est une autre par exemple. Mais ceci est un autre sujet tout aussi passionnant…

(1) A noter que nous pourrions tout aussi bien appeler une application Python « .py » ou autre .cmd…

(2) Impression en tâche de fond, sans passer par contrôle utilisateur.