Guía para implementar extensiones de In-Process
Las extensiones en proceso se cargan en cualquier proceso que las desencadene. Por ejemplo, una extensión de espacio de nombres de Shell se puede cargar en cualquier proceso que tenga acceso al espacio de nombres shell directa o indirectamente. Muchas operaciones de Shell usan el espacio de nombres shell, como la presentación de un cuadro de diálogo de archivo común, el inicio de un documento a través de su aplicación asociada o la obtención del icono usado para representar un archivo. Dado que las extensiones en proceso se pueden cargar en procesos arbitrarios, debe tener cuidado de que no afecten negativamente a la aplicación host ni a otras extensiones en proceso.
Un entorno de ejecución concreto es Common Language Runtime (CLR), también conocido como código administrado o .NET Framework. Microsoft recomienda escribir extensiones administradas en proceso en el Explorador de Windows o Windows Internet Explorer y no las considera un escenario admitido.
En este tema se describen los factores que se deben tener en cuenta al determinar si cualquier entorno de ejecución distinto del CLR es adecuado para su uso por parte de las extensiones en proceso. Algunos ejemplos de otros entornos de ejecución son Java, Visual Basic, JavaScript/ECMAScript, Delphi y la biblioteca en tiempo de ejecución de C/C++. En este tema también se proporcionan algunas razones por las que el código administrado no se admite en las extensiones en proceso.
Conflictos de versiones
Un conflicto de versiones puede surgir a través de un entorno de ejecución que no admite la carga de varias versiones en tiempo de ejecución dentro de un único proceso. Las versiones de CLR anteriores a la versión 4.0 se dividen en esta categoría. Si la carga de una versión de un entorno de ejecución impide la carga de otras versiones de ese mismo tiempo de ejecución, esto puede crear un conflicto si la aplicación host u otra extensión en proceso usa una versión en conflicto. En el caso de un conflicto de versión con otra extensión en proceso, el conflicto puede ser difícil de reproducir porque el error requiere las extensiones en conflicto adecuadas y el modo de error depende del orden en el que se cargan las extensiones en conflicto.
Considere una extensión en proceso escrita con una versión de CLR anterior a la versión 4.0. Cada aplicación del equipo que usa un cuadro de diálogo Abrir archivo podría tener el código administrado del diálogo y su dependencia CLR operador cargada en el proceso de la aplicación. La aplicación o extensión que primero se va a cargar una versión anterior a la 4.0 de CLR en el proceso de la aplicación restringe las versiones de CLR que puede usar posteriormente ese proceso. Si una aplicación administrada con un cuadro de diálogo Abrir se basa en una versión en conflicto de CLR, la extensión podría no ejecutarse correctamente y podría provocar errores en la aplicación. Por el contrario, si la extensión es la primera que se carga en un proceso y una versión en conflicto del código administrado intenta iniciarse después de eso (quizás una aplicación administrada o una aplicación en ejecución carga clR a petición), se produce un error en la operación. Para el usuario, parece que algunas características de la aplicación dejan de funcionar aleatoriamente o que la aplicación se bloquea misteriosamente.
Tenga en cuenta que las versiones de CLR iguales o posteriores a la versión 4.0 no suelen ser susceptibles al problema de control de versiones porque están diseñadas para coexistir entre sí y con la mayoría de las versiones anteriores a 4.0 de CLR (con la excepción de la versión 1.0, que no puede coexistir con otras versiones). Sin embargo, pueden surgir problemas distintos de los conflictos de versión, como se describe en el resto de este tema.
Problemas de rendimiento
Los problemas de rendimiento pueden surgir con tiempos de ejecución que imponen una penalización de rendimiento significativa cuando se cargan en un proceso. La penalización del rendimiento puede estar en forma de uso de memoria, uso de CPU, tiempo transcurrido o incluso consumo de espacio de direcciones. ClR, JavaScript/ECMAScript y Java son entornos de ejecución de alto impacto. Dado que las extensiones en proceso se pueden cargar en muchos procesos y a menudo se realizan en momentos sensibles al rendimiento (por ejemplo, al preparar un menú para mostrar al usuario), los entornos de ejecución de alto impacto pueden afectar negativamente a la capacidad de respuesta general.
Un tiempo de ejecución de alto impacto que consume recursos significativos puede provocar un error en el proceso de host u otra extensión en proceso. Por ejemplo, un tiempo de ejecución de alto impacto que consume cientos de megabytes de espacio de direcciones para su montón puede dar lugar a que la aplicación host no pueda cargar un conjunto de datos grande. Además, dado que las extensiones en proceso se pueden cargar en varios procesos, un consumo elevado de recursos en una sola extensión puede multiplicarse rápidamente en un consumo elevado de recursos en todo el sistema.
Si un tiempo de ejecución permanece cargado o sigue consumiendo recursos incluso cuando la extensión que usa ese tiempo de ejecución se ha descargado, ese tiempo de ejecución no es adecuado para su uso en una extensión.
Problemas específicos de .NET Framework
En las secciones siguientes se describen ejemplos de problemas encontrados con el uso de código administrado para extensiones. No son una lista completa de todos los posibles problemas que puede encontrar. Los problemas que se describen aquí son ambos motivos por los que el código administrado no se admite en extensiones y puntos que se deben tener en cuenta al evaluar el uso de otros entornos de ejecución.
Volver a entrar
Cuando CLR bloquea un subproceso de un solo subproceso (STA), por ejemplo, debido a una instrucción Monitor.Enter, WaitHandle.WaitOne o a una instrucción de bloqueo contendida, CLR, en su configuración estándar, entra en un bucle de mensajes anidado mientras espera. Muchos métodos de extensión están prohibidos para procesar mensajes, y esta reentrada impredecible e inesperada puede dar lugar a un comportamiento anómalo que es difícil de reproducir y diagnosticar.
El apartamento multiproceso
CLR crea contenedores invocables en tiempo de ejecución para objetos de modelo de objetos componentes (COM). Estos mismos contenedores invocables en tiempo de ejecución se destruyen más adelante por el finalizador de CLR, que forma parte del apartamento multiproceso (MTA). Mover el proxy de STA a MTA requiere serialización, pero no todas las interfaces usadas por las extensiones se pueden serializar.
Duraciones de objetos no deterministas
CLR tiene garantías de duración de objetos más débiles que el código nativo. Muchas extensiones tienen requisitos de recuento de referencias en objetos e interfaces, y el modelo de recolección de elementos no utilizados empleado por CLR no puede cumplir estos requisitos.
- Si un objeto CLR obtiene una referencia a un objeto COM, la referencia de objeto COM mantenida por el contenedor invocable en tiempo de ejecución no se libera hasta que se recopile el contenedor invocable en tiempo de ejecución. El comportamiento de versión no determinista puede entrar en conflicto con algunos contratos de interfaz. Por ejemplo, el método IPersistPropertyBag::Load requiere que el objeto no conserve ninguna referencia al contenedor de propiedades cuando devuelve el método Load .
- Si se devuelve una referencia de objeto CLR al código nativo, el contenedor invocable en tiempo de ejecución renuncia a su referencia al objeto CLR cuando se realiza la llamada final del contenedor en tiempo de ejecución a Release , pero el objeto CLR subyacente no se finaliza hasta que se recopilan elementos no utilizados. La finalización no determinista puede entrar en conflicto con algunos contratos de interfaz. Por ejemplo, los controladores de miniaturas son necesarios para liberar todos los recursos inmediatamente cuando su recuento de referencias cae a cero.
Usos aceptables del código administrado y otros entornos de ejecución
Es aceptable usar código administrado y otros entornos de ejecución para implementar extensiones fuera de proceso. Entre los ejemplos de extensiones de Shell fuera de proceso se incluyen los siguientes:
- Controladores de vista previa
- Acciones basadas en la línea de comandos, como las registradas en subclaves decomandos deverbo\ de shell\.
- Objetos COM implementados en un servidor local, para puntos de extensión de Shell que permiten la activación fuera del proceso.
Algunas extensiones se pueden implementar como extensiones en proceso o fuera de proceso. Puede implementar estas extensiones como extensiones fuera de proceso si no cumplen estos requisitos para las extensiones en proceso. En la lista siguiente se muestran ejemplos de extensiones que se pueden implementar como extensiones en proceso o fuera de proceso:
- IExecuteCommand asociado a una entrada DelegateExecute registrada en una subclave delcomandode verbo\ de shell\.
- IDropTarget asociado al CLSID registrado en una subclaveDropTarget delverbo\ de shell\.
- IExplorerCommandState asociado a una entrada CommandStateHandler registrada en una subclavede verbo de shell\.