Imaginez que vous êtes un utilisateur d'un quelconque système d'exploitation moderne, et de surcroît un programmeur . Vous vivez une vie douce et heureuse, jusqu'au jour où...

Jusqu'au jour où l'on vous demande si le programme sur lequel vous travaillez actuellement sera porté sous Microsoft Windows. Votre première réaction est immédiate : aucun support des systèmes d'exploitation exotiques n'est prévu, mais c'est libre, donc rien ne vous empêche de le faire. La seconde, quelques temps après, est : je n'utilise que des technologies portables, python, éventuellement GTK, donc pourquoi pas ? Et c'est déjà trop tard. Vous commencez à vérifier que vous n'utilisiez aucune fonction spécifique à un système d'exploitation. Vous installez python dans une machine virtuelle sur une vieille licence de Windows 98 d'un ordinateur mort à présent (restons dans la légalité, n'est-ce pas).

Vous avez terminé votre programme python. Le setup.py, construit dans les règles de l'art, est prêt. Vous êtes en période de tests intensifs sous Microsoft Windows (après avoir perdu une partie de votre chevelure à installer les dépendances - dans le bon ordre, la bonne version, et avec le bon installeur - de votre programme), vous vous mettez à écrire du code spécifique à Microsoft Windows (alors que vous en avez supprimé pour les autres systèmes), notamment pour l'internationalisation, et enfin vous considérez votre programme comme prêt.

Mais autant vous savez que votre programme finira empaqueté (dans des dépôts officiels ou non) sur toute distribution GNU/Linux, ou qu'à défaut les utilisateurs sauront lancer python setup.py install en copiant/collant la ligne du README, autant vous savez combien un utilisateur de Microsoft Windows est peu dégourdi de ses dix doigts, ignore que le clavier est utile en dehors de msn et outlook (vous le savez parce que vous en cotoyez tous les jours, n'ayez pas honte). Il faut donc faire un machin magique, le setup.exe. C'est un fichier binaire, qui permet à l'utilisateur de Microsoft Windows de retrouver le sourire alors que vous lui parliez des fonctions de votre programme, et qu'il se demandait où pourrait-il bien trouvé le crack pour faire marcher la copie warez du logiciel (ils ont un de ces jargon, les utilisateurs de Microsoft Windows, j'vous jure !). Et ce fichier binaire, vous pourrez le réaliser grâce au setup.py dans lequel vous avez mis tant d'amour !

Mais hélas, tout ne se fait pas tout seul. Cet installateur ne placera pas automatiquement un raccourcis sur le bureau, et un autre dans le menu démarrer, condition sine qua non pour que l'utilisateur de Microsoft Windows ne vous envoie pas un mail vous répondant que votre programme il marche pas. Car non, il ne suffit pas de faire ALT+F2 Windows+R et d'entrer le nom du programme en minuscule pour qu'il se lance sous Microsoft Windows. Car s'il existe bien un PATH, il ne sert à rien. Alors comment faire ces raccourcis ? Non, ne pensez pas à placer un fichier .desktop standardisé dans un dossier application standardisé. Pensez postinstallation script.

Sauf que cette documentation gagnerait à être plus étoffée. Alors voici un exemple de script d'après-installation pour créer les raccourcis vers votre programme sur le bureau et dans le menu démarrer. Ces raccourcis seront supprimés lors de la désinstallation du programme, celle-ci devant être réalisée via l'Ajout/Suppression de programmes du panneau de configuration (le programme de désinstallation est créé automatiquement par les distutils, je ne fais pas de raccourcis dans le menu démarrer pour celui-ci, car j'ai la flemme et que c'est déconseillé pour Microsoft Windows Vista - voyez comme j'anticipe).

Dans ce qui suit, on considère que votre programme sera installé dans share/coinoin et que le fichier à lancer est share/coincoin/coincoin.py. Voici le contenu du script en lui-même, ici nommé w32_postinst.py et placé dans le même dossier que le setup.py (ce qui n'est pas obligatoire, vous adapterez) :

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# La première ligne doit commencer par #! et contenir python.
# Elle sera adaptée au système de destination automatiquement

""" This is a part of CoinCoin project.

    Post installation script for win32 system
    
    This script creat a shortcut for coincoin.py in the desktop and the
    start menu, and remove them at the uninstallation
    
"""

import os
import sys

# Ce script sera aussi lancé lors de la désinstallation.
# Pour n'exécuter du code que lors de l'installation :
if sys.argv[1] == '-install':
    # On récupère le dossier où mes fichiers seront installés (dossier où python est aussi installé sous windows)
    python_path = sys.prefix
    # On récupère le chemin de pythonw.exe (l'exécutable python qui n'affiche pas de console).
    # Si vous voulez une console, remplacez pythonw.exe par python.exe
    pyw_path = os.path.abspath(os.path.join(python_path, 'pythonw.exe'))
    # On récupère le dossier coincoin
    coincoin_dir = os.path.abspath(os.path.join(python_path, 'share', \
                                                    'coincoin'))

    # On récupère les chemins de coincoin.py, et de coincoin.ico
    # (Ben oui, l'icone est au format ico, oubliez le svg, ici on en est encore à la préhistoire.
    # Heureusement que the GIMP sait faire la conversion !)
    ico_path = os.path.join(coincoin_dir, 'coincoin.ico')
    script_path = os.path.join(coincoin_dir, 'coincoin.py')
    
    # Création des raccourcis
    # Pour chaque raccourci, on essaye de le faire pour tous les utilisateurs (Windows NT/2000/XP),
    # sinon on le fait pour l'utilisateur courant (Windows 95/98/ME)
    
    # Raccourcis du bureau
    # On essaye de trouver un bureau
    try:
        desktop_path = get_special_folder_path("CSIDL_COMMON_DESKTOPDIRECTORY")
    except OSError:
        desktop_path = get_special_folder_path("CSIDL_DESKTOPDIRECTORY")
    
    # On créé le raccourcis
    create_shortcut(pyw_path, # programme à lancer
                    "powerful coincoin duke program", # Description
                    os.path.join(desktop_path, 'coincoin.lnk'),  # fichier du raccourcis (gardez le .lnk)
                    script_path, # Argument (script python)
                    coincoin_dir, # Dossier courant
                    ico_path # Fichier de l'icone
                    )
    # On va cafter au programme de désinstallation qu'on a fait un fichier, pour qu'il soit supprimé
    # lors de la désinstallation
    file_created(os.path.join(desktop_path, 'coincoin.lnk'))
    
    # Raccourcis dans le menu démarrer (idem qu'avant)
    try:
        start_path = get_special_folder_path("CSIDL_COMMON_PROGRAMS")
    except OSError:
        start_path = get_special_folder_path("CSIDL_PROGRAMS")
    
    

    # Création du dossier dans le menu programme
    programs_path = os.path.join(start_path, "Coincoin project")
    try :
        os.mkdir(programs_path)

    except OSError:

        pass
    directory_created(programs_path)
    
    create_shortcut(pyw_path, # Cible
                    "casio data manager", #Description
                    os.path.join(programs_path, 'coincoin.lnk'),  # Fichier
                    script_path, # Argument
                    coincoin_dir, # Dossier de travail
                    ico_path # Icone
                    )
    file_created(os.path.join(programs_path, 'coincoin.lnk'))
    
    # End (youpi-message)
    # Ce message sera affiché (très) furtivement dans l'installateur.
    # Vous pouvez vous en servir comme moyen de communication secret, c'est très in.
    sys.stdout.write("Shortcuts created.
")
    # Fin du bidule
    sys.exit()

Ouf ! On y est presque ! Il ne reste plus qu'à référencer notre script en ajoutant quelque part dans le setup.py :

setup(
    ...,
    scripts=['w32_postinst.py'],
    ...)

Ensuite, il vous suffit de lancer :

python setup.py bdist_wininst --install-script w32_postinst.py

Et votre installeur est fabrique dans le dossier dist. Elle est pas belle la vie ?