web-dev-qa-db-fra.com

Extension Windows Shell avec C #

Je voulais écrire une simple extension Windows Shell à ajouter au menu contextuel, et C # est le langage que j'utilise le plus ces jours-ci. Est-ce un choix décent pour une extension Shell? Les interfaces sont-elles faciles d'accès? Y a-t-il une surcharge supplémentaire qui fait que le menu est plus lent à apparaître?

Quelqu'un a-t-il de bons conseils pour commencer?

37
Pete McKinney

Un message de Raymond: Ne pas écrire d'extensions Shell en cours de processus dans du code managé .


Un suivi récent: Maintenant que la version 4 du .NET Framework prend en charge les runtimes côte à côte en cours de processus, est-il maintenant possible d'écrire des extensions Shell en code managé?

L'essentiel est que non, ce n'est pas correct:

Le Conseils pour l'implémentation d'extensions en cours a été révisé et continue la recommandation contre l'écriture d'extensions Shell et d'extensions Internet Explorer (et d'autres types d'extensions en cours) dans du code managé, même si vous ' vous utilisez la version 4 ou supérieure.

26
GSerg

Conseils pour l'implémentation d'extensions en cours de processus

Conflits de version

Un conflit de version peut survenir via un environnement d'exécution qui ne prend pas en charge le chargement de plusieurs versions d'exécution au sein d'un même processus. Les versions du CLR antérieures à la version 4.0 entrent dans cette catégorie. Si le chargement d'une version d'un runtime empêche le chargement d'autres versions de ce même runtime, cela peut créer un conflit si l'application hôte ou une autre extension en cours utilise une version en conflit. Dans le cas d'un conflit de version avec une autre extension en cours de processus, le conflit peut être difficile à reproduire car l'échec nécessite les bonnes extensions en conflit et le mode d'échec dépend de l'ordre dans lequel les extensions en conflit sont chargées.

Considérez une extension en cours écrite à l'aide d'une version du CLR antérieure à la version 4.0. Chaque application sur l'ordinateur qui utilise une boîte de dialogue Ouvrir un fichier peut potentiellement avoir le code géré de la boîte de dialogue et sa dépendance CLR associée chargée dans le processus de l'application. L'application ou l'extension qui charge en premier une version antérieure à 4.0 du CLR dans le processus de l'application restreint les versions du CLR qui peuvent être utilisées ultérieurement par ce processus. Si une application gérée avec une boîte de dialogue Ouvrir est construite sur une version en conflit du CLR, l'extension peut ne pas s'exécuter correctement et provoquer des échecs dans l'application. À l'inverse, si l'extension est la première à se charger dans un processus et qu'une version en conflit du code géré tente de se lancer après cela (peut-être qu'une application gérée ou une application en cours d'exécution charge le CLR à la demande), l'opération échoue. Pour l'utilisateur, il semble que certaines fonctionnalités de l'application cessent de fonctionner de manière aléatoire ou que l'application plante mystérieusement.

Notez que les versions du CLR égales ou ultérieures à la version 4.0 ne sont généralement pas sensibles au problème de version car elles sont conçues pour coexister entre elles et avec la plupart des versions antérieures à 4.0 du CLR (à l'exception de la version 1.0, qui ne peut pas coexistent avec d'autres versions). Cependant, des problèmes autres que des conflits de version peuvent survenir, comme indiqué dans le reste de cette rubrique.

Problèmes de performances

Des problèmes de performances peuvent survenir avec les environnements d'exécution qui imposent une pénalité de performances significative lorsqu'ils sont chargés dans un processus. La pénalité de performances peut être sous la forme d'utilisation de la mémoire, d'utilisation du processeur, du temps écoulé ou même de la consommation d'espace d'adressage. CLR, JavaScript/ECMAScript et Java sont connus pour être des environnements d'exécution à fort impact. Étant donné que les extensions en cours peuvent être chargées dans de nombreux processus, et le sont souvent à des moments sensibles aux performances ( comme lors de la préparation d'un menu à afficher pour l'utilisateur), les temps d'exécution à fort impact peuvent avoir un impact négatif sur la réactivité globale.

Un environnement d'exécution à fort impact qui consomme des ressources importantes peut provoquer une défaillance du processus hôte ou d'une autre extension en cours. Par exemple, un environnement d'exécution à fort impact qui consomme des centaines de mégaoctets d'espace d'adressage pour son tas peut empêcher l'application hôte de charger un ensemble de données volumineux. De plus, étant donné que les extensions en cours peuvent être chargées dans plusieurs processus, une consommation élevée de ressources dans une seule extension peut rapidement se multiplier en une consommation élevée de ressources sur l'ensemble du système.

Si un runtime reste chargé ou continue de consommer des ressources même lorsque l'extension qui utilise ce runtime a été déchargée, alors ce runtime n'est pas adapté à une utilisation dans une extension.

Problèmes spécifiques au .NET Framework

Les sections suivantes présentent des exemples de problèmes rencontrés lors de l'utilisation du code managé pour les extensions. Ils ne constituent pas une liste complète de tous les problèmes possibles que vous pourriez rencontrer. Les problèmes abordés ici sont à la fois les raisons pour lesquelles le code managé n'est pas pris en charge dans les extensions et les points à prendre en compte lorsque vous évaluez l'utilisation d'autres environnements d'exécution.

  • Réintégration
    Lorsque le CLR bloque un thread STA (single-threaded apartment), par exemple, en raison d'une instruction Monitor.Enter, WaitHandle.WaitOne ou de verrouillage contesté, le CLR, dans sa configuration standard, entre un message imbriqué boucle pendant qu'il attend. Il est interdit à de nombreuses méthodes d'extension de traiter les messages et cette réentrance imprévisible et inattendue peut entraîner un comportement anormal difficile à reproduire et à diagnostiquer.

  • Le cloisonnement multithread Le CLR crée des wrappers appelables à l'exécution pour les objets COM (Component Object Model). Ces mêmes wrappers appelables Runtime sont détruits plus tard par le finaliseur du CLR, qui fait partie de l'appartement multithread (MTA). Le déplacement du proxy du STA vers le MTA nécessite le marshaling, mais toutes les interfaces utilisées par les extensions ne peuvent pas être rassemblées.

  • Durée de vie des objets non déterministes
    Le CLR a des garanties de durée de vie des objets plus faibles que le code natif. De nombreuses extensions ont des exigences de comptage de références sur les objets et les interfaces, et le modèle de récupération de place utilisé par le CLR ne peut pas répondre à ces exigences.

    • Si un objet CLR obtient une référence à un objet COM, la référence d'objet COM détenue par le Runtime Callable Wrapper n'est pas libérée tant que le Runtime Callable Wrapper n'est pas récupéré. Un comportement de libération non déterministe peut entrer en conflit avec certains contrats d'interface. Par exemple, la méthode IPersistPropertyBag :: Load nécessite qu'aucune référence au sac de propriétés ne soit conservée par l'objet lorsque la méthode Load est renvoyée.
    • Si une référence d'objet CLR est retournée au code natif, le Runtime Callable Wrapper abandonne sa référence à l'objet CLR lorsque le dernier appel du Runtime Callable Wrapper à Release est effectué, mais l'objet CLR sous-jacent n'est pas finalisé tant qu'il n'est pas récupéré. La finalisation non déterministe peut entrer en conflit avec certains contrats d'interface. Par exemple, les gestionnaires de vignettes doivent libérer toutes les ressources immédiatement lorsque leur nombre de références tombe à zéro.

Utilisations acceptables du code managé et autres exécutions

Il est acceptable d'utiliser du code managé et d'autres environnements d'exécution pour implémenter des extensions hors processus. Les exemples d'extensions Shell hors processus sont les suivants:

  • Aperçu des gestionnaires
  • Actions basées sur la ligne de commande telles que celles enregistrées sous les sous-clés Shell\verb\command.
  • Objets COM implémentés dans un serveur local, pour les points d'extension Shell qui permettent une activation hors processus.

Certaines extensions peuvent être implémentées en tant qu'extensions en cours ou hors processus. Vous pouvez implémenter ces extensions en tant qu'extensions hors processus si elles ne remplissent pas ces conditions pour les extensions en cours. La liste suivante montre des exemples d'extensions qui peuvent être implémentées en tant qu'extensions en cours ou hors processus:

  • IExecuteCommand associé à une entrée DelegateExecute enregistrée sous une sous-clé Shell\verb\command.
  • IDropTarget associé au CLSID enregistré sous une sous-clé Shell\verb\DropTarget.
  • IExplorerCommandState associé à une entrée CommandStateHandler enregistrée sous une sous-clé Shell\verb.

SharpShell

SharpShell facilite la création d'extensions Windows Shell à l'aide du .NET Framework.

Le code source est hébergé sur https://github.com/dwmkerr/sharpshell - vous pouvez poster des questions et des demandes de fonctionnalités ici ou là. Extensions prises en charge

Vous pouvez utiliser SharpShell pour créer l'une des extensions ci-dessous:

  • Menus contextuels du shell
  • Gestionnaires d'icônes
  • Gestionnaires de conseils d'information
  • Gestionnaires de goutte
  • Gestionnaires d'aperçu
  • Gestionnaires de superposition d'icônes
  • Thumbnail Hanlders
  • Extensions de feuille de propriétés

Projets utilisant SharpShell
1. Menu contextuel Trello
2. REAL Shuffle Player 2.

Série d'articles sur CodeProject

14
Ehsan Mohammadi