El estado actual de la integración con el shell de Windows — el menú contextual, la asociación de archivos y los cambios de Windows 11

· Actualizado el: · · Windows, Extensiones de shell, Menú contextual, Asociación de archivos, COM, Windows 11, Explorador de archivos, MSIX, Desarrollo para Windows

En una consulta nos contaron: «Al cambiar a un PC con Windows 11, el menú contextual de la aplicación que ustedes nos hicieron hace tiempo dejó de aparecer». Al preguntar más a fondo, resultó que no había desaparecido. Al hacer clic derecho sobre un archivo y elegir «Mostrar más opciones», al final del menú, aparecía el menú de siempre tal cual. Es decir, el elemento del menú de su aplicación había quedado escondido un paso más adentro. Desde el propio negocio nos llegaron comentarios como «ahora hace falta un clic más» y «han aumentado las consultas de la gente que no encuentra la opción».

Esto no es una avería ni un error de configuración, sino un cambio de diseño de Windows 11. El menú contextual del Explorador pasó a tener una estructura dual, nueva y antigua, y las condiciones para que un elemento aparezca en el nuevo menú son completamente distintas de las de antes.

Por otro lado, el mecanismo subyacente de la asociación de archivos y las extensiones de shell sigue siendo, hoy en día, el mismo mundo de COM y del registro de Windows de siempre. La clave de extensión señala a un ProgID, el verb del ProgID tiene una línea de comandos, y las extensiones más elaboradas funcionan como servidores COM en proceso (DLL) que se cargan en el Explorador: esta estructura no ha cambiado en más de 20 años. Sin conocer a la vez la base que no ha cambiado y el menú que se duplicó en Windows 11, no es posible diagnosticar si «el menú no aparece», «se ha escondido» o «aparece duplicado».

Este artículo, dirigido a responsables de sistemas de pequeñas y medianas empresas y a desarrolladores de Windows que mantienen aplicaciones de negocio, conecta en un solo hilo la estructura de tres niveles de la asociación de archivos, los puntos de atención de las extensiones de shell tradicionales, cómo adaptarse al nuevo menú contextual de Windows 11, y el registro, la limpieza y la resolución de problemas desde el instalador.

1. Conclusión principal

  • La base del menú contextual y de la asociación de archivos es la estructura de tres niveles del registro «clave de extensión → ProgID → verb». La clave de extensión es un puntero que señala al ProgID, el ProgID es la entidad, y el shell\<verb>\command que cuelga de él tiene la línea de comandos.1
  • HKEY_CLASSES_ROOT (HKCR) no es una hive independiente, sino una vista combinada de HKLM\Software\Classes y HKCU\Software\Classes. El registro pensado para todos los usuarios se escribe en HKLM, el de un usuario concreto en HKCU, y HKCR se debe tratar como algo solo de lectura.2
  • La aplicación predeterminada (la que se abre con doble clic) está diseñada para que la elija el usuario, y no se le puede arrebatar desde un programa. La elección del usuario está protegida por el sistema operativo, y lo único que puede hacer el instalador es registrarse como candidato.3
  • Una extensión de shell tradicional es una DLL que actúa como servidor COM en proceso cargado en el Explorador. Un bloqueo o una lentitud de la extensión se propaga a todo el Explorador (y a cualquier otra aplicación que use el shell); en entornos de 64 bits se requiere una DLL de 64 bits, y la implementación en código administrado no tiene soporte.45
  • En Windows 11 el menú contextual se duplicó. En el nuevo menú solo aparecen los comandos registrados con IExplorerCommand más identidad de paquete; las extensiones IContextMenu tradicionales quedan relegadas al menú antiguo que se abre con «Mostrar más opciones» (Shift+F10).67
  • La ruta oficial para mostrar un comando propio en el nuevo menú es registrar una DLL nativa que implemente IExplorerCommand mediante el manifiesto de un paquete MSIX (desktop4:FileExplorerContextMenus). Las aplicaciones que no pueden convertirse a MSIX pueden obtener solo la identidad con un sparse package (MSIX con ubicación externa).78
  • Si solo se quiere que «esta aplicación abra el archivo», la asociación y un verb estático siguen siendo suficientes hoy en día. No hace falta ninguna DLL de extensión de shell, y la propia Microsoft recomienda «elegir el método más simple que cumpla el requisito (un verb estático)».9
  • Tras registrar o modificar una asociación hay que notificarlo con SHChangeNotify (SHCNE_ASSOCCHANGED), y la guía oficial indica que al desinstalar se elimine el ProgID pero no el valor predeterminado de la clave de extensión. Diseñar bien esa limpieza también forma parte de la integración con el shell.110

En resumen: el mundo de la asociación y de los verbs no ha cambiado, solo la forma de mostrar el menú se ha duplicado en Windows 11. A continuación lo revisamos desde la base.

2. Cómo funciona la asociación de archivos — la estructura de tres niveles clave de extensión→ProgID→verb

2.1. Leer la estructura de tres niveles con un ejemplo

Qué ocurre al hacer doble clic en un archivo de determinada extensión depende de tres niveles de claves del registro.1

HKEY_CLASSES_ROOT
   .kmrpt                                  ← (1) Clave de extensión
      (Default) = KomuraSoft.Report.1      ←     Puntero que solo señala al ProgID
      OpenWithProgids
         KomuraSoft.Report.1               ←     Candidato para "Abrir con"
   KomuraSoft.Report.1                     ← (2) ProgID (la entidad de la asociación)
      (Default) = Documento de informe KomuraSoft
      DefaultIcon
         (Default) = "C:\Program Files\KomuraSoft\Report.exe",0
      shell                                ← (3) Lista de verbs (verbos)
         open
            command
               (Default) = "C:\Program Files\KomuraSoft\Report.exe" "%1"
  • (1) La clave de extensión (.kmrpt) se limita, con su valor predeterminado, a señalar el nombre del ProgID. Escribir un comando directamente aquí es un error.
  • (2) El ProgID (KomuraSoft.Report.1) es la entidad de la asociación y tiene el nombre visible, el icono y la lista de verbs.
  • (3) El verb es un verbo como «abrir» o «imprimir», y el valor predeterminado de shell\open\command es la línea de comandos que realmente se ejecuta.

Gracias a esta separación se pueden apuntar varias extensiones (por ejemplo .kmrpt y .kmrpt-file) al mismo ProgID, o sustituir el ProgID al actualizar la versión de la aplicación.

Estructura de tres niveles de la asociación de archivosLa clave de extensión es solo un puntero que señala al ProgID mediante su valor predeterminado, el ProgID es la entidad que tiene el nombre visible, el icono y la lista de verbs, y el valor predeterminado del command bajo el verb es la línea de comandos que realmente se ejecutaSeñala al ProgID por su valor predeterminadoClave de extensión .kmrptProgID KomuraSoft.Report.1Verb(open, bajo shell)Valor predeterminado de commandSe ejecuta Report.exeTambién tiene nombre visible y DefaultIcon

Figura 1: la clave de extensión es un puntero, el ProgID es la entidad, y el command del verb es la línea de comandos que realmente se ejecuta.

2.2. HKCR es una «vista combinada» — el significado depende de dónde se escribe

El ejemplo anterior se mostró en HKEY_CLASSES_ROOT (HKCR), pero HKCR no es un lugar de almacenamiento físico, sino una vista combinada que superpone HKLM\Software\Classes y HKCU\Software\Classes. Si la misma clave existe en ambos, gana el lado de HKCU.2

HKCR es una vista combinadaHKCR es la superposición de las claves Classes de HKLM y HKCU, si la misma clave existe en ambas gana el lado de HKCU, y la escritura del registro debe indicar explícitamente HKLM o HKCU dejando HKCR solo para lecturaHKLM\Software\Classes(todos los usuarios)HKCR(vista combinada)HKCU\Software\Classes(por usuario)Si la clave coincide, gana HKCUSe trata solo como lectura(verificación)

Figura 2: HKCR es la manera en que se ven combinadas las claves Classes de HKLM y HKCU; el destino de escritura debe indicarse siempre explícitamente.

Destino de escritura Significado Permisos necesarios
HKLM\Software\Classes Registro común para todos los usuarios Permisos de administrador
HKCU\Software\Classes Registro exclusivo de ese usuario No se necesitan
Escribir directamente en HKCR Se redirige según dónde exista ya la clave Depende del caso

En la práctica, lo más seguro es escribir siempre el registro indicando explícitamente HKLM o HKCU, y tratar HKCR solo como algo de lectura (verificación). Conviene además tener claro cómo se relaciona esto con la redirección del registro de WOW64. Los datos de asociación bajo HKLM\Software\Classes directamente, como las claves de extensión o los ProgID, se comparten entre las vistas de registro de 32 y 64 bits desde Windows 7 en adelante, así que aunque un instalador de 32 bits los escriba, no se desvían hacia Wow6432Node. En cambio, algunas subclaves del registro de COM, como Classes\CLSID, sí son objeto de redirección, y en el registro de extensiones de shell (COM en proceso) que veremos más adelante, la distinción entre 32 y 64 bits sí influye. Este tema se trata con detalle en «La redirección de 32/64 bits del registro y las trampas de la virtualización».

2.3. Registro del lado de la aplicación — App Paths, Applications y RegisteredApplications

Además del lado de los archivos (extensión y ProgID), también existen tres tipos de registro del lado de la aplicación.11

  • App Paths (HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths): permite iniciar la aplicación desde ShellExecuteEx solo con el nombre del ejecutable. Como no ensucia la variable de entorno PATH, es lo que recomienda Microsoft.
  • Applications (HKCR\Applications\<app.exe>): define la forma predeterminada de abrir un archivo arbitrario cuando se pasa a través de «Abrir con», y el nombre visible de la aplicación (FriendlyAppName).
  • RegisteredApplications + Capabilities: declara qué extensiones y tipos MIME puede manejar la aplicación, y es el registro necesario para figurar como candidato en la pantalla de configuración de aplicaciones predeterminadas de Windows.

La mayoría de las consultas del tipo «nuestra aplicación no aparece en la lista de aplicaciones predeterminadas» se deben a que se registró el ProgID pero se omitió este registro de Capabilities.

Los tres tipos de registro del lado de la aplicaciónEl registro del lado de la aplicación tiene tres tipos, App Paths, Applications y RegisteredApplications, que cumplen respectivamente el papel de iniciar solo con el nombre del ejecutable, definir la forma predeterminada de abrir con Abrir con y aparecer en la pantalla de configuración de aplicaciones predeterminadasRegistro del lado de la aplicaciónApp PathsApplicationsRegisteredApplicationsSe inicia solo con el nombre del archivoForma predeterminada de Abrir conAparece en la pantalla de apps predeterminadasRequiere declaración en Capabilities

Figura 3: hay tres tipos de registro del lado de la aplicación, y para aparecer como candidato en la pantalla de aplicaciones predeterminadas se necesita el registro de Capabilities.

2.4. La aplicación predeterminada pertenece al usuario — la protección de UserChoice

Escribir un ProgID en el valor predeterminado de la clave de extensión no basta por sí solo para convertirse en la aplicación predeterminada. El resultado que el usuario elige explícitamente, por ejemplo con «Abrir con», se guarda en HKCU\...\Explorer\FileExts\<extensión>\UserChoice, y ese es el que prevalece al resolver la asociación.

Y lo importante es que Windows no admite que la aplicación predeterminada se cambie mediante programación. El cambio de aplicación predeterminada está diseñado para hacerse a través de la interfaz de configuración del sistema, los datos de UserChoice están ofuscados, y un controlador de filtro (UCPD.sys) bloquea que las aplicaciones escriban en ellos. En entornos administrados, la directiva de grupo o la directiva MDM son el medio oficial.3

El hecho de que en el pasado se usaran herramientas como SetUserFTA, que «imitan el hash y lo reescriben», es el reflejo inverso de esta protección. Lo que un instalador de una aplicación propia debe incorporar no es arrebatar el valor predeterminado, sino tres cosas: (a) registrar correctamente el ProgID y el verb, (b) añadirse a OpenWithProgIds, y (c) dirigir al usuario, si hace falta, hacia la pantalla de configuración.

Resolución de la aplicación predeterminada y protección de UserChoiceEl resultado que el usuario elige explícitamente se guarda en UserChoice y tiene prioridad en la resolución de la asociación, la reescritura desde una aplicación es bloqueada por UCPD.sys, por lo que el instalador solo puede registrarse como candidato y dirigir al usuario a la pantalla de configuraciónPrioridadBloqueada por UCPD.sysUserChoice(elección del usuario)Resolución de la asociaciónValor predeterminado de la clave de extensiónReescritura desde una aplicaciónTarea del instaladorRegistrar ProgID y verbAñadir a OpenWithProgIdsDirigir a la pantalla de configuración

Figura 4: en la resolución de la asociación tiene prioridad la elección del usuario (UserChoice), y el sistema operativo protege contra la reescritura desde una aplicación.

3. Verbs más allá de «abrir» — print, edit, runas y verbs personalizados

Un verb no es solo open. Entre los verbs estándar que el sistema operativo entiende están, además de open, edit, print, play, preview, y a los verbs estándar se les asigna automáticamente un nombre visible según el idioma del sistema operativo. El verb predeterminado que se usa al hacer doble clic se decide en este orden: el valor predeterminado de la clave shell, el primer verb del registro, open y por último openwith.12

Orden de determinación del verb predeterminadoEl verb predeterminado que se usa al hacer doble clic se decide por el primero que se encuentre en este orden: el valor predeterminado de la clave shell, el primer verb del registro, open y openwithSi no existeSi no existeSi no existeValor predeterminado de la clave shellPrimer verb del registroopenopenwith

Figura 5: el verb predeterminado al hacer doble clic es el primero que se encuentre en este orden.

Para añadir un verbo propio se registra un verb personalizado.

KomuraSoft.Report.1
   shell
      open
         command
            (Default) = "C:\Program Files\KomuraSoft\Report.exe" "%1"
      print
         command
            (Default) = "C:\Program Files\KomuraSoft\Report.exe" /print "%1"
      verify                          ← Verb personalizado
         (Default) = Verificar informe (&V)   ← Nombre mostrado en el menú
         command
            (Default) = "C:\Program Files\KomuraSoft\Report.exe" /verify "%1"

Van tres pequeños detalles útiles de saber.

  • Registrar un verb llamado runas permite definir un inicio elevado equivalente a «Ejecutar como administrador», y también se usa cuando se especifica runas desde las API de la familia ShellExecute.
  • Si en la clave del verb se coloca un valor vacío llamado Extended, se convierte en un verb extendido que solo se muestra al hacer clic derecho con la tecla Shift pulsada. Es útil para ocultar operaciones peligrosas que se usan rara vez.12
  • En asociaciones de aplicaciones antiguas a veces persiste una configuración con DDE (la clave ddeexec) que envía el documento a un proceso ya existente, pero iniciar un verb mediante DDE ya es un legado desaprobado (Deprecated). No hay motivo para escribirlo de nuevo.12

Otro origen frecuente de errores son las comillas en la línea de comandos. Si algún elemento de la cadena de comandos puede contener espacios, hay que encerrarlo entre comillas. Además de la ruta del EXE, del tipo C:\Program Files\..., %1 (la ruta del archivo seleccionado) siempre debe escribirse como "%1", porque no se puede garantizar que la ruta del archivo del usuario no contenga espacios. Un My Program.exe sin comillas se interpreta como «ejecutar My con el argumento Program.exe».13

El accidente de las comillas en la línea de comandosUn command sin comillas se divide por los espacios y se malinterpreta como el inicio de My con el argumento Program.exe, por lo que la ruta del EXE que puede contener espacios y %1, que representa la ruta del archivo seleccionado, deben ir siempre entre comillasSe divide por espacioscommand sin comillasSe malinterpreta como otro EXEcommand con comillasSe ejecuta como se pretendeEncerrar la ruta del EXE entre comillasEncerrar también %1 siempre entre comillas

Figura 6: un comando sin comillas se divide erróneamente por los espacios, así que la ruta del EXE y %1 deben ir siempre entre comillas.

Todo lo visto hasta aquí, basado únicamente en el registro (verb estático), se puede lograr sin escribir una sola DLL, y no conlleva el riesgo de desestabilizar el Explorador. La propia Microsoft repite que, antes de escribir una extensión de shell, hay que considerar si basta con el verb estático más simple que cumpla el requisito.9

4. Extensiones de shell tradicionales — DLL que se ejecutan dentro del Explorador

4.1. Tipos de extensiones de shell

Para requisitos que un verb estático no puede cubrir, como «cambiar el menú dinámicamente según lo seleccionado» o «sustituir el icono o la pantalla de propiedades», se usan controladores de extensión de shell. Los tipos representativos son los siguientes.4

Controlador Interfaces principales Qué permite hacer
Controlador de menú contextual IContextMenu + IShellExtInit Añadir y controlar dinámicamente elementos del menú
Controlador de icono / superposición de icono IExtractIcon / IShellIconOverlayIdentifier Icono por archivo y superposiciones
Controlador de hoja de propiedades IShellPropSheetExt Añadir pestañas a la pantalla de propiedades
Miniatura / información emergente IThumbnailProvider / IQueryInfo Vista en miniatura y descripción al pasar el cursor
Controlador de arrastrar y soltar / de copia IDropTarget / ICopyHook Intervenir al soltar o al copiar/mover

Todos ellos se implementan como clases COM y se registra su CLSID en el registro. Para el concepto de COM en sí, consulte «Qué es COM / ActiveX / OCX».

4.2. Qué implica ser un servidor COM en proceso

La esencia de una extensión de shell tradicional es que es un servidor COM en proceso (DLL) que se carga dentro del proceso del Explorador (o de cualquier aplicación que abra un cuadro de diálogo de archivos común). De aquí se derivan todos los puntos de atención.4

  • Si la extensión se bloquea, el Explorador se bloquea con ella. Si se cuelga, el clic derecho se queda congelado varios segundos. Y el daño no se limita al Explorador: alcanza a cualquier aplicación que muestre un diálogo de abrir archivo.
  • La construcción del menú se hace en el hilo de la interfaz de usuario, así que no deben realizarse operaciones lentas, como acceso a red o E/S de archivos, al mostrar el menú.
  • La regla es registrar el modelo de subprocesamiento como Apartment.
Estructura de arrastre de las extensiones en procesoLa DLL de la extensión de shell se carga no solo en el Explorador sino también en el proceso de cualquier aplicación que abra un cuadro de diálogo de archivos, por lo que un bloqueo o cuelgue de la extensión se propaga a todo el proceso anfitriónSe carga en el procesoSe carga en el procesoDLL de la extensión de shellExploradorCualquier app que abre un diálogoSe propagan bloqueos o cuelguesNo hacer procesos lentos al mostrar

Figura 7: la DLL de la extensión corre dentro del proceso anfitrión, por lo que un bloqueo o cuelgue se propaga a todo el anfitrión.

Al investigar consultas del tipo «el Explorador se congela al abrir cierta carpeta» o «el clic derecho tarda cinco segundos», no es raro descubrir que la causa no era una aplicación propia, sino una extensión de shell de terceros. El método de diagnóstico se trata en el capítulo 8.

4.3. Coincidencia de arquitectura — en un entorno de 64 bits se requiere una DLL de 64 bits

Una DLL en proceso debe coincidir en arquitectura con el proceso que la carga. Como el Explorador de un Windows de 64 bits es un proceso de 64 bits, una DLL de extensión de shell compilada solo para 32 bits sencillamente no se carga y no aparece en el menú en absoluto. Como no se produce ningún error, es una causa habitual de «lo registré pero no aparece». La combinación de un cuerpo de aplicación de 32 bits con una DLL de extensión de shell de 64 bits es una configuración válida, pero hay que tener en cuenta que el registro COM se divide según la arquitectura (Wow6432Node). El EXE que se inicia desde el command de un verb, por ser un proceso distinto, no está sujeto a esta restricción (puede seguir siendo de 32 bits sin problema).

Coincidencia de arquitectura de la DLL de extensión de shellEl Explorador de 64 bits solo puede cargar una DLL de extensión de shell de 64 bits, una DLL de solo 32 bits no aparece en el menú sin ningún error, y el EXE que se inicia desde el command de un verb no tiene esta restricción porque corre en otro procesoPuede cargarNo puede cargarOtro procesoExplorador de 64 bitsDLL de extensión de shell de 64 bitsDLL de solo 32 bitsNo aparece en el menú, sin errorEXE iniciado por un verbPuede seguir siendo de 32 bits

Figura 8: al Explorador de 64 bits solo puede cargarse una DLL de 64 bits, y el EXE iniciado por un verb no está sujeto a esta restricción.

4.4. Por qué no se debe escribir en código administrado

Es frecuente que nos pregunten «¿se puede escribir una extensión de shell en C#?», pero Microsoft afirma explícitamente que escribir extensiones de shell en proceso en código administrado (.NET) no es recomendable y no tiene soporte oficial.5

La razón está en que la extensión se carga en un proceso arbitrario. Existen factores estructurales que pueden desestabilizar la aplicación anfitriona: conflictos de versión del CLR (especialmente por debajo de .NET Framework 4), la reentrada del CLR en el bucle de mensajes durante una espera de bloqueo, y el choque entre el ciclo de vida no determinista de los objetos por la recolección de basura y el contrato de recuento de referencias de COM. Algunos de estos puntos se han aliviado desde .NET Framework 4 en adelante y con el .NET moderno, pero la postura oficial no ha cambiado.

La pauta práctica es sencilla. Las extensiones en proceso se escriben en C++ nativo. Si se quiere usar código administrado, hay que hacerlo como un EXE normal iniciado por el command de un verb, o como una extensión fuera de proceso que corre en otro proceso (como un controlador de vista previa).5

Criterio para decidir si usar código administradoLa regla es escribir en C++ nativo las extensiones en proceso que se ejecutan dentro del proceso del Explorador, y si se quiere usar código administrado, conviene un EXE normal iniciado por el command de un verb o una extensión fuera de proceso que corre en otro procesoNo¿Se ejecuta dentro del proceso?Escribir en C++ nativoCódigo administrado también sirveConflictos de CLR o reentrada inestabilizan el anfitriónEXE normal iniciado por un verbExtensión fuera de proceso(como una vista previa)

Figura 9: la regla es escribir las extensiones en proceso en C++ nativo, y el código administrado se limita a configuraciones que corren en otro proceso.

5. El nuevo menú contextual de Windows 11 — la duplicación del menú

5.1. Qué ha cambiado

Windows 11 renovó el menú contextual del Explorador. Cortar, copiar, etc. pasaron a ser una fila de iconos en la parte superior; «Abrir» y «Abrir con» se agrupan y se colocan también en la parte superior; y los comandos que añaden las aplicaciones se agrupan debajo de los comandos estándar del shell. Cuando una misma aplicación añade varios comandos, se agrupan en un flyout (submenú) con el nombre de la aplicación.6

Y aquí está el punto clave: las extensiones de shell tradicionales basadas en IContextMenu no se eliminaron, sino que quedaron relegadas al menú antiguo, el mismo de Windows 10, que se abre con «Mostrar más opciones» (Shift+F10).6 Esta duplicación es la verdadera identidad del «el menú se ha escondido» de la consulta inicial.

El menú contextual duplicado en Windows 11Al hacer clic con el botón derecho, primero se abre el nuevo menú, en el que solo aparecen los comandos registrados con IExplorerCommand e identidad de paquete, mientras que las extensiones IContextMenu tradicionales quedan relegadas al menú antiguo que se abre con Mostrar más opcionesMostrar más opciones, Shift+F10Clic derecho en un archivoNuevo menú(Windows 11)Comandos con IExplorerCommand+identidadMenú antiguo(el menú de Windows 10)Extensión IContextMenu tradicionalVarios comandos se agrupan en un flyout

Figura 10: en el nuevo menú solo aparecen los comandos con IExplorerCommand+identidad, y las extensiones tradicionales quedan relegadas al menú antiguo.

5.2. La ruta oficial para aparecer en el nuevo menú — IExplorerCommand+registro en el manifiesto

Solo hay una forma de sacar un comando propio en el nuevo menú: preparar una DLL nativa que implemente la interfaz IExplorerCommand, y declarar el servidor COM y la extensión de menú contextual en el manifiesto del paquete MSIX.7

<!-- Manifiesto del paquete (extracto) -->
<com:Extension Category="windows.comServer">
  <com:ComServer>
    <com:SurrogateServer DisplayName="Komura commands">
      <com:Class Id="01234567-89AB-CDEF-0123-456789ABCDEF"
                 Path="KomuraCommand.dll" ThreadingModel="STA" />
    </com:SurrogateServer>
  </com:ComServer>
</com:Extension>
<desktop4:Extension Category="windows.fileExplorerContextMenus">
  <desktop4:FileExplorerContextMenus>
    <desktop5:ItemType Type=".kmrpt">
      <desktop5:Verb Id="VerifyReport"
                     Clsid="01234567-89AB-CDEF-0123-456789ABCDEF" />
    </desktop5:ItemType>
  </desktop4:FileExplorerContextMenus>
</desktop4:Extension>

En Type de ItemType se puede indicar, además de una extensión concreta, * (todos los archivos), Directory (carpetas) o Directory\Background (el fondo de una carpeta). La DLL debe coincidir con la arquitectura del Explorador (64 bits/ARM64).7

IExplorerCommand es una interfaz que existe desde la época de Windows 7, e implementa el título (GetTitle), el icono (GetIcon), el estado habilitado/deshabilitado/oculto (GetState) y la ejecución (Invoke). Como los métodos se llaman desde el hilo de la interfaz de usuario, está prohibido acceder a recursos de red, y los métodos de construcción del menú deben devolver el control con rapidez. El procesamiento pesado se realiza después de Invoke.147

Estructura del manifiesto para registrar el nuevo menúLa declaración del servidor COM en el manifiesto MSIX asocia el CLSID con la DLL, y la declaración de la extensión del menú contextual vincula el objetivo y la implementación mediante ItemType y Verb, de modo que el comando propio se muestra en el nuevo menúAsocia CLSID con la DLLEspecifica ItemType y VerbManifiesto MSIXDeclaración del servidor COMDeclaración de la extensión del menúDLL que implementa IExplorerCommandComando visible en el nuevo menúEl objetivo puede ser una extensión, todos los archivos, etc.

Figura 11: las dos declaraciones del manifiesto vinculan la DLL de implementación con el objetivo, y así el comando aparece en el nuevo menú.

5.3. La opción para aplicaciones sin empaquetar — obtener solo la identidad con un sparse package

Para el caso de «nuestra aplicación solo se puede distribuir con un MSI, no es posible convertirla a MSIX», la vía de escape es el sparse package (MSIX con ubicación externa). Se firma y se crea un MSIX pequeño que solo contiene el manifiesto, sin el cuerpo de la aplicación, y se registra al final del instalador existente. Con esto la aplicación obtiene identidad de paquete, y pasa a ser posible el registro del manifiesto mencionado arriba (es decir, la aparición en el nuevo menú). Está disponible desde Windows 10 versión 2004 en adelante, y el paquete necesita estar firmado con un certificado de confianza en el equipo de destino.8

Flujo para obtener identidad con un sparse packageTras colocar el cuerpo de la aplicación con el instalador existente, registrar un sparse package que solo contiene el manifiesto con una ubicación externa hace que la aplicación obtenga identidad de paquete y así sea posible el registro del manifiesto en el nuevo menúInstalador existenteColoca el cuerpo de la appsparse packageSolo manifiesto, sin cuerpoSe registra con ubicación externaObtiene identidad de paqueteYa es posible registrarse en el nuevo menúRequiere una firma de confianza

Figura 12: al registrar con ubicación externa un sparse package que no incluye el cuerpo, la aplicación obtiene identidad de paquete.

La mayor ventaja es que no hace falta sustituir el instalador, lo que lo convierte en una solución realista para aplicaciones que ya cuentan con instaladores MSI/EXE existentes. Para comparar con una migración completa a MSIX, consulte también «Cómo elegir el método de distribución de aplicaciones de Windows».

5.4. Cómo se ven los verbs de asociación en el nuevo menú

Un punto fácil de malinterpretar es que la asociación (ProgID y verb) de los capítulos 2 y 3 sigue vigente incluso en el nuevo menú. El verb predeterminado del doble clic, «Abrir», y los candidatos de «Abrir con» se resuelven a partir de la asociación y se muestran en la parte superior del nuevo menú. Es decir, si solo se quiere «que esta aplicación pueda abrirlo», en Windows 11 tampoco hace falta ninguna adaptación adicional. Por otro lado, la asociación no es una extensión de menú de propósito general, así que si se quiere sacar un comando personalizado arbitrario en el primer nivel del nuevo menú, hace falta IExplorerCommand más identidad; ese es el reparto de funciones.7

Reparto de funciones entre la asociación y el nuevo menúLa asociación de ProgID y verb también se usa en el nuevo menú para resolver el verb predeterminado del doble clic y Abrir y Abrir con, mostrándose en la parte superior, mientras que mostrar un comando personalizado arbitrario en el primer nivel del nuevo menú requiere IExplorerCommand e identidadAsociación(ProgID y verb)Resolución del verb predeterminado y AbrirSe muestra en la parte superior del nuevo menúNo requiere trabajo adicional ni en Windows 11Comando personalizado arbitrarioIExplorerCommand+identidadSe muestra en el primer nivel del nuevo menú

Figura 13: la asociación sigue encargándose de la resolución de «Abrir» también en el nuevo menú, y solo un comando personalizado requiere IExplorerCommand+identidad.

6. Tabla de decisión práctica — cuál de las tres opciones elegir

Resumimos todo lo anterior en tres opciones prácticas.

Lo que se quiere lograr Método recomendado Cómo se ve en Windows 11 Trabajo y coste necesarios
(a) Iniciar la aplicación propia con doble clic o «Abrir» Asociación + verb estático (solo registro en el registro de Windows) Se integra en «Abrir»/«Abrir con» del nuevo menú Solo el registro de claves desde el instalador. No hace falta DLL ni requisitos adicionales de firma
(b) Sacar un comando propio para archivos o carpetas seleccionados en el nuevo menú Implementar IExplorerCommand + registro en el manifiesto MSIX. Las aplicaciones sin empaquetar obtienen identidad con un sparse package Primer nivel del nuevo menú (varios comandos se agrupan en un flyout con el nombre de la aplicación) DLL nativa en C++ + identidad de paquete + firma de código
(c) Seguir usando una extensión IContextMenu tradicional existente Mantenerla tal cual por ahora (no elegirla para desarrollo nuevo) Solo en el menú antiguo de «Mostrar más opciones» (Shift+F10) Mantener la compilación de 64 bits y el registro COM. Planificar a futuro la migración a (b)

Hay dos puntos clave para decidir. Primero, no recurrir a (b) o (c) para un requisito que (a) ya cubre: escribir una extensión de shell implica asumir, desde ese momento, una responsabilidad sobre la estabilidad del Explorador. Segundo, (c) solo significa que «no está roto», pero como experiencia de usuario sigue quedando en una posición inferior. Cuanto más se use un comando en el día a día, mayor será el retorno de la inversión en migrar a (b).

Cómo elegir entre las tres opcionesSi solo se quiere iniciar con doble clic o Abrir, basta con la asociación y un verb estático, si se quiere sacar un comando propio en el nuevo menú se necesita IExplorerCommand y el registro en el manifiesto MSIX, si no se puede convertir a MSIX se otorga identidad con un sparse package, y una extensión IContextMenu tradicional existente se mantiene por ahora en el menú antiguoNoNoNo¿Basta con abrir?Asociación+verb estático¿Comando propio en el nuevo menú?¿Se puede convertir a MSIX?IExplorerCommand+MSIXIdentidad con sparse packageMantener lo tradicional por ahoraSolo se muestra en el menú antiguoSin DLL, riesgo bajo

Figura 14: según el requisito, se elige entre el verb estático, IExplorerCommand+identidad, o mantener lo tradicional.

7. La práctica del despliegue y el registro — instalador, sparse package y limpieza

7.1. ¿HKLM o HKCU?

Hay que hacerlo coincidir con la forma del instalador. Si es para todos los usuarios (se coloca en Program Files, con permisos de administrador), corresponde a HKLM\Software\Classes; si es una instalación por usuario (sin elevación de permisos), corresponde a HKCU\Software\Classes. Mezclarlos genera consultas del tipo «a la usuaria A se le abre, pero al usuario B no». En las extensiones de shell que implican registro de CLSID, existe también la opción de Reg-Free COM, que evita por completo el registro en el registro de Windows y que es válida para el uso de COM dentro de la propia aplicación, pero no puede aplicarse a las extensiones de shell que carga el Explorador, por lo que ahí sí es necesario el registro convencional (véase «Qué es Reg-Free COM»).

7.2. Notificar tras cada cambio — SHChangeNotify

Cada vez que se registre, modifique o elimine una asociación, hay que notificarlo con el evento SHCNE_ASSOCCHANGED mediante SHChangeNotify. Omitir esto puede provocar que el cambio no lo reconozca el Explorador hasta el próximo reinicio.110

// Llamar una vez, por ejemplo desde una acción personalizada del instalador, después de cambiar la asociación
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr);

7.3. Registro y anulación del sparse package

Registrar y anular el sparse package es tarea del instalador. El registro se hace después de colocar los archivos, y la anulación antes de borrarlos.8

# Durante la instalación: tras colocar los archivos, registrar la carpeta de instalación como ubicación externa
Add-AppxPackage -Path "C:\Program Files\KomuraSoft\KomuraReport.identity.msix" `
                -ExternalLocation "C:\Program Files\KomuraSoft"

# Durante la desinstalación: anular el registro del paquete antes de borrar los archivos
Remove-AppxPackage <nombre completo del paquete>

Un punto de atención: Add-AppxPackage se registra para el usuario que lo ejecuta. Si se invoca desde una acción personalizada de un MSI por máquina, ejecutarlo como LocalSystem no otorga la identidad al usuario que hizo la instalación, así que hay que ejecutarlo con suplantación (impersonate) del usuario. Aun así, la identidad registrada mediante la suplantación solo corresponde al usuario que realizó esa instalación. En un entorno donde varios usuarios comparten un mismo PC, los demás usuarios, o los que se crean después, no tienen identidad de paquete y no verán el comando en el nuevo menú. Para que funcione con todos los usuarios, hay que preparar un mecanismo que, en el primer inicio de la aplicación, compruebe si el registro del paquete del propio usuario existe y lo registre si falta (registro por usuario), e incluir también en la desinstalación la anulación del registro de cada usuario que lo tenga registrado. Además, la aplicación del registro del manifiesto puede requerir reiniciar el Explorador (o cerrar sesión).7

Orden de registro y anulación del sparse packageDurante la instalación se registra el sparse package después de colocar los archivos, durante la desinstalación se anula el registro antes de borrar los archivos, pero hay que tener en cuenta que el registro solo es válido para el usuario que lo ejecutóInstalaciónColoca los archivosRegistra el sparse packageDesinstalaciónAnula el registro del paqueteBorra los archivosEl registro solo es válido para el usuario que lo ejecutó

Figura 15: el registro se hace después de colocar los archivos, la anulación antes de borrarlos, y hay que tener en cuenta que el registro es por usuario ejecutante.

7.4. Limpieza al desinstalar — qué eliminar y qué conservar

La guía oficial tiene un criterio claro sobre la limpieza al desinstalar.1

  • Qué eliminar: el conjunto de claves ProgID propias, el registro de Capabilities/RegisteredApplications, el registro de CLSID de las extensiones de shell, y el sparse package (con Remove-AppxPackage).
  • Qué conservar: el valor predeterminado de la clave de extensión (.kmrpt). La recomendación oficial es no eliminarlo aunque siga apuntando al ProgID propio. Es difícil determinar, tras la instalación, si otra aplicación ha tomado el valor predeterminado, y como Windows simplemente ignora el ProgID predeterminado si no está registrado, dejarlo así no causa ningún daño real.
  • Al final de la limpieza también se llama a SHChangeNotify (SHCNE_ASSOCCHANGED).

Muchos de los problemas del tipo «desinstalé la aplicación pero queda un residuo en el menú» se deben a huecos en este diseño de la limpieza.

Diseño de la limpieza al desinstalarAl desinstalar se eliminan la clave ProgID propia, el registro de CLSID y el sparse package, se conserva el valor predeterminado de la clave de extensión porque un ProgID no registrado simplemente se ignora, y al final de la limpieza se notifica el cambio con SHChangeNotifyDesinstalaciónQué eliminarQué conservarRegistro de ProgID o CLSIDsparse packageValor predeterminado de la clave de extensiónUn ProgID no registrado se ignoraNotificar al final con SHChangeNotify

Figura 16: se elimina el registro propio, se conserva el valor predeterminado de la clave de extensión, y al final de la limpieza se notifica el cambio.

8. Solución de problemas — no aparece, aparece duplicado, va lento

8.1. El menú no aparece

Se diagnostica en este orden.

  1. Qué menú se está viendo: el registro del método antiguo solo aparece en el menú antiguo de Shift+F10. Primero hay que comprobar ambos.
  2. Arquitectura: una DLL de extensión de shell compilada solo para 32 bits no se carga en un Explorador de 64 bits (apartado 4.3).
  3. Destino de registro: confusión entre HKLM/HKCU o entre las vistas de Wow6432Node. Se comprueba la clave real con reg query.
  4. Registro del paquete: si es para el nuevo menú, se comprueba con Get-AppxPackage si el registro existe, si el certificado de firma es de confianza, y la ruta de -ExternalLocation, y se reinicia el Explorador.7
  5. Falta de notificación: si se olvidó SHChangeNotify, se puede confirmar viendo si se refleja al reiniciar el Explorador.
Orden de diagnóstico cuando el menú no apareceSe empieza confirmando si se está viendo el menú nuevo o el antiguo, y luego se sigue en orden con la arquitectura de la DLL, el destino del registro, el registro del paquete y la firma, y por último la falta de notificación de SHChangeNotifyConfirmar si es el menú nuevo o el antiguoConfirmar la arquitectura de la DLLConfirmar el destino de registro en HKLM y HKCUConfirmar el registro del paquete y la firmaDeterminar la falta de notificación reiniciando

Figura 17: cuando «no aparece», se diagnostica en orden: qué menú se ve, la arquitectura, el destino de registro, el registro del paquete y la falta de notificación.

8.2. Aparece duplicado o no desaparece

Las causas típicas son la coexistencia del registro tradicional en el registro de Windows con el registro en el manifiesto, huecos en la limpieza al desinstalar (apartado 7.4), y restos de un ProgID de una versión anterior. Si la duplicación aparece solo en el menú antiguo, se sospecha del tipo de restos; si aparece en ambos menús, del tipo de coexistencia.

Diagnóstico de la aparición duplicadaSi aparece duplicado solo en el menú antiguo se sospecha de restos por limpieza incompleta o de un ProgID antiguo, y si aparece duplicado en ambos menús se sospecha de la coexistencia del registro antiguo en el registro y del registro en el manifiestoSolo en el menú antiguoEn ambos menús¿Dónde aparece duplicado?Caso de restosCaso de coexistenciaLimpieza incompleta o restos de un ProgID antiguoCoexistencia del registro antiguo y el nuevo

Figura 18: si la duplicación aparece solo en el menú antiguo se sospecha del tipo de restos, y si aparece en ambos menús, del tipo de coexistencia.

8.3. El Explorador va lento o se bloquea

Cuando el clic derecho es lento o el Explorador se bloquea en cierta carpeta, lo primero es hacer inventario de las extensiones de shell instaladas. Con una herramienta como ShellExView de NirSoft se listan las extensiones que no son de Microsoft, y deshabilitando temporalmente las sospechosas con una búsqueda binaria se puede identificar la DLL causante. En caso de bloqueo, el «módulo con errores» del Visor de eventos también sirve de pista. Si la causa resulta ser una extensión propia, conviene sospechar de E/S síncrona o acceso de red en la ruta de construcción del menú (apartados 4.2 y 5.2).

Identificación de la DLL causante cuando va lento o se bloqueaSe listan las extensiones de shell que no son de Microsoft con ShellExView, se identifica la DLL causante mediante búsqueda binaria deshabilitando temporalmente las sospechosas, y en caso de bloqueo el módulo con errores del Visor de eventos también sirve de pistaInventario de extensiones de shellListar las que no son de MicrosoftBúsqueda binaria deshabilitando temporalmenteIdentificar la DLL causanteEn caso de bloqueoRevisar el módulo con errores

Figura 19: se deshabilitan temporalmente las extensiones que no son de Microsoft mediante búsqueda binaria, y en caso de bloqueo se usa también el Visor de eventos.

8.4. Windows Sandbox resulta útil para la verificación

Verificar la integración con el shell consiste, básicamente, en confirmar el ciclo «instalar en un entorno limpio → funcionamiento → desinstalar → cero residuos». Aquí resulta muy útil Windows Sandbox (Pro/Enterprise/Education), que arranca en pocos segundos un Windows desechable completamente limpio cada vez, lo que permite repetir cuantas veces haga falta las pruebas de registro y limpieza del instalador. Como al cerrarlo se elimina todo, también es útil para investigar residuos en el registro.15

9. Resumen

  • La asociación de archivos tiene la estructura de tres niveles «clave de extensión → ProgID → verb», y HKCR es la vista combinada de las Classes de HKLM y HKCU. El destino de escritura debe indicarse explícitamente, y %1 siempre debe ir entre comillas.
  • La aplicación predeterminada está diseñada para que la elija el usuario, y no se puede cambiar desde un programa. La tarea del instalador llega hasta registrarse correctamente como candidato.
  • Una extensión de shell tradicional es una DLL que actúa como servidor COM en proceso cargado en el Explorador. Un bloqueo o una lentitud se propaga a todo el conjunto, se requiere 64 bits, el código administrado no tiene soporte, y la regla es implementarla en C++ nativo.
  • En Windows 11 el menú contextual se duplicó. Para sacar un comando propio en el nuevo menú hace falta IExplorerCommand+manifiesto MSIX, y las extensiones IContextMenu tradicionales quedan relegadas al lado de «Mostrar más opciones».
  • Para las aplicaciones que no pueden convertirse a MSIX, obtener la identidad con un sparse package (MSIX con ubicación externa) es la solución realista.
  • Si solo se quiere «que esta aplicación lo abra», la asociación y un verb estático siguen siendo suficientes hoy en día. Empezar por el medio más simple es también la pauta oficial.
  • Después de registrar, modificar o eliminar hay que notificarlo con SHChangeNotify, y al desinstalar, aunque se elimine el ProgID, se conserva el valor predeterminado de la clave de extensión. Windows Sandbox resulta muy útil para la verificación.

Si al cambiar de PC a Windows 11 nota que «el menú se ha escondido», empiece por comprobar en la tabla de decisión del capítulo 6 a cuál de las opciones (a), (b) o (c) corresponde su caso. Con eso podrá estimar en el momento el alcance del trabajo necesario.

Artículos relacionados

Áreas de consultoría relacionadas

KomuraSoft LLC se ocupa del diseño e implementación de la asociación de archivos, el menú contextual y las extensiones de shell de aplicaciones de negocio, de la adaptación al nuevo menú contextual de Windows 11 (migración a IExplorerCommand, introducción de sparse package), de la revisión del registro y la limpieza de instaladores existentes, y de la investigación de las causas cuando el Explorador va lento o se bloquea. Puede empezar simplemente decidiendo qué hacer con el menú que ha quedado escondido en «Mostrar más opciones».

Referencias

  1. Microsoft Learn, File Types. Sobre la estructura en la que la clave de extensión señala al ProgID, OpenWithProgIds, el uso diferenciado del registro en HKLM/HKCU\Software\Classes, la necesidad de llamar a SHChangeNotify (SHCNE_ASSOCCHANGED) tras modificar una asociación, y que al desinstalar se debe eliminar el ProgID conservando el valor predeterminado de la clave de extensión.  2 3 4 5

  2. Microsoft Learn, HKEY_CLASSES_ROOT Key. Sobre que HKEY_CLASSES_ROOT es una vista que combina HKLM\Software\Classes y HKCU\Software\Classes, que la definición del lado del usuario tiene prioridad sobre la de la máquina, y las reglas de reparto al escribir.  2

  3. Microsoft Learn, Windows app defaults platform. Sobre que el cambio de aplicación predeterminada está diseñado para hacerse solo a través de la interfaz de configuración del sistema, que los datos de configuración del usuario están ofuscados y protegidos frente a escritura por un controlador de filtro (UCPD.sys), que el cambio basado en el registro no tiene soporte, y que en entornos administrados se usa la directiva de grupo o MDM.  2

  4. Microsoft Learn, Working with Shell Extensions. Sobre los tipos de controladores de extensión de shell, que la extensión es una DLL que actúa como servidor COM en proceso cargado en el Explorador (y en los procesos que alojan el shell), que un bloqueo o cuelgue se propaga a todo el Explorador, el registro con ThreadingModel=Apartment, y que conviene considerar primero alternativas más simples que una extensión de shell.  2 3

  5. Microsoft Learn, Guidance for Implementing In-Process Extensions. Sobre que Microsoft no recomienda y no da soporte a la implementación de extensiones de shell en proceso en código administrado, las razones como los conflictos de versión del CLR, la reentrada y el ciclo de vida no determinista de los objetos, y que las extensiones fuera de proceso (controladores de vista previa o inicio desde shell\verb\command) sí admiten código administrado.  2 3

  6. Windows Developer Blog, Extending the Context Menu and Share Dialog in Windows 11. Sobre el diseño del nuevo menú contextual de Windows 11, la extensión mediante IExplorerCommand+identidad de aplicación, la ubicación superior de «Abrir» y «Abrir con», la agrupación de varios comandos en un flyout con el nombre de la aplicación, y que las extensiones IContextMenu tradicionales se cargan como el menú de Windows 10 mediante «Mostrar más opciones» (Shift+F10).  2 3

  7. Microsoft Learn, Add a File Explorer context menu command to a packaged desktop app. Sobre que el registro en el nuevo menú contextual de Windows 11 se realiza mediante la implementación de IExplorerCommand junto con la declaración en el manifiesto de windows.comServer y desktop4:FileExplorerContextMenus, que en ItemType se puede indicar *, Directory o Directory\Background, la coincidencia de arquitectura de la DLL, mantener rápidos los métodos de construcción del menú, la adaptación de aplicaciones sin empaquetar mediante sparse package, que aplicar el registro puede requerir reiniciar el Explorador, y que la asociación de archivos no es una extensión de menú de propósito general.  2 3 4 5 6 7 8

  8. Microsoft Learn, Grant package identity by packaging with external location. Sobre que se puede obtener identidad de paquete registrando un paquete con ubicación externa (sparse package) sin modificar el instalador existente, que está disponible desde Windows 10 versión 2004 en adelante, y que pasan a poder usarse funciones de Windows que requieren identidad (registro en el menú contextual, notificaciones, etc.).  2 3

  9. Microsoft Learn, Choosing a Static or Dynamic Shortcut Menu Method. Sobre que se debe elegir el método de verb estático más simple que cumpla el requisito, que IContextMenu es el más potente pero también el más complejo y está clasificado del lado no recomendado, y que IExplorerCommand/IExplorerCommandState es el método recomendado.  2

  10. Microsoft Learn, SHChangeNotify function. Sobre el método para emitir el evento SHCNE_ASSOCCHANGED que notifica al sistema los cambios en la asociación de archivos, y cómo usarlo para que el shell reconozca el cambio.  2

  11. Microsoft Learn, Application Registration. Sobre que se recomienda registrar el ejecutable mediante la subclave App Paths, el papel de la subclave Applications, el registro de verbs mediante SystemFileAssociations, y el orden de prioridad del ProgID y la información relacionada al cambiar la aplicación predeterminada. 

  12. Microsoft Learn, Creating Shortcut Menu Handlers. Sobre el método de registro de verbs estáticos, el orden de determinación del verb predeterminado (valor predeterminado → primer verb → Open → Open With), que el nombre visible de los verbs estándar lo suministra el sistema operativo, el verb extendido mediante Extended, que la asociación mediante comandos DDE está desaprobada (Deprecated), y las precauciones sobre la redirección WOW64 en entornos de 64 bits.  2 3

  13. Microsoft Learn, Verbs and File Associations. Sobre que el verb también se usa desde ShellExecuteEx, que los elementos de la cadena de comandos que puedan contener espacios deben ir entre comillas, que “%1” siempre debe escribirse entre comillas, y el registro del procedimiento predeterminado bajo HKCR\Applications. 

  14. Microsoft Learn, IExplorerCommand interface. Sobre la composición de métodos como GetTitle, GetIcon, GetState, Invoke y EnumSubCommands, que los métodos se llaman desde el hilo de la interfaz de usuario y por tanto no deben comunicarse con recursos de red, y que está disponible desde Windows Vista en adelante. 

  15. Microsoft Learn, Windows Sandbox. Sobre que permite iniciar en pocos segundos un entorno de Windows aislado y desechable, que al cerrarlo se descartan todos los cambios, que es adecuado para probar software y verificar instaladores, y que está disponible en Pro/Enterprise/Education. 

Artículos recientes con las mismas etiquetas para profundizar en temas cercanos.

Estas páginas sitúan el tema en un contexto más amplio de servicios y decisiones.

El artículo está directamente relacionado con los siguientes servicios.

Preguntas frecuentes

Preguntas habituales en las consultas sobre el tema del artículo.

¿Por qué el menú contextual de mi aplicación en Windows 11 solo aparece dentro de «Mostrar más opciones»?
Porque en Windows 11 el menú contextual del Explorador se dividió en dos niveles, uno nuevo y uno antiguo. Solo pueden aparecer en el nuevo menú los comandos que implementan la interfaz IExplorerCommand y que se registran en el manifiesto de un paquete MSIX (es decir, que tienen identidad de paquete); las extensiones de shell tradicionales basadas en IContextMenu quedaron relegadas al menú antiguo que se abre con «Mostrar más opciones» (Shift+F10). La extensión en sí no se ha roto, así que por ahora seguirá funcionando igual, pero si se quiere que aparezca en el nuevo menú es necesario migrar a IExplorerCommand y otorgarle identidad mediante MSIX o un sparse package.
¿Puedo hacer que mi instalador configure mi aplicación como la aplicación predeterminada para abrir un archivo con doble clic?
No es posible. La elección de la aplicación predeterminada está diseñada para que la haga el usuario, y Windows no admite que se cambie la aplicación predeterminada desde ningún lugar que no sea la interfaz de configuración del sistema. La información de UserChoice que conserva la elección de cada usuario está ofuscada, y además un controlador de filtro (UCPD.sys) bloquea que las aplicaciones la escriban. Lo único que puede hacer el instalador es registrar el ProgID y el verb, añadirse a OpenWithProgIds para figurar como candidato en «Abrir con», y en todo caso dirigir al usuario hacia la pantalla de configuración de aplicaciones predeterminadas. La implementación correcta no es arrebatar el valor predeterminado, sino preparar la aplicación para ser elegida.
¿Puedo escribir una extensión de shell en código administrado, como C#?
Microsoft afirma explícitamente que escribir en código administrado extensiones de shell que se cargan en proceso (como los controladores de menú contextual o los controladores de iconos) no es recomendable y no cuenta con soporte oficial. La razón es que la extensión se carga en el proceso de cualquier aplicación que abra el Explorador o un cuadro de diálogo de archivos común, y los conflictos de versión del CLR, la reentrada y la falta de determinismo en la vida útil de los objetos pueden desestabilizar la aplicación anfitriona. La regla es implementarlas en C++ nativo. En cambio, un EXE normal iniciado por el command de un verb, o una extensión fuera de proceso que corre en otro proceso, como un controlador de vista previa, sí puede escribirse en código administrado sin problema.
¿Qué es un sparse package (MSIX con ubicación externa)?
Es un paquete MSIX pequeño que no incluye los archivos de la propia aplicación, sino solo el manifiesto (la información de identidad). Si a una aplicación instalada normalmente con un instalador existente (MSI, Inno Setup, etc.) se le registra un sparse package apuntando con -ExternalLocation de Add-AppxPackage a la carpeta de instalación, esa aplicación obtiene identidad de paquete y puede usar funciones que la requieren, como el registro en el nuevo menú contextual de Windows 11 o las notificaciones toast. Está disponible desde Windows 10 versión 2004 en adelante, y el paquete debe firmarse con un certificado de confianza en el equipo de destino. Es una opción realista para adaptarse al nuevo menú sin migrar por completo la distribución a MSIX.
¿Qué hago si un elemento del menú contextual aparece duplicado o no desaparece?
Primero hay que aislar la causa comprobando si aparece en el nuevo menú, en el antiguo (Mostrar más opciones) o en ambos. La aparición duplicada suele deberse a que coexisten el registro tradicional del registro de Windows y el registro en el manifiesto MSIX, o a que, tras desinstalar, quedaron sin limpiar el ProgID o el registro de CLSID de la extensión. También conviene sospechar de una notificación perdida mediante SHChangeNotify (SHCNE_ASSOCCHANGED) después de cambiar una asociación, o de que falte reiniciar el Explorador justo después de registrar el paquete. Si aun así no se resuelve, deshabilitar temporalmente las extensiones que no son de Microsoft con ShellExView y aplicar una búsqueda binaria permite identificar la DLL causante.

Perfil del autor

Página de presentación del autor del artículo.

Go Komura

Representante de KomuraSoft LLC

Especializado en desarrollo de software para Windows, consultoría técnica e investigación de fallos, sobre todo en proyectos con sistemas existentes y errores difíciles de reproducir.

Volver al blog