La création de greffons (2.x)

Comment développer des greffons pour KeePass 2.x ?

Cette documentation s'applique aux greffons de KeePass 2.x. Les greffons 2.x sont fondamentalement différents des greffons 1.x. Les greffons 1.x ne peuvent pas être chargés par KeePass 2.x.


Exigences

Avant de pouvoir commencer à développer un greffon KeePass, vous avez besoin des prérequis suivants :


Le tutoriel pas à pas

Démarrez votre IDE préféré et créez un nouveau projet de bibliothèque de classes C# (pour le Framework .NET, et non pas pour le Standard/Core .NET). Dans ce tutoriel, l'exemple de greffon que nous développons s'appelle SimplePlugin. La première chose que vous devez faire maintenant est d'ajouter une référence à KeePass : accédez à la boîte de dialogue des références et sélectionnez le fichier KeePass.exe (à partir du package ZIP portable). Après avoir ajouté la référence, les espaces de noms KeePass et KeePassLib devraient être disponibles.

Il est important que vous fassiez référence à un KeePass.exe officiel, et non à un instantané de développement ou à votre propre build, car sinon votre greffon sera incompatible avec les builds officiels de KeePass.

Tous les greffons KeePass doivent dériver d'une classe de greffon d'un KeePass de base (un greffon dans l'espace de noms KeePass.Plugins). En remplaçant les méthodes et les propriétés de cette classe, vous pouvez personnaliser le comportement de votre greffon.

Un greffon minimal ressemble à ceci :

using System; using System.Collections.Generic; using KeePass.Plugins; namespace SimplePlugin { public sealed class SimplePluginExt : Plugin
{ private IPluginHost m_host = null; public override bool Initialize(IPluginHost host) { if(host == null) return false; m_host = host; return true; } } }

Vous pouvez trouver une version entièrement documentée et étendue de ce greffon simple sur la page Web des greffons de KeePass.

Ce greffon ne fait exactement rien, mais il montre déjà quelques conventions importantes, qui doivent être suivies par tous les greffons :

  • namespace (l'espace de noms) doit être nommé comme le fichier DLL sans extension. Notre fichier DLL s'appelle SimplePlugin.dll, donc namespace doit s'appeler SimplePlugin.
  • La classe principale du greffon (que KeePass instanciera lorsqu'il chargera votre greffon) doit être appelée exactement de la même manière que le namespace plus "Ext". Dans ce cas : "SimplePlugin" + "Ext" = "SimplePluginExt".
  • La classe de greffon principale doit être dérivée de la classe de base KeePass.Plugins.Plugin.

La fonction Initialize est la plus importante et vous la remplacerez probablement toujours. Dans cette fonction, vous obtenez une interface vers les composants internes de KeePass : une référence d'interface IPluginHost. Grâce à cette interface, vous pouvez accéder au menu principal de KeePass, à la base de données actuellement ouverte, etc. La fonction Initialize est appelée immédiatement après que KeePass a chargé votre greffon. Toute initialisation doit être effectuée dans cette méthode (pas dans le constructeur de votre classe de greffon !). Si vous avez tout initialisé avec succès, alors vous devez retourner true. Si vous retournez false, alors KeePass déchargera immédiatement votre greffon.

Une seconde fonction dont vous aurez très souvent besoin est la méthode Terminate :

public override void Terminate() { }

Cette fonction est appelée peu de temps avant que KeePass ne décharge votre greffon. Vous ne pouvez pas interrompre ce processus (c'est juste une notification et votre dernière chance de nettoyer toutes les ressources utilisées, etc.). Immédiatement après votre retour depuis cette méthode, KeePass peut décharger votre greffon. Il est fortement recommandé de libérer toutes les ressources dans cette méthode (pas dans le destructeur de votre classe de greffon !).

Nous avons presque terminé ! Nous devons maintenant dire à KeePass que notre fichier est un greffon KeePass. Cela se fait en éditant le bloc d'informations de version du fichier. Ouvrez la boîte de dialogue d'édition de la version du fichier (dans Visual Studio 2005 : cliquez avec le bouton droit sur le nom du projet → 'Propriétés' → bouton 'Informations sur l'assemblage'). Tous les champs peuvent être attribués librement à l'exception du champ Nom du produit (pour plus d'informations, voir Les conventions d'un greffon). Ce champ doit être positionné à "KeePass Plugin" (sans les doubles quotes).

C'est ça ! Essayez maintenant de compiler votre greffon et de copier le fichier DLL résultant dans le répertoire KeePass. Si vous démarrez KeePass et accédez à la boîte de dialogue des greffons, alors vous devriez voir votre greffon dans la liste des greffons chargés.


La fourniture d'éléments de menu

De nombreux greffons fournissent des éléments de menu (avec des sous-éléments, si nécessaire) dans des emplacements bien en vue comme le menu 'Outils', le menu contextuel d'entrée, etc. Un tel élément de menu peut être fourni à KeePass en remplaçant la méthode GetMenuItem de votre classe de greffon (qui dérive de la classe de base du greffon). Dans cette méthode, le greffon peut construire et renvoyer un ToolStripMenuItem, que KeePass affichera ensuite à l'emplacement approprié.

Les utilisateurs doivent pouvoir associer l'élément de menu à votre greffon. En règle générale, les greffons positionnent le texte de l'élément de menu sur le nom du greffon ou sur une chaîne de caractères commençant par le nom du greffon. Par exemple, un greffon 'Abcd' qui veut fournir un seul élément de menu (pour l'accès aux options du greffon) pourrait positionner le texte de l'élément de menu sur 'Options Abcd'. Si le greffon prend en charge plusieurs commandes, alors positionnez le texte de l'élément de menu sur le nom du greffon (par exemple 'Abcd') et ajoutez un sous-élément pour chaque commande.

La méthode GetMenuItem doit toujours construire et retourner un nouveau ToolStripMenuItem. Ne mettez pas en cache l'élément de menu ou l'un de ses sous-éléments à des fins ultérieures (KeePass peut invoquer la méthode GetMenuItem plusieurs fois et afficher les éléments de menu à plusieurs endroits ; si votre greffon mettait en cache un élément de menu, alors essayer de l'afficher à plusieurs endroits entraînerait des problèmes, car un ToolStripMenuItem ne peut avoir qu'un seul élément parent). Si vous souhaitez mettre à jour l'état des sous-éléments (comme désactiver certains éléments ou afficher des coches), alors vous pouvez le faire par exemple dans une méthode anonyme qui gère l'événement DropDownOpening de l'élément de menu renvoyé (de cette façon, vous n'avez pas besoin de vous souvenir manuellement des références de l'élément de menu); voir SamplePlugin pour un exemple.

KeePass prend possession de l'élément de menu renvoyé (et de ses sous-éléments). Le greffon ne doit pas ajouter ou supprimer l'élément à/depuis n'importe quel menu lui-même ; KeePass le fera.

Si votre greffon ne fournit pas d'élément de menu à l'emplacement spécifié par le paramètre t de PluginMenuType , alors, renvoyez null.

Exemple:

public override ToolStripMenuItem GetMenuItem(PluginMenuType t) { // Provide a menu item for the main location(s)
if(t == PluginMenuType.Main) { ToolStripMenuItem tsmi = new ToolStripMenuItem(); tsmi.Text = "Abcd Options"; tsmi.Click += this.OnOptionsClicked; return tsmi; } return null; // No menu items in other locations
} private void OnOptionsClicked(object sender, EventArgs e) { // Called when the menu item is clicked
}

Pour un exemple sur comment créer un élément de menu avec des sous-éléments (et de mise à jour dynamique de leurs états), consultez l'exemple de greffon SamplePlugin.

Les conventions d'un greffon

Bloc d'informations sur la version du fichier :

KeePass utilise le bloc d'informations sur la version du fichier pour détecter si un fichier DLL est un greffon KeePass et il en récupère les informations à afficher dans la boîte de dialogue des greffons. Les champs sont utilisés comme suit :

  • Title: doit contenir le nom complet du greffon.
  • Description: doit contenir une courte description (pas plus de 5 lignes) de votre greffon.
  • Company: doit contenir le nom de l'auteur du greffon.
  • Product name: doit être positionné à "KeePass Plugin" (sans les doubles quotes).
  • Copyright: non utilisé par KeePass ; librement assignable par le greffon.
  • Trademarks: non utilisées par KeePass ; librement assignable par le greffon.
  • Assembly version: doit être positionné à la version de votre greffon.
  • File version: doit être positionné à la version de votre greffon. C'est à vous de décider comment vous versionnez vos versions de greffon, mais cela devrait être un schéma qui permet des comparaisons de version (en comparant les composants de version). N'utilisez pas d'astérisques pour créer un numéro de version au moment de la génération.
  • GUID: non utilisé par KeePass ; librement assignable par le greffon.

Name, namespace et class name :

Si vous souhaitez utiliser le nom (name) "KeePass" en tant que partie du nom de votre greffon, alors préfixez/ajoutez directement un préfixe/suffixe non numérique. Par exemple, "KeePassSync" est correct, mais "KeePass Sync" ne l'est pas.

L'espace de noms (namespace) doit être nommé comme le fichier DLL sans extension. Par exemple, si le fichier DLL est nommé SecretImporter.dll, alors vous devez appeler l'espace de noms SecretImporter.

La classe du greffon doit être nommée comme l'espace de noms plus "Ext". Pour le greffon SecretImporter, ce serait SecretImporterExt.


La vérification de la mise à jour

La vérification des mises à jour de KeePass ≥ 2.18 peut également vérifier les mises à jour des greffons. La prise en charge de la vérification des mises à jour est facultative ; les greffons n'ont pas à prendre en charge les vérifications de mise à jour.

Afin de prendre en charge les vérifications de mise à jour, les développeurs de greffon doivent effectuer les opérations suivantes :

  • Fournir le fichier d'informations de version : lorsqu'un utilisateur final appelle une vérification de mise à jour, KeePass télécharge un fichier d'informations de version, qui spécifie les numéros de version actuels d'un ou plusieurs greffons. Chaque auteur de greffon héberge son propre fichier d'informations de version. Le format du fichier d'informations de version est décrit en détail ci-dessous.
  • Laisser KeePass savoir : afin de pouvoir vérifier la version du greffon, KeePass doit savoir où se trouve votre fichier d'informations de version. Pour informer KeePass, remplacez la propriété de chaîne UpdateUrl de votre classe de greffon (celle dérivée de Plugin) pour renvoyer l'URL complète et absolue de votre fichier d'informations de version. Il doit s'agir d'une URL https:// (pour la rétrocompatibilité, KeePass prend également en charge http:// et ftp://, mais pour des raisons de sécurité, https:// devrait être utilisé).

Les développeurs de greffon doivent mettre à jour leur fichier d'informations de version chaque fois qu'ils publient de nouvelles versions de leurs greffons.

Format de fichier d'informations de version :

  • Le fichier est un simple fichier texte. Il doit être encodé en UTF-8 sans marque d'ordre d'octet (KeePass ≥ 2.21 prend en charge les BOM UTF-8 dans les fichiers d'informations de version, mais pour la compatibilité avec KeePass < 2.21, il est recommandé de ne pas utiliser de BOM). Toutes les fins de ligne sont prises en charge.
  • La première ligne du fichier doit commencer par un caractère séparateur de votre choix. Le caractère de séparation peut être n'importe quel caractère, mais il ne doit pas apparaître dans les noms et les versions de greffon. Il est suggéré ':'.
  • Chacune des lignes suivantes spécifie un nom de greffon et sa version actuellement disponible, séparés par le caractère de séparation spécifié dans la ligne d'en-tête.
  • Comme nom de greffon, la valeur du champ 'Title' dans le bloc d'informations de version du greffon doit être spécifiée. Pour les greffons gérés, il s'agit de la valeur spécifiée à l'aide de l'attribut d'assemblage AssemblyTitle.
  • Comme numéro de version, la valeur de la version du fichier dans le bloc d'informations de version du greffon doit être spécifiée. Pour les greffons gérés, il s'agit de la valeur spécifiée à l'aide de l'attribut d'assemblage AssemblyFileVersion. Le .0 à la fin peut être supprimé (par exemple, spécifiez 1.3 au lieu de 1.3.0.0).
  • Le fichier doit se terminer par une ligne contenant uniquement le caractère de séparation.
  • Vous pourriez éventuellement compresser votre fichier d'informations de version à l'aide de GZip (notez que ce n'est pas la même chose que Zip). Le nom du fichier doit alors se terminer par ".gz".

Exemple : supposons que vous développiez deux greffons : MonGreffon1 (version 1.5) et MonGreffon2 (version 1.13.2.17). Ensuite, votre fichier d'informations de version pourrait ressembler à ceci :

: MonGreffon:1.5 MonGreffon:1.13.2.17 :

Si vous avez développé plusieurs greffons, alors il est recommandé de créer un fichier d'informations de version, de répertorier tous vos greffons dans ce fichier et de spécifier l'URL du fichier dans tous vos greffons. Lorsque KeePass vérifie les mises à jour, il ne télécharge votre fichier d'informations de version qu'une seule fois. Cela réduit le trafic réseau et est plus rapide que de télécharger un fichier d'informations de version pour chaque greffon séparément.

Signature : depuis KeePass 2.34, vous pouvez éventuellement signer numériquement votre fichier d'informations de version à l'aide de RSA/SHA-512.

  • Une paire de clés RSA peut par exemple être générée comme suit :

using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(4096)) { rsa.PersistKeyInCsp = false; Console.WriteLine("Private key: " + rsa.ToXmlString(true)); Console.WriteLine("Public key: " + rsa.ToXmlString(false)); }

Toutes les longueurs de clé prises en charge par RSACryptoServiceProvider sont prises en charge par KeePass (jusqu'à .NET 4.5, soit 384 à 16384 bits par pas de 8 bits). Nous recommandons au moins 2048 bits ; le fichier d'informations de version principal (contenant la version KeePass) utilise 4096 bits.

  • Afin de dire à KeePass d'accepter un fichier d'informations de version spécifique uniquement lorsqu'il est vérifiable avec une clé publique spécifique, votre greffon doit appeler la méthode UpdateCheckEx.SetFileSigKey pour associer l'URL spécifiée à la clé publique spécifiée. La clé publique doit être une chaîne XML au format renvoyé par la méthode RSACryptoServiceProvider.ToXmlString. Ne stockez pas la clé privée dans votre greffon, uniquement la clé publique.
  • Pour signer un fichier d'informations de version non signé, hachez toutes les lignes non vides coupées entre l'en-tête et la ligne de pied de page à l'aide du codage SHA-512, UTF-8, chaque ligne se terminant par '\n' (et non "\r\n"). Signez le hachage à l'aide de la clé privée (si vous utilisez RSACryptoServiceProvider : alors chargez la clé privée à l'aide de sa méthode FromXmlString, puis calculez la signature à l'aide de la méthode SignData). Encodez le hachage à l'aide de Base64 et ajoutez-le à la première ligne du fichier d'informations de version.


Est-ce que les greffons de KeePass 2.x peuvent être écrits en C++ non managé ?

Oui et non. Vous pouvez écrire la logique de votre greffon en C++ non managé (des API Win32 natives peuvent être utilisées). Cependant, vous devez fournir une interface managée à votre greffon, c'est-à-dire que vous devez exporter une classe managée dérivée de la classe de base du Greffon comme décrit dans le tutoriel. De plus, le C++ managé est nécessaire pour modifier les éléments internes de KeePass (les entrées, les groupes, la fenêtre principale, etc.).

Pour un exemple d'utilisation d'API non gérées dans un assemblage de greffon en C++ géré, consultez l'exemple de greffon SamplePluginCpp.

Il est fortement recommandé de développer des greffons en C#, et non en C++, pour des raisons de compatibilité (dans le cas des greffons natifs, des versions 32 et 64 bits distinctes sont nécessaires ; les greffons natifs ne fonctionnent pas sur des systèmes de type Unix ; etc.).


Les fichiers PLGX

PLGX est un format de fichier de greffon optionnel pour KeePass ≥ 2.09. Au lieu de compiler votre greffon dans un fichier DLL, les fichiers de code source du greffon peuvent être empaquetés dans un fichier PLGX et KeePass compilera le greffon lui-même lors de son chargement.

Le principal avantage de l'appoche PLGX est la compatibilité avec les versions de KeePass personnalisées. Un greffon DLL fait référence à une version officielle de KeePass, et à moins qu'il y ait un changement dans KeePass qui casse le greffon, le greffon est également compatible avec toutes les futures versions de KeePass qui sont compilées avec la même clé de signature d'assemblage (nom fort). Cela s'applique à tous les systèmes d'exploitation. En particulier, un greffon DLL qui n'utilise aucune fonction spécifique à Windows fonctionne correctement sous Linux avec une version KeePass du package ZIP portable officiel. Cependant, certains packages Linux compilent KeePass à partir du code source ; ces constructions ne sont pas signées du tout ou sont signées avec une clé de signature d'assemblage différente et sont donc incompatibles avec les greffons DLL. En revanche, les greffons PLGX sont compatibles avec les versions (builds) de KeePass personnalisées, car KeePass peut ajuster la référence KeePass du greffon avant de le compiler.

Un autre avantage de l'approche PLGX est une forte détection de compatibilité. Dans le cas d'un greffon DLL, une incompatibilité (causée par un changement d'API dans KeePass) est détecté par le runtime lorsque le greffon essaie d'appeler/accéder à la méthode/classe, pas au moment du chargement. Ainsi, une incompatibilité est détectée tardivement et peut planter KeePass. En revanche, lors de l'utilisation du format PLGX, une incompatibilité est détecté immédiatement au moment du chargement : en cas de problème, le le processus de compilation échoue et KeePass peut afficher une information message d'incompatibilité du greffon à l'utilisateur. Pour les greffons DLL, KeePass effectue sa propre vérification de compatibilité, qui ne détecte cependant pas toutes les incompatibilités ; PLGX est supérieur ici.

En ce qui concerne la sécurité, les plugins DLL sont meilleurs, car ils peuvent être signé numériquement (Authenticode). De plus, les plugins DLL sont généralement chargés légèrement plus rapidement (parce qu'ils peuvent être chargés directement ; pas cache des greffons).

Pour les utilisateurs, la procédure d'installation d'un greffon DLL est exactement la même que pour un greffon PLGX ; les deux doivent être copiés dans le dossier 'Plugins'.

 

DLL

PLGX

Compatibilité avec les versions (builds) personnalisées (Linux)

No Partielle.

Yes

Vérification de compatibilité

No Faible.

Yes Forte.

Prise en charge de la signature Authenticode

Yes

No

Pas de compilation sur le système de l'utilisateur

Yes

No

Pas de cache de greffon

Yes

No

Ainsi, les deux formats ont des avantages et des inconvénients uniques.

Package double : vous pouvez expédier un greffon à la fois sous forme de DLL et de PLGX dans un seul package (par exemple : 'SecretImporter.dll' et 'SecretImporter.plgx' à l'intérieur du même dossier). KeePass chargera le fichier le plus approprié (si KeePass a été signé avec la clé officielle de signature d'assemblage, alors il chargera la DLL, sinon le PLGX). Si KeePass charge la DLL, le PLGX est ignoré.

Recommandations : Dans tous les cas, fournissez un fichier DLL (pour des raisons de sécurité). Si vous souhaitez prendre en charge les builds KeePass personnalisés, fournissez également un fichier PLGX (c'est-à-dire fournir un package double).

La création de fichiers PLGX : les fichiers PLGX peuvent être créés à partir des sources de greffon en appelant KeePass.exe avec l'option de ligne de commande --plgx-create. Si vous passez en plus un chemin vers le répertoire des sources du greffon (sans séparateur de fin), alors KeePass utilisera celui-ci ; sinon, il affichera une boîte de dialogue de navigation de dossiers pour vous permettre de sélectionner le répertoire. Si vous souhaitez transmettre l'emplacement du répertoire à l'aide de la ligne de commande, alors assurez-vous de spécifier un chemin d'accès complet et absolu ; les chemins relatifs ne fonctionneront pas.

Afin de garder la taille du fichier PLGX petite, il est recommandé de nettoyer le répertoire des sources du greffon avant de compiler le PLGX. Supprimez tous les fichiers binaires inutiles (fichiers dans les répertoires bin et obj) ; en particulier, supprimez toute DLL d'assemblage de greffon que vous avez compilée vous-même. Les fichiers temporaires de l'IDE (tels que les fichiers .suo et .user) peuvent également être supprimés.

Les fonctionnalités PLGX :

  • Format de fichier extensible et orienté objet.
  • Prise en charge de la compression (les fichiers de données sont compressés à l'aide de GZip).
  • Prise en charge de .csproj. KeePass récupère toutes les informations nécessaires à la compilation de l'assemblage du greffon à partir du fichier .csproj dans les sources du greffon.
  • Prise en charge des ressources embarquées.
  • Prise en charge des assemblages .NET référencés. L'information de références est lue à partir du fichier .csproj.
  • Prise en charge des assemblages personnalisés référencés. Les assemblages tiers requis par le greffon (références aux DLL) sont pris en charge, à condition que l'assemblage tiers se trouve dans le répertoire du code source du greffon (ou tout sous-répertoire de celui-ci).
  • Prise en charge de ResX. Les fichiers .resx sont automatiquement compilés en fichiers binaires .resources.
  • Le cache PLGX. Les fichiers PLGX sont compilés une seule fois et l'assemblage généré est stocké dans un cache. Pour tous les démarrages de KeePass suivants, aucune compilation n'est requise.
  • Maintenance du cache PLGX. La taille du cache PLGX peut être vue dans la boîte de dialogue des greffons KeePass. Ici, le cache peut également être marqué pour être effacé (il sera effacé lors du prochain démarrage de KeePass). Une option pour supprimer automatiquement les anciens fichiers du cache est prise en charge et activée par défaut.

Les limites de PLGX :

  • Seul C# est pris en charge (pas Visual Basic ou tout autre langage .NET).
  • Le compilateur inclus dans le .NET Framework prend en charge au maximum C# 5. Afin d'éviter d'utiliser les fonctionnalités d'une version plus récente de C#, il est donc recommandé de définir la version C# de votre projet de greffon sur 5 :
    • Dans Visual Studio 2017 et versions antérieures , ouvrez les propriétés du projet → onglet 'Version' → bouton 'Avancé' → définissez l'option 'Version du language' sur 'C# 5'.
    • Dans Visual Studio 2019 et versions ultérieures, le fichier XML du projet doit être modifié : l'élément 'LangVersion' doit contenir '5'. Pour plus de détails, consultez Gestion des versions du langage C# (C# Language Versioning).
  • Les ressources liées (dans différents assemblages) ne sont pas prises en charge.
  • Les dépendances sur d'autres projets ne sont pas prises en charge (réorganisez votre projet pour utiliser à la place des références d'assemblage personnalisées).

Définition des prérequis : vous pouvez éventuellement spécifier une version minimale de KeePass, un framework .NET installé au minimum, un système d'exploitation et la taille minimale d'un pointeur (x86 contre x64) en utilisant les options --plgx-prereq-kp:, --plgx-prereq-net:, --plgx-prereq-os: et --plgx-prereq-ptr: de ligne de commande. Si l'une des conditions préalables du greffon n'est pas remplie, alors KeePass affiche un message d'erreur détaillé à l'utilisateur final (au lieu d'un message générique d'incompatibilité du greffon). Exemple de construction :
KeePass.exe --plgx-create C:\VotreRépertoireDeGreffon --plgx-prereq-kp:2.09 --plgx-prereq-net:3.5

Les valeurs de système d'exploitation valides sont Windows et Unix. Lorsqu'il s'exécute sur un système d'exploitation inconnu, KeePass est par défaut Windows. Les tailles de pointeur (vérification de x86 par rapport à x64) sont spécifiées en octets ; par exemple, pour autoriser uniquement l'exécution sur x64, vous spécifiez --plgx-prereq-ptr:8.

Générer des commandes : vous pouvez éventuellement spécifier des commandes de préconstruction et de post-construction à l'aide de --plgx-build-pre: et --plgx-build-post:. Ces commandes sont intégrées dans le fichier PLGX et exécutées lors de la compilation du greffon sur le système de l'utilisateur final.

Dans les commandes de génération, le paramètre substituable {PLGX_TEMP_DIR} spécifie le répertoire temporaire (incorporant un séparateur de fin), dans lequel les fichiers ont été extraits. Dans la commande de post-construction, {PLGX_CACHE_DIR} est remplacé par le répertoire de cache du greffon (incorporant un séparateur de fin), dans lequel l'assemblage généré a été stocké.

Ces commandes de construction peuvent par exemple être utilisées pour copier des fichiers supplémentaires dans le répertoire de cache. Exemple : KeePass.exe --plgx-create C:\VotreRépertoireDeGreffon --plgx-build-post:"cmd /c COPY """{PLGX_TEMP_DIR}MonFichier.txt""" """{PLGX_CACHE_DIR}MonFichier.txt""""

Afin de spécifier une double quote sur la ligne de commande, elle doit être encodée à l'aide de trois doubles quotes (c'est le standard Windows, voir MSDN: SHELLEXECUTEINFOW). Ainsi, la ligne de commande ci-dessus intégrera en fait la commande post-build cmd /c COPY "{PLGX_TEMP_DIR}MonFichier.txt" "{PLGX_CACHE_DIR}MonFichier.txt" dans le PLGX, ce qui est correct. Il est fortement recommandé d'encadrer les chemins contenant des espaces réservés PLGX à l'aide de doubles quotes, sinon la commande ne s'exécutera pas correctement si le chemin contient un espace (ce qui arrive très souvent).

Si vous devez exécuter plusieurs commandes, alors écrivez-les dans un fichier batch et exécutez-le (avec cmd). Si vous avez besoin d'effectuer des tâches de construction plus complexes, alors écrivez votre propre exécutable de construction et exécutez-le à l'aide des commandes de construction (il est généralement utile de transmettre les emplacements des répertoires en tant qu'arguments à votre exécutable de construction), par exemple :
KeePass.exe --plgx-create C:\VotreRépertoireDeGreffon --plgx-build-post:"{PLGX_TEMP_DIR}MonBuild.exe {PLGX_TEMP_DIR} {PLGX_CACHE_DIR}"

Le débogage PLGX : lorsque l'option de ligne de commande --debug est transmise et qu'un greffon PLGX ne parvient pas à se compiler, alors la sortie de tous les compilateurs essayés est enregistrée dans un fichier temporaire.