Lors de la première tentative de déploiement d'une application sur un équipement industriel, j'ai été confronté à une erreur « Accès refusé ». J'ai d'abord soupçonné une panne matérielle. C'est un collègue qui m'a signalé, de manière anodine, que le « EWF n'était pas désactivé ». Cette anecdote illustre bien que, dans le monde de l'embarqué, le système d'exploitation est un environnement qu'il faut maîtriser, pas un allié par défaut.
Le scénario abordé ici – créer un installeur pour un équipement industriel exécutant une version personnalisée de Windows – peut sembler pointu. Cependant, les développeurs de dispositifs médicaux, de bornes en libre-service ou de systèmes embarqués véhiculaires y seront confrontés tôt ou tard.
La cible est Windows18-HD19, une variante du système dont la documentation est rare et les permissions serrées. À l'inverse d'un Windows standard, sa philosophie de conception repose sur l'immuabilité. Une fois démarré, la partition système (C:) agit comme un volume en lecture seule ; toute modification est éphémère, réinitialisée au redémarrage.
Cette architecture garantit stabilité et sécurité, mais rend les méthodes d'installation traditionnelles caduques. Les popups UAC bloquent les installations silencieuses, l'enregistrement de services est soumis à la vérification de signature, et même la modification d'un fichier de configuration nécessite de « dégeler » la partition système.
La solution passe par une adaptation de notre approche. Trois compétences clés sont requises :
- Interaction avec le filtre de protection en écriture (EWF)
- Établir la confiance du système via la signature numérique
- Injecter la configuration sans interaction utilisateur
Cet article détaille la construction, basée sur une expérience réelle, d'un package d'installation fonctionnel pour Windows18-HD19.
Caractéristiques déterminantes du système
Windows18-HD19 n'est pas une simple version allégée de Windows. Dérivé de Windows 10 IoT Enterprise LTSB et spécifiquement taillé pour la carte mère HD19, il n'est pas disponible publiquement ; son SDK est soumis à accord de confidentialité (NDA). Ses traits distinctifs sont :
- Image système minimale d'environ 4.5 Go
- Démarrage en moins de 15 secondes
- EWF (Enhanced Write Filter) activé par défaut
- Gestionnaire des tâches, éditeur de registre et panneau de configuration désactivés
- Composants non essentiels (Edge, Cortana, OneDrive) supprimés
- Secure Boot UEFI obligatoire, requérant une signature pour tous les exécutables et pilotes
L'exigence de signature est critique. Tout fichier .exe non signé sera bloqué avec le message « Impossible de vérifier l'éditeur ». De plus, les politiques de groupe figent les paramètres système comme l'UAC. Toute écriture dans des répertoires protégés comme C:\Program Files échoue tant que l'EWF est actif.
Choix de l'outil d'installation : Inno Setup plutôt que WiX
Pour ce type de projet, l'outil WiX Toolset, souvent privilégié pour sa conformité et sa génération de packages MSI, présente des limites. L'exécution via msiexec complique la personnalisation, empêche un contrôle direct de l'EWF et ne garantit pas une exécution totalement silencieuse.
Inno Setup se révèle plus adapté. Il génère un exécutable unique, supporte l'extension par des scripts Pascal, peut s'exécuter avec des privilèges élevés et offre une intégration aisée avec les outils système.
Exemple de script de base (modifié) :
[Setup]
AppName=MonAppEmbarquee
AppVersion=2.1.0
DefaultDirName={pf}\MonAppEmbarquee
OutputBaseFilename=Installateur_MonApp_WIN18HD19
Compression=lzma
SolidCompression=yes
PrivilegesRequired=admin
Uninstallable=no
[Files]
Source: "build\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
[Run]
Filename: "{app}\gestion_service.exe"; Parameters: "/configurer /mode=calme"; \
StatusMsg: "Enregistrement du service..."; \
Flags: runhidden waituntilterminated
La logique essentielle réside dans la section [Code], qui pilote l'état du système :
function PrepareInstallation(): Boolean;
var
CodeRetour: Integer;
begin
// Vérifier l'environnement cible
if GetWindowsVersion() <> $0A000000 then
begin
MsgBox('Cet installeur est destiné exclusivement à Windows18-HD19.', mbError, MB_OK);
Result := False;
Exit;
end;
// Valider les modifications en attente et désactiver l'EWF
Exec('ewfmgr', 'C: -commitall', '', SW_HIDE, ewWaitUntilTerminated, CodeRetour);
Log('EWF: Transactions validées sur la disque.');
Exec('ewfmgr', 'C: -deactivate', '', SW_HIDE, ewWaitUntilTerminated, CodeRetour);
if CodeRetour = 0 then
Log('EWF: Protection en écriture désactivée.');
Result := True;
end;
procedure TraiterEtape(Etape: TSetupStep);
var
CodeRetour: Integer;
begin
if Etape = ssPostInstall then
begin
// Réactiver l'EWF après l'écriture des fichiers
Exec('ewfmgr', 'C: -activate', '', SW_HIDE, ewWaitUntilTerminated, CodeRetour);
if CodeRetour = 0 then
Log('EWF: Protection en écriture réactivée.');
end;
end;
Dans PrepareInstallation(), le script : 1) valide la version du système, 2) force l'écriture des données EWF en attente, 3) désactive temporairement le filtre. La fonction TraiterEtape() le réactive une fois l'installation des fichiers terminée. Cette « décongélation » contrôlée permet de modifier le volume système de manière sûre.
Note : La commande ewfmgr est spécifique à Windows Embedded. Si elle est introuvable, le pack d'outils WEC doit être installé sur le système cible.
Signature numérique : une exigence fondamentale
La désactivation de l'EWF ne suffit pas. Le Secure Boot UEFI impose que chaque exécutable soit signé par une autorité de certification (CA) de confiance. Sans cela, l'exécution est bloquée par le système, indépendamment des privilèges.
Un certificat EV (Extended Validation) de signature de code est recommandé pour sa confiance accrue et sa compatibilité matérielle (via une clé USB token). L'intégration de la signature dans une chaîne d'intégration continue (CI/CD) est une bonne pratique. La commande suivante illustre l'opération (paramètres adaptés) :
signtool sign /fd SHA256 /tr http://timestamp.sectigo.com /td SHA256 /v \
/n "Mon Entreprise" Installateur_MonApp_WIN18HD19.exe
Les paramètres clés sont : /fd pour l'algorithme de hachage, /tr et /td pour l'horodatage (essentiel pour la pérennité de la signature). La clé privée du certificat ne doit jamais être stockée en clair ; un module HSM (Hardware Security Module) ou un coffre-fort cloud comme Azure Key Vault est préconisé. Une surveillance de l'expiration des certificats est cruciale.
Injection de configuration sans interaction
Les équipements embarqués ne disposent souvent pas d'écran ni de périphériques d'entrée. La saisie manuelle des paramètres (adresse serveur, identifiant unique) lors de l'installation est impossible en production.
Une approche par découverte de fichier de configuration externe est utilisée. L'installeur scrute des emplacements prédéfinis pour un fichier (ex. : config.ini). S'il est trouvé, la configuration est chargée automatiquement et les étapes interactives sont ignorées.
const
CHEMIN_CONFIG = 'config.ini';
EMPLACEMENTS: array[0..2] of string = (
'{srcexe}\..\' + CHEMIN_CONFIG, // Répertoire parent de l'installeur
'{tmp}\' + CHEMIN_CONFIG, // Répertoire temporaire système
'D:\Config\' + CHEMIN_CONFIG // Zone de données persistante
);
function LocaliserFichierConfig(): string;
var
I: Integer;
Chemin: string;
begin
Result := '';
for I := Low(EMPLACEMENTS) to High(EMPLACEMENTS) do
begin
Chemin := ExpandConstant(EMPLACEMENTS[I]);
if FileExists(Chemin) then
begin
Result := Chemin;
Break;
end;
end;
end;
procedure ChargerParametres(const Fichier: string);
var
Valeur: string;
begin
Valeur := GetIniString('Reseau', 'AdresseServeur', '', Fichier);
if Valeur <> '' then
WizardForm.ChampReseau.Text := Valeur;
Valeur := GetIniString('Equipement', 'NumeroSerie', '', Fichier);
if Valeur <> '' then
WizardForm.ChampIdentification.Text := Valeur;
end;
Les formats INI, JSON ou YAML sont possibles, mais l'INI reste le plus léger pour des systèmes aux ressources contraintes.
Stratégie d'emplacement des fichiers
Une règle d'or consiste à ne jamais altérer le contenu du répertoire C:\Windows. Outre la protection par l'EWF, ce répertoire est soumis à la WRP (Windows Resource Protection), et toute modification peut compromettre la stabilité ou la supportabilité.
La séparation des emplacements est conseillée :
- C:\Program Files\MonApp\ : Binaires de l'application (sous protection EWF)
- D:\Data\MonApp\ : Données persistantes, journaux, configuration (hors EWF)
- D:\Sauvegardes\ : Images système ou points de restauration
La partition D: doit être formatée en NTFS et exclue de la protection EWF. Ainsi, les mises à jour des binaires sur C: n'affectent pas la configuration sur D:, et les journaux survivent aux redémarrages.
Enregistrement automatique des services
Placer un raccourci dans le dossier de démarrage est inefficace, car ce dossier est sous protection EWF. La méthode correcte consiste à enregistrer l'application comme un service Windows.
sc create "MonServiceApp" binPath= "D:\Data\MonApp\HoteService.exe" start= auto obj= LocalSystem
L'exécutable du service doit lui-même être signé. Le principe du moindre privilège recommande d'utiliser un compte de service dédié à faibles privilèges plutôt que LocalSystem si possible.
Déploiement de masse via réseau PXE/MDT
Pour des centaines d'appareils, une solution manuelle est impraticable. Une infrastructure basée sur PXE et Microsoft Deployment Toolkit (MDT) permet un déploiement entièrement automatisé.
Le flux typique est :
- L'appareil démarre via PXE et se connecte au serveur MDT.
- Un environnement WinPE personnalisé est téléchargé et chargé en mémoire.
- L'image de base Windows18-HD19 est appliquée.
- Des scripts d'installation automatisent l'exécution du package et l'injection de la configuration.
- L'appareil redémarre sur son système opérationnel final.
Cette méthode, combinée à des outils comme WDS et SCCM, permet un suivi en temps réel, une gestion des échecs et une collecte centralisée des journaux d'installation.
Checklist de dépannage et optimisations
Des problèmes courants peuvent survenir :
- « Accès refusé » durant l'installation : EWF non désactivé. Intégrer la désactivation dans le script.
- Configuration perdue après redémarrage : Fichier écrit sur la partition C: au lieu de D:.
- Service ne démarre pas : Exécutable non signé ou chemin contenant des espaces mal échappés.
- Échec de mise à jour OTA : Conflit de version. Implémenter une procédure de nettoyage des anciens fichiers.
Des optimisations supplémentaires améliorent la fiabilité :
- Durée de vie du SSD : Désactiver le fichier d'échange et l'hibernation. Diriger les journaux vers une RAM disk avec synchronisation périodique vers le disque.
- Sécurité : Chiffrement TLS 1.3 pour toutes les communications, mots de passe robustes, audit régulier des journaux d'événements.
- Maintenabilité : Activer l'accès distant (SSH, PowerShell Remoting) avec restrictions IP, offrir une API REST pour le monitoring, prévoir une restauration système par clé GPIO.
Cette méthodologie a permis, dans un projet réel de terminaux d'acquisition d'images médicales, de réduire le temps de déploiement par appareil de 45 à 8 minutes, et le taux d'échec d'installation de 12% à 0.3%. Elle assure une gestion uniforme des versions, des mises à jour à distance et une récupération rapide en cas de panne, transformant une contrainte technique en fiabilité opérationnelle.