8. Licence et mode démo #
PBToolboxAI est une bibliothèque commerciale. Le contrôle de licence est entièrement hors ligne : aucune connexion, aucune activation, aucun appel serveur. Une clé signée est posée au démarrage, la DLL la vérifie localement.
8.1 Les trois types de clés #
Les clés sont cumulables : appelez PBT_SetLicense autant de fois que nécessaire, la bibliothèque retient une clé par type.
| Type | Porteur | Débride |
|---|---|---|
dev | Nominative, un développeur | Uniquement dans l'IDE PowerBuilder |
runtime | Votre société, embarquée dans l'application livrée | Uniquement dans un exécutable compilé |
demo | Fournie avec l'application de démonstration | L'application de démonstration, dans l'IDE, jusqu'à expiration |
Un projet a donc besoin des deux : un siège dev par développeur, et une clé runtime pour l'application livrée à vos clients.
- Une clé
devqui se retrouverait dans un exécutable ne débride rien. - Une clé
runtimene donne aucun poste de développement. - Vos clients finaux n'ont rien à saisir, rien à activer : la clé
runtimeest dans votre code.
La détection « IDE ou exécutable » est faite par la DLL elle-même (nom du process, modules design-time chargés), pas par du code PowerBuilder — elle ne peut pas être contournée depuis vos sources.
8.2 Poser la clé #
Une seule chose à faire, avant l'ouverture de la première fenêtre :
// Declaration - objet application, "Local External Functions"
Function long PBT_SetLicense (string as_client, string as_key) Library "pbtoolboxai.dll"
// Event open de l'objet application
// Local variables
long ll_rc
string ls_dev_key
// La cle RUNTIME va dans le code : elle DOIT partir dans l'exe livre.
ll_rc = PBT_SetLicense(gs_licensee, gs_runtime_key)
// La cle DEV se lit sur le poste : elle ne debride que l'IDE, et embarquee
// dans le code elle partirait dans chaque copie livree sans y servir a rien.
ls_dev_key = ProfileString("pbtoolboxai.ini", "license", "dev", "")
if ls_dev_key <> "" then ll_rc = PBT_SetLicense(gs_licensee, ls_dev_key)
Open(w_main)
La clé se pose par la fonction de la DLL, jamais par une méthode de composant : elle vaut pour tout le processus et doit être posée avant qu'aucun composant n'existe. C'est pour cette même raison que
PBT_LicenseStatusne demande aucun handle.
Le titulaire est passé en clair, en premier argument : c'est le nom (ou l'adresse e-mail) sous lequel la licence a été émise, et il doit correspondre à celui que porte la clé signée. Une clé ne peut donc pas circuler sans le nom de qui l'a achetée.
| Retour | Signification |
|---|---|
0 | Clé valide et retenue |
-1 | Format de clé invalide |
-2 | Signature invalide (clé altérée ou étrangère) |
-3 | Maintenance expirée pour cette version de la bibliothèque (voir 8.5) |
-4 | Clé demo expirée |
-5 | Le titulaire passé ne correspond pas à celui de la clé |
💡 Où mettre quelle clé. La clé
runtimeappartient au code : elle doit se retrouver dans l'exécutable que vous livrez. La clédev, elle, n'a rien à y faire — elle ne débride que l'IDE, donc dans un exe elle ne sert à rien tout en s'y promenant, avec le nom de votre société. Sa place est un fichierpbtoolboxai.inià côté de l'IDE, ou une valeur dans la base de registre.
Poser la clé après la création d'un composant fonctionne aussi : les composants déjà ouverts se débrident immédiatement. Mais le plus simple reste l'event open de l'application.
💡 Conservez la clé dans une constante ou une ressource de votre application. Elle est signée : elle ne contient aucun secret exploitable et ne peut pas être modifiée sans invalider sa signature.
8.3 Vérifier l'état de la licence #
// Declaration
Function long PBT_LicenseStatus (ref string as_json, long al_len) Library "pbtoolboxai.dll"
// Local variables
string ls_status
// L'etat de la licence, en JSON
ls_status = Space(1024)
PBT_LicenseStatus(ls_status, 1024)
// -> {"licensed":true,"ide":false,"keys":{...},"reason":""}
Utile en phase d'intégration pour vérifier qu'une clé est bien prise en compte, ou pour tracer un démarrage dans votre journal applicatif.
8.4 Le mode démo #
Sans clé valide — ou avec une clé qui ne s'applique pas au contexte (une clé dev dans un exe, par exemple) — la bibliothèque fonctionne en mode démo : tout est utilisable, tout est visible, mais avec des limites — sauf les cinq composants de l'édition communauté, décrits juste en dessous, qui ne sont jamais bridés.
Cinq composants restent gratuits #
L'édition communauté n'a rien à poser : sans aucune clé, cinq composants fonctionnent sans badge et sans limite, indéfiniment.
| Composant | Ce qu'il apporte |
|---|---|
| statictext | Libellé à balises : gras, couleurs, liens, puces, blocs repliables |
| messagebox | Boîte de dialogue thémée, modale, à boutons libres |
| toaster | Notifications en coin d'écran, avec titre, image et actions |
| webbrowser | Navigateur WebView2 hébergé dans une fenêtre PowerBuilder |
| json | Lire et écrire du JSON en PowerScript pur (chemins, types, construction) |
Ce choix est délibéré : les quatre composants visuels sont ceux que l'on rencontre en premier, ils ne portent aucun modèle de données, et ils suffisent à prouver sur un poste verrouillé que le runtime se déploie — l'obstacle réel avant tout achat. json s'y ajoute parce qu'il est écrit en PowerScript pur, sans la DLL : c'est un outil de base, pas un composant.
La liste vit dans la DLL. PBT_LicenseStatus la renvoie telle quelle, dans "free" : votre application peut donc annoncer ce à quoi elle a droit sans clé, plutôt que de le découvrir composant par composant.
Une clé valide prime toujours : sur ces cinq composants comme sur les autres, elle rétablit votre nom et votre édition.
Le badge #
Chaque composant affiche un badge « PBToolboxAI — DEMO », non masquable.
Les limites fonctionnelles #
| Composant | Limite en mode démo |
|---|---|
| tab | 3 onglets visibles dessinés au plus (le composant garde toutes vos pages : la clé les montre) |
| ribbon | 2 onglets maximum |
| toolbar | 6 items affichés, toutes barres confondues ; 6 entrées par niveau de menu déroulant ; 6 choix par liste déroulante |
| tilesbox | 8 tuiles affichées |
| commandpalette | 5 commandes affichées |
| speechout | 4 phrases et 400 caractères par lecture (file d'attente comprise), puis la mention démo est dite ; passées les 4 premières phrases, chaque lecture se termine par elle |
| crypto | textes de 2048 caractères, fichiers et blobs de 2048 octets au plus, à l'entrée comme à la sortie (un déchiffrement ou un décodage aussi) |
| restclient | corps des réponses coupés à 4096 caractères, ni téléchargement, ni téléversement, ni requête de plage (Range) |
| soundplayer | seules les 10 premières secondes d'un son sont jouées (quelle que soit la vitesse), et deux notes descendantes le disent |
| video | un film s'arrête après 10 secondes ; ni saut ni capture d'image au-delà |
| xml | documents de 65 536 caractères au plus, modifications comprises ; un document bâti plus long n'est ni validé (of_is_valid faux) ni indenté (of_pretty vide) |
| listbar | 6 entrées affichées, toutes sections confondues — une recherche ou un of_from_datastore ne montre que ces six-là |
| statusbar | 4 panneaux affichés ; 6 entrées par liste déroulante d'un panneau (les séparateurs ne comptent pas), une dernière ligne grisée dit combien restent cachées |
| contextmenu | 6 entrées par liste, à chaque niveau de cascade (les séparateurs et les en-têtes ne comptent pas) ; les autres restent en mémoire sans être affichées, et une dernière ligne grisée le dit |
| menubar | 3 menus sur la barre ; 6 entrées par liste et 12 par menu, toutes ses cascades comprises (les séparateurs ne comptent pas) ; une liste coupée finit par une ligne grisée qui le dit |
| radialmenu | 4 branches par couronne au plus (moins si ii_max_sectors est plus petit), sans branche « Plus », et un seul niveau de sous-roues (une branche plus profonde est grisée) ; une couronne coupée finit par un secteur grisé « +N », et « PBToolboxAI — DEMO » est écrit sous le moyeu |
| shellexplorer | 8 nœuds par niveau de l'arbre |
| stepbar | 4 étapes affichées |
| buttonbar | 4 boutons affichés ; les suivants ne sont ni dessinés ni déclenchables au clavier (leur lettre Alt reste à la fenêtre) |
| crosstab | 500 lignes de source utilisées, export et copie désactivés ; of_get_cell_value et of_get_cell_rows marchent sur ces 500 lignes et rendent les mêmes chiffres qu'à l'écran |
| breadcrumb | 4 segments affichés, les derniers du chemin ; 6 branches par menu de branches (une note de démo dit le reste) et 6 suggestions de saisie |
| jsontree | Les 200 premières lignes du document affichées, 20 000 caractères au plus (une ligne plus longue est coupée) ; la recherche et la sélection s'y tiennent |
| xmltree | Les 200 premières lignes du document affichées, 20 000 caractères au plus (une ligne plus longue est coupée) ; la recherche et la sélection s'y tiennent |
| datagrid | 100 lignes affichées, exports CSV et Excel désactivés, copie (Ctrl+C) aussi |
| markdownview | Le début du document : 40 blocs (un titre, un paragraphe, une entrée de liste, une ligne de tableau comptent chacun pour un ; un bloc de code est coupé à 40 lignes) ou 4 000 caractères du document, le premier atteint — un bloc plus long est coupé —, suivis d'une note ; la recherche et la table des matières s'en tiennent à eux |
| form | 6 champs, les premiers affichés dans l'ordre de l'écran — un champ d'une section repliée compte aussi : déplier ne redessine rien ; les autres restent en mémoire et dans of_values sans être affichés ni jugés |
| propertygrid | 8 lignes de propriétés, comptées dans l'ordre de l'écran (vue par catégorie) : un groupe fermé compte pour une ligne, ses sous-propriétés ne comptent qu'une fois le groupe ouvert, les en-têtes de catégorie ne comptent pas ; le reste demeure en mémoire et dans of_values sans être affiché, et ni un résumé ni la recherche n'en lisent la valeur |
| kanban | les 4 premières colonnes visibles, 5 cartes par colonne comptées dans l'ordre de la colonne parmi les cartes visibles, chacune suivie d'une note ; le compte et la somme d'un en-tête ne disent que les cartes dessinées ; les autres restent en mémoire et se déplacent sans être affichées |
| gantt | 12 tâches dessinées, les premières lignes de la grille dans son ordre (le contenu d'un récapitulatif replié ne compte pas), suivies d'une note ; les autres restent en mémoire, dans le chemin critique et dans les dates et l'avancement du récapitulatif qui les contient, sans être affichées ni sélectionnables |
| scheduler | Les 12 premiers rendez-vous de la plage à l'écran, les autres restent en mémoire sans être affichés |
| angulargauge | Les 3 premières plages visibles dessinées (une plage masquée ne compte pas) ; les autres restent en mémoire sans être affichées, et la clé posée les montre sans rien renvoyer |
| chartcartesian | Les 3 premières séries dessinées, légende comprise ; les autres restent en mémoire sans être affichées, et la clé posée les montre sans rien renvoyer |
| chartpie | Les 5 premières parts dessinées, légende comprise, et les pourcentages calculés sur elles ; les autres restent en mémoire sans être affichées, et la clé posée les montre sans rien renvoyer |
| gauge | Les 3 premières plages visibles dessinées (une plage masquée ne compte pas) ; les autres restent en mémoire sans être affichées, et la clé posée les montre sans rien renvoyer |
| carousel | Les 6 premiers éléments visibles dessinés, dans l'ordre du carrousel (un élément masqué ne compte pas) ; les autres restent en mémoire sans être affichés ni sélectionnables, et la clé posée les montre sans rien renvoyer |
| treeview | Les 8 premiers nœuds de chaque niveau dessinés, sous chaque parent, dans l'ordre du modèle, et 200 nœuds dans tout l'arbre, les premiers ajoutés — avant le tri, la recherche et le masquage (un nœud masqué compte, une recherche ou un tri ne montrent jamais le neuvième, lots et groupes compris ; un total ne compte jamais ce que le plafond cache) ; les autres restent en mémoire sans être affichés ni sélectionnables, et la clé posée les montre sans rien renvoyer ; of_export_csv et of_export_xlsx sont refusés |
| dockcontainer | 3 panneaux : le quatrième of_add_panel rend -6, son contrôle reste à sa place, visible |
| codeeditor | Les 200 premières lignes affichées et modifiables, suivies d'une note ; les autres restent en mémoire et dans is_text sans être affichées : la recherche, les marqueurs et il_doc_line s'en tiennent aux lignes affichées, et un texte collé qui dépasse va rejoindre les lignes en mémoire |
| Tous les autres | Badge uniquement — aucune limite fonctionnelle |
Ces limites s'appliquent au rendu : rien n'échoue, l'affichage est tronqué. Vous pouvez donc évaluer chaque composant réellement, sur vos données, avant d'acheter.
Poser une clé valide lève instantanément toutes ces limites et retire le badge, sans redémarrer l'application.
8.5 Perpétuel + maintenance #
La licence est perpétuelle : les versions couvertes par votre période de maintenance fonctionnent pour toujours, y compris après l'expiration de celle-ci.
Concrètement, la clé porte une date de fin de maintenance, comparée à la date de compilation de la DLL :
- une version de la bibliothèque publiée pendant votre maintenance est débridée définitivement ;
- une version publiée après l'expiration renvoie
-3: renouvelez la maintenance pour y accéder ; - vos applications déjà livrées ne sont jamais affectées : elles embarquent la version qu'elles ont toujours utilisée.
8.6 Questions fréquentes #
Ma clé est-elle vérifiée en ligne ? Non. Aucun réseau, jamais. La vérification est une signature RSA validée localement par Windows.
Mes clients ont-ils besoin d'une clé ? Non. Votre clé runtime est dans votre application ; ils ne voient jamais rien de la licence.
Que se passe-t-il si j'oublie PBT_SetLicense en production ? L'application fonctionne, mais chaque composant affiche le badge démo et les limites du tableau ci-dessus s'appliquent. C'est le premier point à vérifier si un badge apparaît chez un client.
Puis-je poser une clé dev et une clé runtime dans le même code ? Oui — c'est même le cas courant : la dev sert quand vous exécutez depuis l'IDE, la runtime quand vous exécutez l'exe. Chacune est ignorée dans l'autre contexte.
Le badge apparaît alors que la clé est posée. Trois causes, par ordre de fréquence : (1) clé dev alors que vous exécutez un exe compilé, ou l'inverse ; (2) retour de PBT_SetLicense non testé — vérifiez qu'il vaut 0 ; (3) maintenance expirée pour la version de DLL installée (retour -3). PBT_LicenseStatus tranche en une ligne.
Une clé est nominative. Une clé dev est liée à un développeur, une clé runtime à votre société. Ne les partagez pas hors de votre équipe.