1. Créer des paquets WAPT

1.1. Créer son environnement de développement de paquets WAPT

1.1.1. Pré-requis

Attention

  • Il est impératif d’être en possession d’un compte Administrateur Local de la machine pour cette opération.

  • Nous vous conseillons de créer / éditer vos paquets dans un environnement maîtrisé, sain et jetable.

  • L’utilisation d’une machine virtuelle autonome (type Virtualbox ou équivalent) est vivement recommandée.

  • Importer le paquet tis-waptdev dans votre dépôt local et l’installer sur votre machine de développement.

1.1.2. Préconisations concernant l’environnement de test

La méthode préconisée pour tester correctement vos paquets est d’utiliser un échantillon de machines représentatif de votre parc. Donc plus votre parc est hétérogène, plus votre échantillon devra être large.

Cette démarche vise à confronter le paquet WAPT à une multitude de plateformes et environnements afin qu’il devienne le plus abouti possible en régime de test, avant d’être basculé en production.

Pour expliquer le fonctionnement des maturités de paquets, vous pouvez vous référer à cette vidéo.

1.1.3. Démarche de test

1.1.3.1. Systèmes d’exploitation et architectures


Desktop Operating Systems

Windows XP

Windows 7

Windows 10

Windows 10

Redhat and derivatives

Debian and derivatives

Server Operating Systems

Windows Serveur 2008 R2

Windows Serveur 2012

Windows Serveur 2008 R2

Architectures

x86

x64

Deployment Environments

Machine physique et virtuelle

Des ordinateurs portables

On testera si possible les versions RC / Beta des OS si elles sont disponibles (exemple : Windows 10 Creators Update).

1.1.3.2. L’état des mises à jour Windows

  • Un poste Microsoft Windows sans aucune mise à jour Windows Update : l’objectif est de détecter les mises à jour indispensables au bon fonctionnement du logiciel et adapter le paquet en conséquence ;

  • Un poste Microsoft Windows à jour avec les toutes dernières MàJ Windows Update : l’objectif est de détecter les mise à jour en conflit avec le logiciel et d’adapter le paquet en conséquence ;

1.1.3.3. État des installations des logiciels

  • Un poste avec peu de logiciels déjà installés : l’objectif est de détecter une dépendance possible à Java ou autre framework applicatif ;

  • Les postes avec beaucoup de logiciels déjà installés : l’objectif est de détecter un conflit avec une application existante ;

  • Installer les anciennes versions du logiciel : il est possible que l’installeur ne supporte pas l’écrasement d’une installation précédente, dans ce cas il faudra prévoir la désinstallation des anciennes versions avant d’installer la nouvelle version ;

1.2. Les principes de création d’un paquet WAPT à partir d’un modèle depuis la console

Attention

Pour créer des paquets à partir de la console, il faut d’abord avoir installé l’environnement de développement WAPT tis-pyscripter3 ou tis-vscode. Il n’est PAS recommandé d’utiliser tis-pyscripter4.

Nous vous recommandons de télécharger le paquet tis-waptdev et de l’installer sur votre ordinateur où vous créerez les paquets WAPT.

Si vous ne savez plus comment télécharger un paquet depuis le store Tranquil IT, veuillez consulter comment télécharger un paquet dans votre dépôt privé.

Si vous ne savez plus comment installer un paquet, veuillez consulter comment installer un paquet sur un hôte.

1.2.1. Créer un paquet WAPT depuis la Console WAPT

Nous utilisons l’installation MSI de 7-zip téléchargée depuis le site officiel de 7-zip.

  • Télécharger tis-7zip for x64.

  • Créer le modèle de paquet depuis l’installeur.

    Dans la Console WAPT, cliquer sur Outils –> Générer un modèle de paquet :

    Les principes de création d'un paquet WAPT à partir d'un modèle depuis la console

    Les principes de création d’un paquet WAPT à partir d’un modèle depuis la console

    Sélectionnez le fichier d’installation MSI téléchargé (Windows installer(.msi/.msix/.exe)) et remplissez les champs obligatoires. Vérifiez que le nom du paquet ne contient pas de numéro de version.

    Boîte de dialogue demandant des informations lors de la création du packaging WAPT dans la Console WAPT

    Boîte de dialogue demandant des informations lors de la création du packaging WAPT dans la Console WAPT

  • Deux solutions sont proposées :

    • Cliquez sur Editer manuellement (recommandé) pour vérifier le paquet WAPT et l’adapter aux besoins spécifiques de votre organisation.

    • Cliquer sur Créer et Téléverser pour lancer la création et le chargement direct du paquet sur le Serveur WAPT (non recommandé).

    Avertissement

    Le bouton Build and upload envoi directement le paquet dans le dépôt privé sans tester l’installation.

    Cette méthode fonctionne assez bien avec les MSI car leur installation est standard.

    Cependant la deuxième méthode qui consiste à tester localement le paquet d’abord puis à l’uploader est la méthode recommandée.

Note

Si vous préférez utiliser la ligne de commande, vous pouvez utiliser cette méthode.

1.2.2. Personnaliser le paquet avant de le téléverser dans votre dépôt

La méthode conseillée avant l”upload d’un paquet est de personnaliser son comportement en l’éditant avec PyScripter.

Lors de la création du modèle de paquet, cliquez sur Editer manuellement.

Boîte de dialogue mettant en évidence le bouton « Edit manuall » lors de la création du paquet WAPT dans la console WAPT

« Modifier manuellement » dans la boîte de dialogue

Fenêtre de message indiquant dans la Console WAPT que le packaging WAPT a été téléchargé dans le dépôt WAPT.

Fenêtre de message indiquant dans la Console WAPT que le packaging WAPT a été téléchargé dans le dépôt WAPT

Message windows for information

L’IDE PyScripter se lance et permet d’éditer les fichiers du paquet.

PyScripter - Personnalisation du paquet avec PyScripter

PyScripter - Personnalisation du paquet avec PyScripter

1.2.3. Présentation de PyScripter

1.2.3.1. L’explorateur de projets PyScripter

C’est la vue initiale de l’explorateur Pyscripter lorsque vous ouvrez un paquet WAPT.

PyScripter - Navigation d'un projet dans l'explorateur de fichiers de PyScrypter

PyScripter - Navigation d’un projet dans l’explorateur de fichiers de PyScrypter

L’explorateur de projets PyScripter liste les différents fichiers dont vous pouvez avoir besoin, notamment le fichier control et le fichier setup.py.

1.2.3.2. Zone d’édition

Le panneau d’édition en orange dans l’image ci-dessus.

Le panneau d’édition dans PyScripter permet d’éditer le fichier setup.py et le fichier control.

1.2.3.3. Run Configurations

Dans l’image ci-dessus, la boîte la box verte affiche les configurations préinstallées.

Les options de Run dans l’explorateur de projets de PyScripter vont vous permettre de lancer des actions de votre paquet en cours d’édition.

Ses fonctions sont expliqués dans le tableau ci-dessous.

Liste de fonctions pour la création de paquet.

Fonction

Description

install

Permet d’installer le paquet sur le système de notre machine de test.

remove

Utilisé pour désinstaller le paquet du système de la machine de test.

uninstall

Enables you to run a custom uninstall of the test machine package.

session-setup

Permet d’installer le paquet via le contexte utilisateur de la machine de test.

audit

Permet d’auditer le paquet.

update-package-source

Automatiser la mise à jour d’un paquet logiciel.

1.2.3.4. Console Python

PyScripter - console python de PyScripter

PyScripter - console python de PyScripter

C’est la console python visible dans PyScripter, elle va vous permettre d’afficher la sortie python lorsque vous exécuterez des commandes run.

Vous pouvez également l’utiliser pour tester / déboguer des portions de votre script setup.py.

Pour en savoir plus sur la composition d’un paquet WAPT, consultez la documentation sur la structure détaillée d’un paquet.

1.2.3.5. Tester localement l’installation du paquet WAPT

Vous pouvez ensuite tester le lancement d’une installation sur votre station de développement.

PyScripter - Exécuter une commande d'installation depuis la console PyScripter

La Console PyScripter vous permet de vérifier si l’installation s’est bien déroulée.

1.2.3.6. Tester localement la désinstallation du paquet WAPT

Vous pouvez ensuite tester le lancement d’une installation sur votre station de développement.

PyScripter - Exécuter une commande de désinstallation depuis la console PyScripter

La Console PyScripter vous permet de vérifier si l’installation s’est bien déroulée.

1.2.4. Explorer les fichiers du paquet depuis la Console WAPT

Pour explorer tous les fichiers d’un paquet WAPT via la Console WAPT, vous devez activer l’option Afficher les fonctionnalités de développeur. Pour ce faire :

  • Aller dans le menu Affichage de la Console WAPT.

  • Sélectionner Préférences d’affichage et cocher Afficher les fonctionnalités de développeur.

Comment explorer les fichiers du paquet ? Naviguez dans la section WAPT Packages, sélectionnez votre paquet et faites un clic droit sur Edit_package

Une fois activé, vous pouvez accéder à l’explorateur de fichiers du paquet.

Console WAPT mode développeur

Console WAPT mode développeur

1.3. Créer vos premiers paquets WAPT

1.3.1. Packager des .msi (exemple)

Pour cet exemple, nous prendrons tightvnc.

Vous pouvez le télécharger ici.

Maintenant, vous pouvez générer votre modèle de paquet, veuillez vous référer à la documentation pour la création de paquets à partir de la Console WAPT.

Editer le fichier control (architecture, impacted_process, target_os, description, maintainer …), veuillez vous référer à la structure du fichier documentation du fichier control.

Votre pyscripter s’ouvre, allez dans votre setup.py :

# -*- coding: utf-8 -*-
from setuphelpers import *

uninstallkey = []

def install():
    print('installing tis-tightvnc')
    install_msi_if_needed('tightvnc-2.8.5-setup-64bit.msi')
  • La fonction testera également si une version du logiciel est déjà installée sur la machine avec la clé de désinstallation.

  • Si présence il y a, l’installation sera enclenchée uniquement si la version actuellement installée est plus ancienne.

  • Après installation, la fonction testera finalement la présence de la clé de désinstallation et sa version pour vérifier que tout s’est bien passé.

Liste des arguments disponibles avec install_exe_if_need

Options (Option par défaut)

Description

min_version (par défaut None)

Définit la version minimale au dessus de laquelle le logiciel se mettra à jour.

killbefore (par défaut None)

Liste des programmes à tuer avant de lancer l’installation.

accept_returncodes (par défaut [0,3010])

Définit les codes de retour autres que 0 ou 3010 acceptés en retour par la fonction.

timeout (par défaut 300)

Définit la durée d’attente maximale d’installation (en secondes).

propriétés (par défaut None)

Définit les propriétés supplémentaires à passer en argument au MSI pour l’installation.

get_version (par défaut None)

Définit la valeur passée en paramètre pour le contrôle de version au lieu de celle retournée par la fonction installed_softwares.

remove_old_version (défaut False)

Supprime automatiquement une ancienne version d’un logiciel dont la clé de désinstallation est identique.

force (par défaut False)

Force l’installation du logiciel même si une clé de désinstallation avec une version identique est trouvée.

La fonction install_msi_if_needed récupère la clé de désinstallation depuis le MSI, il n’est pas nécessaire de l’écrire dans le fichier setup.py.

Vous n’avez pas non plus à remplir le champ killbefore si la valeur indiquée dans le champ impacted_process du fichier control est correcte.

Note

Le setup.py aurait pu ressembler à cela, mais la méthode est moins élégante car elle fait moins de vérifications.

# -*- coding: utf-8 -*-
from setuphelpers import *

uninstallkey = ["{8B9896FC-B4F2-44CD-8B6E-78A0B1851B59}"]

def install():
    print('installing tis-tightvnc')
    run('msiexec /norestart /q /i "tightvnc-2.8.5-setup-64bit.msi"')

Lancez l’installation et voyez ce qui se passe lorsque le logiciel est déjà installé.

wapt-get -ldebug install C:\waptdev\tis-tightvnc-wapt
Installing WAPT file C:\waptdev\tis-tightvnc-wapt
MSI tightvnc-2.8.5-gpl-setup-64bit.msi already installed. Skipping msiexec

Results:

=== install packages ===
C:\waptdev\tis-tightvnc-wapt | tis-tightvnc (2.8.5.0-1)

1.3.1.1. Ajouter des propriétés supplémentaires en argument

Pour ajouter des propriétés supplémentaires on va les stocker dans un élément dict.

# -*- coding: utf-8 -*-
from setuphelpers import *

uninstallkey = []

properties = {
    'SERVER_REGISTER_AS_SERVICE': 0,
    'SERVER_ADD_FIREWALL_EXCEPTION': 0,
    'ADDLOCAL': 'Server,Viewer'

    }

def install():
    print(u'Installation en cours de TightVNC')
    install_msi_if_needed('tightvnc-2.8.5-setup-64bit.msi', properties = properties )

Note

Le setup.py aurait pu ressembler à cela, mais la méthode est moins élégante car elle fait moins de vérifications.

# -*- coding: utf-8 -*-
from setuphelpers import *

uninstallkey = ["{8B9896FC-B4F2-44CD-8B6E-78A0B1851B59}"]

def install():
    print('installing tis-tightvnc')
    run('msiexec /norestart /q /i "tightvnc-2.8.5-setup-64bit.msi" SERVER_REGISTER_AS_SERVICE=0 SERVER_ADD_FIREWALL_EXCEPTION=0')

1.3.1.2. Vidéo de démonstration

1.3.2. Packager des .exe (exemple)

  • Télécharger l’installateur .exe à partir d’une source fiable.

    Télécharger l’installateur au format exe Firefox ESR x64 sur https://download.mozilla.org/?product=firefox-esr-latest-ssl&os=win64.

  • Rechercher la documentation associée pour les flags silencieux :

  • Puis générer votre modèle de paquet, veuillez vous référer à la documentation pour la création de paquets à partir de la Console WAPT. PyScripter se charge et ouvre le projet de paquet .exe.

    PyScripter - Ouverture du paquet WAPT de FirefoxESR

    PyScripter - Ouverture du paquet WAPT de FirefoxESR

  • Editer le fichier control (architecture, impacted_process, target_os, description, maintainer …), veuillez vous référer à la structure du fichier documentation du fichier control.

  • Vérifier le contenu du fichier control. Mozilla Firefox-ESR ne répond pas aux standards et retourne un numéro de version erroné (il s’agit du numéro de version du logiciel qui créé l’installeur).

    • Fichier control d’origine.

      package           : tis-firefox-esr
      version           : 4.42.0.0-0
      architecture      : all
      section           : base
      priority          : optional
      maintainer        : user
      description       : automatic package for firefox setup 52.6.0esr
      impacted_process  : 
      
    • Fichier control modifié.

      package           : tis-firefox-esr
      version           : 52.6.0-1
      architecture      : all
      section           : base
      priority          : optional
      maintainer        : Tranquil-IT Systems
      description       : Mozilla Firefox 52.6.0 ESR
      impacted_process  : firefox.exe
      

    Il est à noter qu’une sous-version -1 a été ajoutée au numéro de version du logiciel ; il s’agit de la version de packaging du paquet WAPT.

    Il permet au développeur de paquets de publier plusieurs versions de paquets WAPT d’un même logiciel, ce qui est très utile pour un développement très rapide et itératif.

Utiliser install_exe_if_needed

La fonction est sensiblement la même que celle utilisée pour les installeurs .msi, avec quelques différences :

  • La fonction nécessite l’ajout des flags silencieux en paramètre.

  • La fonction nécessite l’ajout de la clé de désinstallation en paramètre.

# -*- coding: utf-8 -*-
from setuphelpers import *

uninstallkey = []

def install():
    print('installing tis-firefox-esr')
    install_exe_if_needed("Firefox Setup 45.5.0esr.exe",silentflags="-ms",key='',min_version="4.42.0.0")
Liste des arguments disponibles avec install_exe_if_need

Options (Option par défaut)

Description

silentflags (par défaut None)

Paramètres silencieux à passer en argument à l’installeur.

key (par défaut None)

Clé de désinstallation du programme.

min_version (par défaut None)

Définit la version minimale au dessus de laquelle le logiciel se mettra à jour.

killbefore (par défaut None)

Liste des programmes à tuer avant de lancer l’installation.

accept_returncodes (par défaut [0,3010])

Définit les codes de retour autres que 0 ou 3010 acceptés en retour par la fonction.

timeout (par défaut 300)

Définit la durée d’attente maximale d’installation (en secondes).

get_version (par défaut None)

Définit la valeur passée en paramètre pour le contrôle de version au lieu de celle retournée par la fonction installed_softwares. Exemple https://forum.tranquil.it/viewtopic.php?t=1337.

remove_old_version (défaut False)

Supprime automatiquement une ancienne version d’un logiciel dont la clé de désinstallation est identique.

force (par défaut False)

Force l’installation du logiciel même si une clé de désinstallation avec une version identique est trouvée.

Le paquet aura alors ce comportement :

  • Le logiciel Firefox s’installera uniquement si le logiciel n’est pas installé et si la version est strictement inférieure à 45.5.0, sauf si l’option --force est indiquée lors de l’installation du paquet.

  • A l’installation, les processus firefox.exe en cours d’exécution seront tués (avec la valeur indiquée dans impacted_process du fichier control).

  • La fonction ajoutera elle-même la clé de désinstallation, donc laisser l’argument clé de désinstallation vide.

  • A la fin de l’installation, la fonction ira vérifier si la clé de désinstallation est bien présente sur le poste et si la version est bien égale ou supérieure à 45.5.0, si ce n’est pas le cas, elle basculera le paquet en ERREUR.

1.3.2.1. Trouver la clé de désinstallation

Contrairement aux fichiers .msi, la clé pour désinstaller un .exe n’est pas dans les propriétés du fichier.

Vous devez donc d’abord installer le logiciel pour connaître la clé de désinstallation.

Vous devez donc démarrer une fois l’installation à partir de pyscripter avec le run configuration et ensuite install.

PyScripter - Exécuter une commande d'installation depuis la console PyScripter

Une fois le logiciel installé, allez à la Console WAPT, puis trouvez votre machine de développement.

Dans l’onglet inventaire des logiciels, trouvez votre logiciel et copiez la valeur indiquée dans la colonne clé de désinstallation.

Récupérer une clé de désinstallation depuis la Console WAPT

Récupérer une clé de désinstallation depuis la Console WAPT

Vous devez également vérifier la valeur de la version avec la valeur indiquée dans min_version dans votre setup.py.

Modifier votre fichier setup.py avec les nouveaux paramètres :

# -*- coding: utf-8 -*-
from setuphelpers import *

uninstallkey = []

def install():
    print('installing tis-firefox-esr')
    install_exe_if_needed("Firefox Setup 45.5.0esr.exe",silentflags="-ms",key='Mozilla Firefox 45.5.0 ESR (x64 fr)',min_version="45.5.0")

Pour tester que votre clé fonctionne correctement, vous DEVEZ relancer une installation dans pyscripter.

PyScripter - Exécuter une commande d'installation depuis la console PyScripter

WAPT ne tentera pas d’installer le logiciel car il est déjà présent, le message suivant devrait donc s’afficher :

>>>
*** Remote Interpreter Reinitialized ***
Command Line : install "c:\waptdev\tis-firefox-esr_x64_PROD_fr-wapt\WAPT\.."
Using config file: C:\Program Files (x86)\wapt\wapt-get.ini
Installing WAPT files c:\waptdev\tis-firefox-esr_x64_PROD_fr-wapt
Exe setup Firefox_Setup_78.7.1esr.exe already installed. Skipping

Results:

=== install packages ===
c:\waptdev\tis-firefox-esr_x64_PROD_fr-wapt | tis-firefox-esr (78.7.1-102)

Vous pouvez maintenant tester la désinstallation :

PyScripter - Exécuter une commande de désinstallation depuis la console PyScripter

Vous pouvez maintenant construire et envoyer votre paquet, veuillez vous référer à la documentation pour construire et envoyer des paquets depuis la Console WAPT.

Note

Si vous laissez la clé de désinstallation vide, la désinstallation de votre paquet ne fonctionnera pas.

1.3.2.2. Cas particulier d’un dé-installeur non-silencieux

Dans certains cas particuliers, un paquet utilisant install_exe_if_needed remplit la clé de désinstallation, mais la clé de désinstallation pointe vers un désinstalleur non silencieux.

Il nous faut contourner le problème en utilisant une fonction qui va supprimer la clé de désinstallation à la fin de l’installation.

:emphasize-lines: 13

# -*- coding: utf-8 -*-
from setuphelpers import *

uninstallkey = []

def install():
    install_exe_if_needed("setup.exe",
                          silentflags="/s",
                          key='{D9E87643-0005-447E-9111-78697A9C1595}',
                          min_version="14.0")
    uninstallkey.remove('{D9E87643-0005-447E-9111-78697A9C1595')

def uninstall():
    run(r'"C:\Program Files\Kutl\uninstall.exe" /supersilent')

Indication

La fonction de désinstallation peut également être utilisée pour exécuter du code en plus de la désinstallation de logiciels, ex : supprimer un dossier, supprimer un raccourci …

1.3.2.3. Vidéo de démonstration

1.3.3. Packager des paquets linux simples

1.3.4. Construire le paquet et l’envoyer au Serveur WAPT

  • Une fois que le paquet est prêt, le construire et l’envoyer au Serveur WAPT, dans la Console WAPT.

Option de menu *build-upload* dans la Console WAPT
  • Sélectionner le paquet dans le dossier c:\waptdev.

Fenêtre du navigateur permettant de sélectionner le paquet WAPT à importer dans le dépôt privé

Fenêtre du navigateur permettant de sélectionner le paquet WAPT à importer dans le dépôt privé

  • Confirmer le paquet sélectionné.

Boîte de dialogue de la Console WAPT pour confirmer l'importation d'un paquet WAPT dans le dépôt privé

Boîte de dialogue de la Console WAPT pour confirmer l’importation d’un paquet WAPT dans le dépôt privé

Vous venez de charger votre premier paquet wapt.

Avertissement

Une fois que votre paquet est téléversé, rafraîchissez la liste des paquets en utilisant le bouton Actualiser les paquets disponibles ou en appuyant sur la touche F5 de votre clavier.

1.3.4.1. Travailler avec des codes de retour non standard

Les codes de retour sont utilisés pour indiquer si un logiciel a été correctement installé.

Avec Windows, le code standard de retour pour une installation réussie est [0].

Si vous savez que vos paquets WAPT s’installent correctement, mais que vous obtenez quand même un code de retour différent de [0], alors vous pouvez explicitement dire à WAPT d’ignorer le code d’erreur en utilisant le paramètre accept_returncodes.

Vous pouvez découvrir comment utiliser le paramètre accept_returncodes en explorant le code de ce paquet.

# -*- coding: utf-8 -*-
from setuphelpers import *
import re

uninstallkey = []

def is_kb_installed(hotfixid):
    installed_update = installed_windows_updates()
    if [kb for kb in installed_update if kb['HotFixID' ].upper() == hotfixid.upper()]:
        return True
    return False

def waiting_for_reboot():
    # Query WUAU from the registry
    if reg_key_exists(HKEY_LOCAL_MACHINE,r"SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired") or \
        reg_key_exists(HKEY_LOCAL_MACHINE,r"SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending") or \
        reg_key_exists(HKEY_LOCAL_MACHINE,r'SOFTWARE\Microsoft\Updates\UpdateExeVolatile'):
        return True
    return False

def install():
    kb_files = [
        'windows10.0-kb4522355-x64_af588d16a8fbb572b70c3b3bb34edee42d6a460b.msu',
        ]
    with EnsureWUAUServRunning():
      for kb_file in kb_files:
          kb_guess = re.findall(r'^.*-(KB.*)-',kb_file)
          if not kb_guess or not is_kb_installed(kb_guess[0]):
              print('Installing {}'.format(kb_file))
              run('wusa.exe "{}" /quiet /norestart'.format(kb_file),accept_returncodes=[0,3010,2359302,-2145124329],timeout=3600)
          else:
              print('{} already installed'.format(kb_file))

      if waiting_for_reboot():
          print('A reboot is needed!')

Indication

La liste complète des messages d’erreur de l’installeur Windows peut être consultée sur cette page <https://docs.microsoft.com/en-us/windows/win32/msi/windows-installer-error-messages>`_.