Guide Ultime
PulsiForms
Ultimate Guide
PulsiForms
pfstdlib_ps1.js, export.js, psguard.js).
pfstdlib_ps1.js, export.js, psguard.js).
🔄 Comment PulsiForms génère le PS1How PulsiForms generates the PS1
PulsiForms n'est pas un éditeur de texte : c'est un compilateur visuel. Vos actions graphiques (drag & drop, propriétés, code d'événement) sont transformées en un script PowerShell autonome.
PulsiForms is not a text editor: it is a visual compiler. Your graphical actions (drag & drop, properties, event code) are turned into a self-contained PowerShell script.
À l'export, PulsiForms injecte automatiquement la bibliothèque PF-Script Stdlib (issue de pfstdlib_ps1.js) en tête du script. Vous disposez ainsi de fonctions prêtes à l'emploi (Show-PF, Get-PF, Start-PF…) sans rien réécrire.
On export, PulsiForms automatically injects the PF-Script Stdlib (from pfstdlib_ps1.js) at the top of the script. You get ready-to-use functions (Show-PF, Get-PF, Start-PF…) without rewriting anything.
{ ... } de l'événement. PulsiForms s'occupe de la création, du positionnement et du style.The code you write in the Code PS editor is placed inside the event's { ... } block. PulsiForms handles creation, positioning and styling.❌ « Variable non déclarée » — le piège n°1"Variable not declared" — pitfall #1
L'erreur la plus fréquente vient d'une incompréhension du scope PowerShell. Chaque événement Add_Click({ ... }) est un scriptblock avec son propre scope : une variable créée dans un événement n'existe pas dans un autre.
The most common error comes from misunderstanding PowerShell scope. Each Add_Click({ ... }) event is a scriptblock with its own scope: a variable created in one event does not exist in another.
# Les 3 scopes à connaîtreThe 3 scopes to know
$script:form et $script:_controls.$script:form and $script:_controls.{ } courant.{ } block.TextBox_3, écrivez $TextBox_3 — pas $TextBox3, pas $tb.The control's variable name in the Properties panel is exactly what to type. If the control is named TextBox_3, write $TextBox_3 — not $TextBox3, not $tb.# Référencer le formulaireReferencing the form
📐 Règles fondamentalesCore rules
| ❌ Ne pas écrireDon't write | ✅ Compatible PulsiFormsPulsiForms compatible |
|---|---|
| $form.Close() | $script:form.Close() |
| [Windows.Forms.MessageBox]::Show("x") | Alert-PF "x" / Show-PF "x" |
| $maVar = "v" (entre 2 events) | $global:maVar = "v" |
| Write-Host "debug" | Show-PF "debug" |
| Start-Sleep -Seconds 3 (gèle l'UI) | Sleep-PF -Ms 3000 / Wait-PF |
| $script:txt.Text depuis -Work | Write-PF $script:txt "v" (thread-safe) |
*-PF sont thread-safe (gestion automatique de InvokeRequired / .Invoke()) : vous pouvez les appeler depuis un callback async sans crash inter-thread.All *-PF functions are thread-safe (automatic InvokeRequired / .Invoke() handling): you can call them from an async callback without cross-thread crashes.⚡ Async — ne jamais geler l'interfaceAsync — never freeze the UI
Un traitement long (lecture de fichiers, requête réseau, boucle lourde) exécuté directement dans un Add_Click gèle l'interface : la fenêtre devient blanche, Windows affiche « Ne répond pas ». PulsiForms fournit trois outils pour l'éviter. Choisissez selon ce dont vous avez besoin.
A long task (file reading, network request, heavy loop) run directly inside an Add_Click freezes the UI: the window goes white and Windows shows "Not responding". PulsiForms provides three tools to avoid this. Choose based on what you need.
├─ NON · tâche de fond, je veux juste le résultat à la finbackground task, I just want the result at the end → Start-PF
├─ NON · + je veux un dialog « patientez » avec Annuler+ I want a "please wait" dialog with Cancel → Wait-PF
└─ OUI · boucle courte qui met à jour une ProgressBar en directshort loop updating a ProgressBar live → Sleep-PF
-Work de Start-PF et Wait-PF s'exécute dans un runspace isolé (autre thread). Il n'a aucun accès à $script: ni aux contrôles. Pour faire entrer des données → paramètre -With @{}. Pour récupérer le résultat → bloc -Then.
The runspace golden rule. The -Work block of Start-PF and Wait-PF runs in an isolated runspace (separate thread). It has no access to $script: or controls. To pass data in → -With @{}. To get the result out → the -Then block.
-Work ScriptBlock exécuté en arrière-plan (runspace isolé). Reçoit $_shared en argument — qui contient les clés passées via -With. · -Then callback UI au succès, reçoit le résultat de -Work. · -Catch callback UI en cas d'erreur, reçoit le message. · -With hashtable de données injectées dans le runspace.
-Work ScriptBlock run in the background (isolated runspace). Receives $_shared as argument — containing the keys passed via -With. · -Then UI callback on success, receives -Work's result. · -Catch UI callback on error, receives the message. · -With hashtable of data injected into the runspace.
Même moteur que Start-PF, mais affiche un dialog modal avec spinner animé. Le worker doit tester $_shared["_canceled"] pour s'arrêter proprement si l'utilisateur clique Annuler. Retourne le résultat de -Work, ou $null si annulé/erreur.
Same engine as Start-PF, but shows a modal dialog with an animated spinner. The worker must check $_shared["_canceled"] to stop cleanly if the user clicks Cancel. Returns -Work's result, or $null if cancelled/error.
Contrairement à Wait-PF, Sleep-PF reste sur le thread UI (boucle DoEvents) : $script: et les contrôles sont accessibles directement dans la boucle appelante. Idéal pour une boucle courte qui met une ProgressBar à jour. Retourne $true si Annuler cliqué. Toujours appeler Sleep-PF -End en fin de boucle (dans un finally).
Unlike Wait-PF, Sleep-PF stays on the UI thread (DoEvents loop): $script: and controls are directly accessible in the calling loop. Ideal for a short loop updating a ProgressBar. Returns $true if Cancel was clicked. Always call Sleep-PF -End at the end of the loop (in a finally).
-Work de Start-PF/Wait-PF (runspace séparé). Sleep-PF est réservé au thread UI.Never use Sleep-PF inside a Start-PF/Wait-PF -Work block (separate runspace). Sleep-PF is for the UI thread only.# Tableau comparatifComparison table
| Start-PF | Wait-PF | Sleep-PF | |
|---|---|---|---|
| ThreadThread | Runspace | Runspace | UI |
| Bloquant ?Blocking? | Non / No | ModalModal | Boucle UIUI loop |
| DialogDialog | — | ✅ spinner + Annuler | ✅ spinner + Annuler |
| Accès $script:$script: access | ❌ -With/-Then | ❌ -With/-Then | ✅ direct |
| UsageUse | tâche de fondbackground task | opération longue avec attentelong op with wait | boucle + ProgressBarloop + ProgressBar |
📚 Référence des commandes PF-ScriptPF-Script command reference
Toutes ces fonctions sont injectées automatiquement à l'export. Signatures vérifiées dans pfstdlib_ps1.js (Stdlib v2.0).
All these functions are auto-injected at export. Signatures verified against pfstdlib_ps1.js (Stdlib v2.0).
# Notifications & dialogsNotifications & dialogs
$null -ne $val : l'utilisateur peut cliquer Annuler.Always test $null -ne $val: the user can click Cancel.# Contrôles — lire, écrire, remplirControls — read, write, fill
TextBox→string · CheckBox→bool · DateTimePicker→DateTime · TrackBar/NumericUpDown→nombre · ComboBox→SelectedItem ou Text · ListBox→SelectedItem · DataGridView→ligne liée (DataBoundItem).
TextBox→string · CheckBox→bool · DateTimePicker→DateTime · TrackBar/NumericUpDown→number · ComboBox→SelectedItem or Text · ListBox→SelectedItem · DataGridView→bound row (DataBoundItem).
-Then de Start-PF/Wait-PF. Gère InvokeRequired automatiquement.Required to update the UI from a Start-PF/Wait-PF -Then callback. Handles InvokeRequired automatically.Accepte un tableau de strings, de Hashtables ou de PSCustomObjects. Pour un DataGridView, les colonnes sont créées et redimensionnées automatiquement. $null vide le contrôle.
Accepts an array of strings, Hashtables or PSCustomObjects. For a DataGridView, columns are auto-created and resized. $null clears the control.
Sans argument : verrouille tout le formulaire + curseur sablier. Avec -Controls : seulement les contrôles fournis.
No argument: locks the whole form + wait cursor. With -Controls: only the given controls.
# Données & fichiersData & files
$null -ne $result — l'utilisateur peut annuler.Test $null -ne $result — the user can cancel.Save-PF détecte le format : collection d'objets → CSV (UTF8), sinon → TXT. Load-PF détecte le délimiteur (; ou ,) ou renvoie les lignes brutes.
Save-PF detects the format: object collection → CSV (UTF8), else → TXT. Load-PF detects the delimiter (; or ,) or returns raw lines.
# Style & navigationStyle & navigation
-Code attend un entier (notation 0xE74D acceptée), pas une chaîne hexadécimale.-Code expects an integer (0xE74D notation works), not a hex string.🎛️ Patterns de contrôles courantsCommon control patterns
# TextBox
# DataGridView
# ComboBox / CheckBox
💼 Cas d'usage completsComplete use cases
# Formulaire avec validationForm with validation
# Traitement long non-bloquantLong non-blocking task
🤖 IA dans PulsiForms — clés Claude & MistralAI in PulsiForms — Claude & Mistral keys
PulsiForms intègre deux assistants en ligne (en plus de l'IA locale hors-ligne). Vous fournissez votre propre clé API — c'est le modèle BYOK (Bring Your Own Key) : vos clés ne sont jamais stockées sur nos serveurs.
PulsiForms ships two online assistants (plus the offline local AI). You provide your own API key — this is the BYOK (Bring Your Own Key) model: your keys are never stored on our servers.
claude-sonnet-4-6.claude-sonnet-4-6.Ctrl+Shift+P). Wiring rapide & AI Code par contrôle. Modèle : mistral-large-latest.Ctrl+Shift+P). Quick wiring & per-control AI Code. Model: mistral-large-latest.localStorage, les cookies, le DOM ou la console, et transitent uniquement par en-tête (X-Claude-Key / X-Mistral-Key) vers le proxy.
BYOK security. Your keys are encrypted with AES-256-GCM (Web Crypto API) and stored either in an encrypted session or in pure memory (closure variable, wiped on close). They are never written to localStorage, cookies, the DOM or the console, and travel only via header (X-Claude-Key / X-Mistral-Key) to the proxy.
# Créer votre clé Claude (Anthropic)Create your Claude (Anthropic) key
sk-ant-….Click Create Key, name it (e.g. "PulsiForms"), then copy the generated key. It starts with sk-ant-….sk-ant-… et validez.In PulsiForms, open the AI panel, click the Claude key indicator, paste your sk-ant-… key and confirm.# Créer votre clé MistralCreate your Mistral key
sk-…).Enable billing if needed (Billing), then click Create new key and copy the key (format sk-…).Ctrl+Shift+P), cliquez sur l'indicateur de clé Mistral, collez votre clé et validez.Open PulsiForms Studio (Ctrl+Shift+P), click the Mistral key indicator, paste your key and confirm.| Claude | Mistral | |
|---|---|---|
| Créer la cléCreate key | console.anthropic.com/settings/keys | console.mistral.ai/api-keys |
| FormatFormat | sk-ant-… | sk-… |
| Modèle par défautDefault model | claude-sonnet-4-6 | mistral-large-latest |
| Où dans PulsiFormsWhere in PulsiForms | Panneau IA (bas)AI panel (bottom) | Studio (Ctrl+Shift+P) |
# L'IA locale (hors-ligne)The local AI (offline)
🛡️ PS.Guard v3 & Linter internePS.Guard v3 & internal linter
PulsiForms protège votre code à deux niveaux, synchronisés entre eux et avec la Stdlib.
PulsiForms protects your code at two levels, kept in sync with each other and with the Stdlib.
| SystèmeSystem | QuandWhen | SurveilleWatches |
|---|---|---|
| Linter PF_* | Temps réel, à l'écritureReal-time, while typing | Code de l'événement (alias, variables, propriétés)Event code (aliases, variables, properties) |
| PS.Guard PSG-* | Après export du .ps1After .ps1 export | Script complet (sécurité, qualité, perf)Whole script (security, quality, perf) |
# PS.Guard v3 — 33 règles, 3 catégoriesrules, 3 categories
Invoke-Expression, mots de passe en clair, ConvertTo-SecureString -AsPlainText, Net.WebClient, Set-ExecutionPolicy Bypass, processus cachés, Base64.Invoke-Expression, plaintext passwords, ConvertTo-SecureString -AsPlainText, Net.WebClient, Set-ExecutionPolicy Bypass, hidden processes, Base64.$Error[0] dans catch, if/elseif multiples, alias (60+), cmdlets dépréciées (Get-WmiObject→Get-CimInstance…).$Error[0] in catch, multiple if/elseif, aliases (60+), deprecated cmdlets (Get-WmiObject→Get-CimInstance…).New-Object Size, [CmdletBinding()], faux positifs perf neutralisés par PSGuard-disable/enable.New-Object Size, [CmdletBinding()], perf false-positives silenced via PSGuard-disable/enable.# Correction automatique « ⚡ Appliquer »Auto-fix "⚡ Apply"
Pour les règles auto-corrigeables, PS.Guard propose un bouton ⚡ Appliquer qui réécrit le code (alias → cmdlet complète, catch vide → Write-Error + throw, $Error[0] → $_…). Les règles de sécurité exigent une correction manuelle (jamais auto-corrigées, par prudence).
For auto-fixable rules, PS.Guard offers a ⚡ Apply button that rewrites the code (alias → full cmdlet, empty catch → Write-Error + throw, $Error[0] → $_…). Security rules require a manual fix (never auto-corrected, by design).
# PSGuard-disable PSG-P02 … # PSGuard-enable PSG-P02.False positive on a static block? Wrap it: # PSGuard-disable PSG-P02 … # PSGuard-enable PSG-P02.# Linter PF_* (temps réel)(real-time)
- PF_ALIAS — alias détecté (
ls,cat,rm…) → suggère la cmdlet complète. - PF_ALIAS — alias detected (
ls,cat,rm…) → suggests the full cmdlet. - PF_UNDECLARED — variable utilisée sans assignation visible. Solution :
$global:entre événements. - PF_UNDECLARED — variable used without a visible assignment. Fix:
$global:across events. - PF_INVALID_PROP — propriété inexistante sur un contrôle (
.Texte→.Text,.MaxChars→.MaxLength). - PF_INVALID_PROP — non-existent property on a control (
.Texte→.Text,.MaxChars→.MaxLength).
$global:).The linter analyses each event in isolation. Canvas controls and 50+ common variables are whitelisted — a variable shared between two events is still flagged (use $global:).⚠️ Top 10 des erreurs à éviterTop 10 mistakes to avoid
| # | ❌ ErreurMistake | ✅ SolutionFix |
|---|---|---|
| 1 | Variable partagée sans $global:Shared var without $global: | $global:maVar |
| 2 | $form.Close() | $script:form.Close() |
| 3 | Traitement long dans Add_ClickLong task in Add_Click | Start-PF / Wait-PF / Sleep-PF |
| 4 | Lire $script: dans -WorkReading $script: in -Work | -With @{} + -Then |
| 5 | Start-Sleep -Seconds 3 | Sleep-PF -Ms 3000 |
| 6 | Sleep-PF sans -EndSleep-PF without -End | try/finally + Sleep-PF -Endtry/finally + Sleep-PF -End |
| 7 | Pas de test $null après Pick-PF / Read-PFNo $null test after Pick-PF / Read-PF | if ($null -ne $r) { … } |
| 8 | MessageBox::Show("x") | Alert-PF "x" / Show-PF "x" |
| 9 | Catch videEmpty catch | catch { Write-Error $_; throw } |
| 10 | Mauvais nom de contrôle (casse)Wrong control name (case) | Copier le nom des PropriétésCopy the name from Properties |
$global: / $script:), passez par les fonctions *-PF (thread-safe), ne gelez jamais l'UI (async), et laissez PS.Guard + le linter valider le reste. En cas de doute, demandez à l'IA locale de l'application PulsiForms.
In short: respect scopes ($global: / $script:), go through the *-PF functions (thread-safe), never freeze the UI (async), and let PS.Guard + the linter validate the rest. When in doubt, ask the PulsiForms local AI.