Paramétrage utilisateur avec Active Setup
Sommaire
I. Présentation
Le packaging d'application est généralement à la charge de l'éditeur, qui fournit un package MSI ou un Setup.exe que vous n'avez plus qu'à intégrer dans vos déploiement. Habituellement, les programmes proposent des commutateurs d'installation silencieuse et la technologie MSI permet d'associer des transformations au travers de fichier .MST.
En tant qu'administrateur ou technicien de déploiement vous allez pouvoir "scripter" tout ceci sans difficulté. Cela étant, comment gérer le cas d'un programme qui doit terminer sa configuration dans l'environnement de chaque utilisateur ?
En fait, la difficulté réside dans le ciblage de l'environnement propre à chaque utilisateur (p.ex. HKCU, %APPDATA%) lors de la première connexion sur un poste. (Soit l'étape de création du profil Windows.)
La première solution qui vient à l'esprit (si l'on dispose d'un Active Directory et que le poste est membre du domaine), c'est d'utiliser des préférences de GPO, ou via un script de GPO. (ou de MLGPO pour les petits malins qui auraient lu mon article 🙂 )
La seconde solution, plus empirique, consisterait à exécuter des commandes via les clés run / runonce, ou bien via le planificateur de tâches.
Très bien, c'est vous qui voyez, mais ce que je vous propose me semble plus propre et élégant quel que soit l'environnement Domaine ou Workgroup. Bien connue des "packageurs/intégrateurs d'application", cette technique appelée "Active Setup" n'en est pas moins "accessible" aux techniciens de déploiement, sans outillage spécifique….
II. Principes
En quelques mots, "Active Setup" désigne un processus déclenché à chaque ouverture de session d'un utilisateur durant laquelle les entrées de registre suivantes sont comparées :
HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\%APPNAME%
HKCU:\Software\Microsoft\Active Setup\Installed Components\%APPNAME%
Si les entrées de la ruche utilisateur HKCU n'existent pas ou si leur numéro de version est inférieur à celui mentionné dans HKLM, l'application spécifiée est exécutée pour l'utilisateur courant.
Exemple:
Sur l'aspect "déclencheur ponctuel", le principe de l'Active Setup est assez similaire à celui des clés "RunOnce" mais présente à mon avis une meilleure "maintenabilité" en cas d'évolution du besoin, ne serait-ce que par la notion de version.
III. Déclarer votre "Active Setup"
Pour implémenter vos propres commandes "Active Setup", il suffit de :
- Créer une clé "HKLM\SOFTWARE\Microsoft\Active Setup\Installed Components\%APPNAME%"
(Où %APPNAME% correspond à une chaîne arbitraire qui peut être le nom de l'application, ou son code produit GUID si vous utilisez un MSI. L'important est qu'il soit unique sur le poste de travail !)
- Ajouter les 2 valeurs de type chaine (REG_SZ ou REG_EXPAND_SZ) suivantes :
- StubPath = "Votre ligne commande"
- Version=1,0
La commande contenue dans l'entrée "StubPath" peut être un exécutable, avec ou sans paramètre, un script ou toute commande valide.
Attention à respecter la "protection" de certains caractères spéciaux dans les champs de données du registre. En effet, si vous utilisez des lignes de commande contenant des espaces, tels que des noms de chemins longs, il est nécessaire de protéger les guillemets et les barres obliques inversées (backslaches), comme par exemple :
"StubPath"="cscript.exe //nologo \"C:\\Program Files (x86)\\Adobe\\Reader 10.0\\Reader\\EULA.vbs\""
Ici, le "//" est une spécificité de l'interpréteur cscript.exe ou wscript.exe mais en revanche, vous constatez la présence des "antislash" en gras devant chacun des caractères à protéger.
Remarques :
Si la commande est trop conséquente (plutôt rarissime) pour une entrée de type REG_SZ, vous pouvez déclarer la valeur "StubPath" en tant que "Valeur de chaîne extensible", soit "REG_EXPAND_SZ"
Le champ "Version" est à votre discrétion mais la norme "MSI" préconise l'usage de virgules dans la déclaration des valeurs.
Il est assez fréquent, surtout pour les packages MSI, d'utiliser un "Active Setup" effectuant une "réparation" dans le contexte utilisateur, comme suit :
"StubPath"="msiexec.exe /fou {ProductCode} /qb"
Remarque importante : Le déclenchement des commandes "Active Setup" n'est pas assujetti à la disponibilité de l'application dans le contexte de l'utilisateur. En d'autres termes, cela signifie que même si l'utilisateur n'utilise pas l'application installée, la commande sera exécutée malgré tout.
Aparté MSI :
Pour connaitre, le "ProductCode" d'une application livrée au format MSI, je vous conseille d'utiliser l'outil gratuit "InstEd" que vous pour télécharger ici . Pour les néophytes, l'information se trouve dans la table "Property" des packages MSI.
IV. Démonstration et cas pratiques
Pour illustrer cet article, je vous propose quelques petits exemples
A. Vérifier le fonctionnement avec une commande générique simple
Avant de procéder à une mise en œuvre pratique, commencez par vérifier le bon fonctionnement d'un Active Setup en procédant comme suit, sur un poste de test :
- Exécutez "regedit" en tant qu'administrateur, puis sélectionnez la clé
"HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\"
- Créez une nouvelle clé, nommée "Test Active Setup"
- Modifiez la valeur par défaut avec "Calculatrice via Active Setup"
- Créez une nouvelle valeur chaine "Version" avec la donnée "1,0,0"
- Créez une nouvelle valeur chaine "StubPath" avec la donnée "calc.exe"
- Facultatif : Pour conserver cet exemple, ou modèle, sélectionnez la clé "Test Active Setup" puis utilisez le menu "Fichier … Exporter" ou le menu contextuel, et indiquez un nom pour le fichier "TestActiveSetup.reg"
Assurez-vous que l'utilisateur de test n'a pas ouvert de session au préalable et/ou supprimez son profil Windows le cas échéant.
Fermez la session courante puis ouvrez une session avec l'utilisateur de test.
Vous devriez alors constater que la calculatrice est lancée, avant même que le bureau et le menu Démarrer soient affichés. Ce comportement ne sera pas constaté dans les sessions suivantes de cet utilisateur, à moins que son profil Windows soit recréé.
Bien, poursuivons la démonstration en exécutant "regedit" via un compte d'administrateur, puis modifions la valeur "Version" de cet exemple par "1,0,1". Fermez puis rouvrez la session de l'utilisateur de test.
La calculatrice doit se lancer de nouveau car le numéro de version est supérieur au précédent.
Si cette démonstration est concluante, nous pouvons passer à des exemples plus concrets 🙂
B. Configuration du lecteur multimédia VLC
On ne présente plus ce lecteur multimédia universel. Le package d'installation de type NSIS offre de nombreuses options, dont le mode silencieux. Toutefois, chaque utilisateur doit au premier lancement, valider la politique d'accès au réseau. C'est ce que je vous propose de masquer dans cet exemple.
En premier lieu, il vous faut récupérer les fichiers à partir d'une instance installée. Pour cela, lancez VLC, décochez les 2 cases, puis cliquez sur "Continuer"
Ouvrez le menu "Personnaliser l'interface" puis effectuez éventuellement quelques ajustements puis fermez l'application.
Sauvegardez les 3 fichiers situés sous "%APPDATA%\vlc" vers le dossier utilisé par le processus d'installation tel que "Z:\Applications\VLC".
Le script d'installation devra se charger de copier ces fichiers dans un emplacement de votre choix, tel que le dossier de l'application "C:\Program Files\VideoLAN\VLC" ou "C:\Program Files (x86)\VideoLAN\VLC"
Réalisez un script de copie, par exemple en vbscript, comme suit
Set wshShell=CreateObject("WScript.Shell") AppDataPath = wshShell.ExpandEnvironmentStrings("%appdata%") ' Postionnement de variable selon l'architecture du systeme 32 ou 64 bits If wshShell.ExpandEnvironmentStrings("%PROCESSOR_ARCHITECTURE%") = "AMD64" Then ProgramPath = wshShell.ExpandEnvironmentStrings("%ProgramFiles(x86)%") Else ProgramPath = wshShell.ExpandEnvironmentStrings("%ProgramFiles%") End If Set oFSO=CreateObject("Scripting.FileSystemObject") ' Création du dossier vlc dans %appdata% si le dossier n'existe pas sAppdata = AppDataPath & "\vlc" If Not oFSO.FolderExists(sAppdata) Then oFSO.CreateFolder(sAppdata) End If ' Copie des fichiers de configuration oFSO.CopyFile ProgramPath & "\VideoLAN\VLC\vlcrc", sAppdata & "\", True oFSO.CopyFile ProgramPath & "\VideoLAN\VLC\vlc-qt-interface.ini", sAppdata & "\", True oFSO.CopyFile ProgramPath & "\VideoLAN\VLC\ml.xspf", sAppdata & "\", True
Enregistrez ce script sous "vlc-config.vbs" (qui devra également faire partie de la copie initiale via le script d'installation au même titre que les 3 fichiers précédents).
Passons maintenant à la phase de création de l'Active Setup. Pour cela, il existe plusieurs écoles :
- En mode batch via les commandes "reg add", ou via "regedit /s fichierActiveSetup.reg"
- En script vbs, ou Powershell
Le choix dépend donc surtout de la méthode d'installation retenue.
Exemple de fichier VLCActiveSetup32.reg
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Active Setup\Installed Components\VideoLAN Config] @="VideoLAN Media Player Configuration" "Version"="2,2,4" "StubPath"="cscript.exe //B //nologo \"C:\\Program Files\\VideoLAN\\VLC\\vlc-config.vbs\""
Exemple de fichier VLCActiveSetup64.reg
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Active Setup\Installed Components\VideoLAN Config] @="VideoLAN Media Player Configuration" "Version"="2,2,4" "StubPath"="cscript.exe //B //nologo \"C:\\Program Files (x86)\\VideoLAN\\VLC\\vlc-config.vbs\""
Ici, je vous propose une configuration via des exports.reg, mais il est également possible d'assurer la création de ces entrées de registre en mode batch via des commandes "reg add" ou en mode script .vbs ou Powershell.
Ce qui pourrait donner dans un batch d'installation:
@echo off Echo Installation de vlc v2.2.4 - 32 bits ... Start /wait %~dp0vlc-2.2.4-win32.exe /L=1036 /S If "%PROCESSOR_ARCHITECTURE%"=="x86" ( Echo Configuration pour un systeme 32 bits Copy "%~dp0vlcrc" "%ProgramFiles%\VideoLAN\VLC" /Y Copy "%~dp0vlc-qt-interface.ini" "%ProgramFiles%\VideoLAN\VLC" /Y Copy "%~dp0ml.xspf" "%ProgramFiles%\VideoLAN\VLC" /Y Copy "%~dp0vlc-config.vbs" "%ProgramFiles%\VideoLAN\VLC" /Y Regedit /s %~dp0VLCActiveSetup32.reg ) Else ( Echo Configuration pour un systeme 64 bits Copy "%~dp0vlcrc" "%ProgramFiles(x86)%\VideoLAN\VLC" /Y Copy "%~dp0vlc-qt-interface.ini" "%ProgramFiles(x86)%\VideoLAN\VLC" /Y Copy "%~dp0ml.xspf" "%ProgramFiles(x86)%\VideoLAN\VLC" /Y Copy "%~dp0vlc-config.vbs" "%ProgramFiles(x86)%\VideoLAN\VLC" /Y Regedit /s %~dp0VLCActiveSetup64.reg )
A titre d'information, voici le contenu du dossier des sources d'installation
Je vous laisse le soin de faire cette implémentation et vérifier que cela fonctionne 🙂
Par acquis de conscience, vous pouvez vérifier la présence du dossier "vlc" dans "%appdata%" avant de lancer le programme pour la première fois.
C. Gérer l'environnement utilisateur par défaut
La technique "Active Setup" est donc adaptée à tout ce qui touche à l'environnement utilisateur, tel que le registre HKCU et les pointeurs %APPDATA%, %HOMEPATH%, %LOCALAPPDATA%, %USERNAME%, %USERPROFILE%...
Par exemple, le sujet de l'épinglage est récurent dans les entreprises qui souhaitent conserver un minimum de contrôle sur les environnements de leurs utilisateurs. On peut donc envisager des actions d'aménagement de l'environnement utilisateur lors de sa première connexion, tel que la suppression d'épinglages ou raccourcis.
Exemple :
Contenu du script d'installation "Install.bat"
@echo off Copy "%~dp0UserInit.vbs" %windir% /Y Regedit /s %~dp0UI-ActiveSetup.reg
Contenu du fichier "UI-ActiveSetup.reg"
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Active Setup\Installed Components\UserInit] @="User Environment Configuration" "StubPath"="cscript.exe //B //nologo C:\\Windows\\UserInit.vbs" "Version"="1,0,0"
Contenu du script de configuration "UserInit.vbs"
' Nettoyage des raccourcis Internet Explorer Set WshShell = WScript.CreateObject("WScript.Shell") sPROGRAMFILES = WshShell.ExpandEnvironmentStrings("%ProgramFiles%") sPROGRAMFILES86 = WshShell.ExpandEnvironmentStrings("%ProgramFiles(x86)%") sAPPDATA = WshShell.ExpandEnvironmentStrings("%APPDATA%") Set objShell = CreateObject("Shell.Application") Set objFolder = objShell.Namespace(sPROGRAMFILES & "\Internet Explorer") Set objFolderItem = objFolder.ParseName("iexplore.exe") Set colVerbs = objFolderItem.Verbs For Each objVerb in colVerbs If Replace(objVerb.name, "&", "") = "Détacher de la barre des tâches" Then objVerb.DoIt If Replace(objVerb.name, "&", "") = "Détacher du menu Démarrer" Then objVerb.DoIt Next Set objFolder = objShell.Namespace(sPROGRAMFILES86 & "\Internet Explorer") Set objFolderItem = objFolder.ParseName("iexplore.exe") Set colVerbs = objFolderItem.Verbs For Each objVerb in colVerbs If Replace(objVerb.name, "&", "") = "Détacher de la barre des tâches" Then objVerb.DoIt If Replace(objVerb.name, "&", "") = "Détacher du menu Démarrer" Then objVerb.DoIt Next Set objFSO = CreateObject("Scripting.FileSystemObject") strLNK = sAPPDATA + "\Microsoft\Windows\Start Menu\Programs\Accessories\System Tools\Internet Explorer (sans modules complémentaires).lnk" If objFSO.FileExists(strLNK) Then objFSO.DeleteFile strLNK, True strLNK = sAPPDATA + "\Microsoft\Windows\Start Menu\Programs\Internet Explorer.lnk" If objFSO.FileExists(strLNK) Then objFSO.DeleteFile strLNK, True
A titre d'information, voici le contenu du dossier des sources d'installation
Une fois de plus, je vous laisse le soin de réaliser cet exemple. Par la suite, lors les besoins évoluent et/ou que le script "UserInit" est modifié, il suffit d'incrémenter la valeur "Version" (sous [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Active Setup\Installed Components\UserInit] ) pour que la mise à jour soit appliquée à la prochaine connexion de l'utilisateur.
V. Conclusion
Cette technique "Active Setup" est à mon humble avis, très intéressante, mais je pense qu'il faut l'utiliser à bon escient, typiquement lorsqu'il n'y a pas d'autre solution plus adaptée et que l'application en question ou l'infrastructure ne présente pas d'autre point d'entrée pour effectuer ces actions.
Typiquement, j'opte pour la technique "Active Setup" pour les applications qui requiert des réglages HKCU et déployées via une solution MDT afin d'assurer une configuration minimale, dans l'attente des ajustements apportés par l'infrastructure de domaine.
Je terminerais ce billet en précisant que cette technique est pleinement fonctionnelle sur toutes les versions de Windows. A vous de juger si elle peut alimenter votre boite à solutions 🙂
Bonne continuation
Bonjour,
Je crois qu’il y a beaucoup plus simple en copiant les profils d’application voulu dans C:\Users\Default
Bonjour Florent,
La solution de copie des fichiers est effectivement bcp plus simple pour ce cas de figure (présence de fichier dans le dossier %Appdata%). Toutefois, si le besoin est plus complexe, tel qu’épingler des éléments dans un menu, modifier des clés HKCU, ou des actions conditionnelles, exploiter des variables de ce contexte, ou un contenu spécifique, lancer une réparation .msi, etc, le recours à un script Active Setup n’aura que la limite des droits utilisateur mais accès à tout le périmètre de ce dernier.
Bonne continuation
Bonjour,
Cette technique fonctionne-t-elle dans les cas où les utilisateurs ne sont pas administrateurs de leur PC ? Je suppose que non car les accès registre sont verrouillés.
Bonjour,
Je confirme que cette technique n’octroie pas de droit et sert simplement à « finaliser » des opérations de configuration dans le contexte des utilisateurs (avec leurs privilèges respectifs) – L’idée étant de cibler des dossiers et/ou ruche HKCU qui que n’existent qu’après une ouverture de session. Pour effectuer des opérations qui requièrent des droits d’administrateur, on peut éventuellement passer par des techniques telles que MLGPO https://www.it-connect.fr/mlgpo-exploiter-les-strategies-locales-multiples/
Bonne continuation