ShellExecute fait partie des innombrables fonctions de l'API Windows ; cela
veut dire qu'elle est utilisée par tous les programmes pour dialoguer
avec le système d'exploitation.
ShellExecute est déclarée dans une unité,
ShellAPI, qui n'est pas utilisée par défaut par les
projets de Delphi, il faut donc, dans chaque unité où
l'on veut appeler ShellExecute, ajouter ShellAPI dans les uses.
Cela permet de comprendre directement les multiples fonctionnalités
de cette fonction : elle peut exécuter un programme ou ouvrir un fichier
(Filename), en lui passant des paramètres (Parameters), en spécifiant
le mode d'affichage (ShowCmd).
Ensuite, il y a les types : HWND qui signifie que la fonction attend un Handle
(identificateur unique d'un contrôle fenêtré) et PChar, ce
type est peut être apparenté à une chaîne normale
(String), à la différence qu'elle est reconnue, contrairement
à String, par l'API Windows.
Pour remplir le paramètre Handle, il y a plusieurs possibilités,
soit l'appel de ShellExecute est dans procédure quelconque:
Dans ce cas, il faut préciser de quel Handle de fiche on
spécifie, c'est pourquoi on ajoute NomdeFiche avant Handle.
Soit l'appel est dans une méthode d'une fiche :
En effet, le seul intérêt de spécifier un Handle,
est que si l'exécution provoque un message d'erreur, la fenêtre
dont le Handle est spécifié, sera le parent de la
boite de dialogue d'erreur.
Au passage, il est maintenant déconseillé d'utiliser la fonction
WinExec, car obsolète, elle est maintenue pour des raisons de compatibilité
ascendante avec les versions 16 bits de Windows.
En conclusion, cette fonction est la plus adaptée, lorsqu'il s'agit
d'ouvrir, d'exécuter un programme, même s'il s'agit ici qu'une
partie de ses fonctionnalités...
Il faut comprendre que l'on demande d'ouvrir (paramètre "Open")
la calculette de Windows (paramètre "C:\Windows\Calc.exe")
et de l'afficher normalement, c'est à dire pas maximisée ou minimisée,
mais comme si l'on ouvrait le fichier dans l'explorateur (paramètre SW_SHOWDEFAULT).
ShellExecute n'utilise pas les String de Delphi, mais les PChar.
Si l'on spécifie une chaîne de caractère dans
l'éditeur de code, la conversion sera automatique. Dans le
cas contraire, il faudra explicitement effectuer le transtypage
(conversion d'un type vers un autre).
Mais, dans ce cas, le compilateur va générer une
erreur : "Types incompatibles : String et PChar". En effet,
par défaut dans Delphi, une chaîne est un string, et
un string n'est pas accepté par ShellExecute, qui demande
des PChar.
En effet, PChar étant un pointeur sur le premier caractère
d'une chaîne AZT (A Zéro Terminal), on peut spécifier
un paramètre vide, grâce à un "pointeur
sur rien", avec Nil
Dans ce tutorial, l'utilisation de Nil est préférée
car plus lisible, mais sinon l'utilisation est laissée libre
au programmeur.
En conclusion, lancer un programme avec cette fonction est simple et rapide.
Ce qui fait la puissance de ShellExecute par rapport à d'autre fonctions
de l'API comme WinExec, c'est le support de l'ouverture de fichiers et des alias
grâces aux variables d'environnement.
En effet, cette fonction peut non seulement exécuter des programmes
ou des batchs DOS, mais aussi ouvrir des fichiers avec leur programme associé
:
Ce code ouvrira le document spécifié dans l'OpenDialog, avec
son programme associé. Par exemple, si le fichier est un .PAS, le code
ouvrira Delphi avec le fichier ouvert ; si le fichier est un .TXT, le code ouvrira
le Bloc-Note avec le fichier ouvert... Cela permet donc d'ouvrir n'importe quel
fichier, sans se soucier quel programme il faut lancer, afin de l'ouvrir.
Ensuite, cette fonction gère, comme Démarrer \ Exécuter,
les alias. En effet, si vous tapez "notepad" dans Exécuter,
le Bloc-Note s'ouvrira, bien que Notepad.exe ne se situe pas dans la racine
du disque. Il en est de même avec ShellExecute ; cela fonctionne grâce
en partie aux variables d'environnement DOS, dans AutoExec ou Boot dans Win2K,
il y a toujours une ligne du type :
SET PATH=C:\WINDOWS;C:\WINDOWS\SYSTEM...
Cela veut dire que Windows, s'il n'y a pas de chemin spécifié,
devra chercher les exécutables dans ces dossiers. Partant de là,
ces lignes sont correctes :
ShellExecute a pour l'instant été appelé avec comme paramètre
Operation, la chaine "Open". Mais il en existe une infinité
d'autres, bien que seulement quelques unes (dont "Open") sont indépendantes
du sytème.
Operation permet ainsi de spécifier l'opération à réaliser
sur le fichier spécifié par FileName, le plus souvent c'est "Open"
qui est utilisé, mais il y en existe d'autres :
Open
Si le fichier est executable, il est executé. Sinon l'application
associée est lancée
Print
Imprime le fichier
Find
Ouvre la boite de dialogue de recherche dans le dossier spécifié
Edit
Ouvre le fichier avec l'éditeur associé
Explore
Ouvre l'explorateur sur le dossier spécifié
Properties
Ouvre la boite de dialogue des Propriétés du raccourci
Cependant, toutes les opérations ne marchent pas sur tous les fichiers
:
Open
Print
Find
Edit
Explore
Properties
Dossier
Ouvre le dossier
Aucun effet
Ouvre le boite de dialogue de recherche dans le dossier
Aucun effet
Ouvre l'explorateur dans le dossier
Aucun effet
Exécutable
Lance l'exécutable
Aucun effet
Aucun effet
Aucun effet
Aucun effet
Aucun effet
Fichier
Ouvre le fichier avec le programme associé
Imprime le fichier avec le programme associé
Aucun effet
Edite le fichier avec le programme associé
Aucun effet
Aucun effet
Raccourci
Lance la cible du raccourci
Aucun effet
Aucun effet
Aucun effet
Aucun effet
Ouvre la boite de dialogue "Propriétés du raccourci"
Raccourci internet
Lance la cible du raccourci
Aucun effet
Aucun effet
Aucun effet
Aucun effet
Aucun effet
Ressource internet
Lance la ressource internet
Aucun effet
Aucun effet
Aucun effet
Aucun effet
Aucun effet
Pour précision, on pourrait se demander la différence entre Open
et Edit, c'est vrai que dans la plupart des cas, il n'y en a pas, mais dans
le cas des .HTM par exemple, Open ouvre le navigateur, alors que Edit ouvre
l'éditeur HMTL. La différence n'est visible que lorsqu'un fichier
est ouvert et édité par deux programmes différents (c'est
le cas aussi des .BAT).
ShellExecute(Handle,'Open','C:\MaPage.htm',nil,nil,SW_SHOWDEFAULT);
//Ouvre le document HMTL dans le navigateur
ShellExecute(Handle,'Edit','C:\MaPage.htm',nil,nil,SW_SHOWDEFAULT);
//Ouvre le document HMTL dans l'éditeur
HMTL
ShellExecute(Handle,'Print','C:\MaPage.htm',nil,nil,SW_SHOWDEFAULT);
//Imprime le document HMTL
La spécialité du paramètre Operation est d'être
une chaine, alors que la plupart des paramètres qui semblent limités
de l'API sont des entiers. Or les différents paramètres de Operation
sont illimités et extrémement variables d'une machine à
une autre : on peut définir plusieurs constantes d'entiers pour une spécificité
d'un OS, mais dans le cas d'Operation, chaque programme a le droit de d'ajouter
ses paramètres, d'où la chaine qui est presque illimitée.
Chaque programme peut rajouter ses paramètres, pour la simple et bonne
raison que les différents paramètres sont stockés dans
la base de registres, mais comme nom de clé, et pas comme valeur, d'où
l'utilisation de chaine. Ces paramètres sont de surplus spécifiques
à chaque extension, car stockés dans HKEY_CLASSES_ROOT\Extension\Shell\Operation
ou HKEY_CLASSES_ROOT\CLSID\{CLSID_Objet}\Shell\Operation. Ces paramètres
sont utilisés par ShellExecute, mais aussi, et surtout, par Explorer,
pour créer le menu contextuel avec Ouvrir, Imprimer...
Il est donc possible d'ajouter sans trop de difficultés des nouvelles
opérations, cela étant précisé en annexe.
Partant de là, on pourra créer une extension qui aura un nouveau
paramètre Operation, et que l'on pourra appeller avec ShellExecute :
//Un paramètre Operation
"Compile" a été ajouté à l'extension
.DPR
Le dernier paramètre de ShellExecute permet tout simplement de spécifier
comment sera la fenêtre de l'application ouverte, il y en a deux principaux
et opposés :
SW_SHOW
Affiche la fenêtre normalement (pas minimisée, maximisée...)
SW_HIDE
Cache la fenêtre
Donc, ShellExecute permet de lancer une application complement cachée,
sans être visible dans la barre de tâches :
ShellExecute(Handle,'Open','Notepad',nil,nil,SW_SHOW);
//Ouvre Bloc-Note, et l'affiche
ShellExecute(Handle,'Open','Notepad',nil,nil,SW_HIDE);
//Ouvre Bloc-Note et le cache
Mais, il y a aussi d'autres paramètres, pour maximiser, minimiser :
SW_SHOWDEFAULT
Equivalent à SW_SHOW
SW_MAXIMIZE
Affiche la fenêtre maximisée
SW_MINIMIZE
Affiche la fenêtre minimisée et la sélectionne
SW_SHOWMINNOACTIVE
Affiche la fenêtre minimisée et redonne le focus à
le fenêtre active précedente
SW_SHOWNA
Affiche la fenêtre comme SW_SHOW, mais ne l'active pas
ShellExecute peut evidemment passer des paramètres à un executable
ou batch, il suffit de remplir le paramètre Parameters :
ShellExecute(Handle,'Open','mplayer2','C:\MaVideo.avi
- fullscreen',nil,SW_SHOWDEFAULT); //Ouvre
Media Player Classic en mode plein écran, grâce au paramètre
"-fullsreen"
ShellExecute(Handle,'Open','C:\Sierra\Half-Life\hl.exe','-console',nil,SW_SHOWDEFAULT);
//Lance Half-Life en mode console, grâce
au paramètre "-console"
La spécificité de ShellExecute est de séparer
le nom de fichier de ses paramètres, il ne faut donc pas
écrire :
Il faut faire attention lors de la spécification de paramètres
qui sont des noms de fichier. En effet, si le chemin ou le nom comporte
des espaces, le programme n'interprétera pas le nom du fichier
comme un nom de fichier, mais comme plusieurs paramètres,
ce qui sera une source de non fonctionnement. Il faut donc utiliser
des guillemets, ce qui obligera le programme à n'interpréter
qu'un seul paramètre :
Un programme s'execute toujours par rapport à un dossier, par défaut,
c'est le dossier où il se trouve, mais ce dossier peut-être modifié.
Ce dossier peut par exemple être modifié par un raccourci : grâce
au champ "Démarrer dans : ". Le dossier d'execution sert à
déterminer le chemin complet, lors de la spécification d'un seul
nom de fichier sans chemin :
AssignFile(T,'MonFichier.txt');
Dans cet exemple, Windows détermine le chemin complet de ce fichier
par rapport au dossier d'execution, qui est le dossier où se situe le
programme si aucun autre a été spécifié.
Ce passage de chemin relatif à chemin absolu pose alors
un problème. Il ne faut jamais spécifier un dossier
d'execution sans raison, car si le programmes cherche des DLL, fichiers,
par rapport à son dossier d'execution, et que ce dossier
est erroné, le bon fonctionnement ne sera plus assuré
(même s'il peut aussi forcer le répertoire avec ChDir).
Bien qu'il y a peu de cas, où il faudra utiliser le dossier d'execution,
il est facile de l'utiliser avec ShellExecute, il suffit de le spécifier
:
ShellExecute(Handle,'Open','C:\UnProg.exe',nil,'C:\DataUnProg',SW_SHOW);
//Ouvre UnProg et spécifie un dossier
d'execution
Ce qui a pour équivalent dans un raccourci à :
Cible : "C:\Unprog.exe"
Démarrer en : "C:\DataUnProg"
Et en DOS, à :
rem C: est le lecteur courant
C:
rem C:\DataUnProg est le répertoire courant
cd C:\DataUnProg
rem Lancement de C:\UnProg, sans changer le répertoire
courant
ShellExecute est une fonction, qui renvoit le résultat : si le résultat
renvoyé est plus petit ou égal à 32, une erreur s'est produite,
et l'opération ne sera pas executée.
ShellExecute ne renvoit plus d'instance d'application. Le type
renvoyé, est maintenu pour des raisons de compatibilité
ascendante avec les systèmes Windows 16 bit. Il ne faut plus
utiliser le handle renvoyé pour des opérations avec
l'API, seul les codes d'erreurs sont encore utilisables.
Les principaux différents codes d'erreur sont les suivants :
0
Plus de mémoire disponible
ERROR_FILE_NOT_FOUND
Le fichier est introuvable
ERROR_PATH_NOT_FOUND
Le dossier est introuvable
ERROR_BAD_FORMAT
Le fichier n'est pas un executable correct (pas une application Win32
valide)
SE_ERR_ACCESSDENIED
Acces refusé
SE_ERR_OOM
Plus assez de mémoire pour finir l'opération
SE_ERR_SHARE
Violation de partage
SE_ERR_NOASSOC
Le fichier spécifié n'a pas d'executable associé
L'executable associé ne peux pas imprimer le fichier spécifié
Il existe encore d'autres codes d'erreur, comme ceux associés avec les
liaisons DDE (Dynamic Data Exchange).
if ShellExecute(Handle,'Open','Delphi32',nil,nil,SW_SHOWDEFAULT)
<= 32 then
ShowMessage('Erreur lors
de l'exécution de Delphi');
On peut facilement ajouter une opération à une extension de fichier
:
Par exemple, lorsque l'on a un éditeur d'image simple et que l'on ouvre
un gif animé, celui-ci ne l'anime pas. Il faudrait l'ouvrir avec le navigateur.
C'est pourquoi, on va ajouter une opération "Anime" dans l'extension
Gif afin de pouvoir ouvrir un gif animé.
1. Ouvrir HKEY_CLASSES_ROOT\.gif
2. Si celle
ci contient une clé "Shell", aller à l'étape
4.
3. Repérer
le type de fichier comme spécifié dans HKEY_CLASSES_ROOT\.gif\(Defaut)
3. Ensuite,
chercher ce nom dans les sous-clés de HKEY_CLASSES_ROOT
4. Maintenant,
soit il y a une clé "Shell" dans HKEY_CLASSES_ROOT\.gif
soit dans HKEY_CLASSES_ROOT\(FichierGif)
5. Ajouter
une clé nommé "Anime" et une sous-clé de
celle-ci nommé "command"
6. Modifier
la valeur par défaut, par "Lecteur:\Dossier\...\Dossier\IExplore.exe
%1" (le plus souvent "C:\Program Files\Internet Explorer\IExplore.exe"
A la différence de ShellExecute, la base de registre n'accepte
pas les chemins de fichiers imcomplets, il faut obligatoirement
spécifier le nom de fichier absolu.