Compartir a través de


Inicialización de controladores de extensión de shell

Gran parte de la implementación de un objeto de controlador de extensión de Shell está determinado por su tipo. Sin embargo, hay algunos elementos comunes. En este tema se describen los aspectos de la implementación que comparten todos los controladores de extensión de Shell.

Todos los controladores de extensión de Shell son objetos del modelo de objetos componentes (COM) en proceso. Se deben asignar un GUID y registrarse como se describe en Registro de controladores de extensión de shell. Se implementan como archivos DLL y deben exportar las siguientes funciones estándar:

  • DllMain. Punto de entrada estándar al archivo DLL.
  • DllGetClassObject. Expone el generador de clases del objeto.
  • DllCanUnloadNow. COM llama a esta función para determinar si el objeto está atendiendo a cualquier cliente. Si no es así, el sistema puede descargar el archivo DLL y liberar la memoria asociada.

Al igual que todos los objetos COM, los controladores de extensión de Shell deben implementar una interfaz IUnknown y un generador de clases. La mayoría también debe implementar una interfaz IPersistFile o IShellExtInit en Windows XP o versiones anteriores. Estos se reemplazaron por IInitializeWithStream, IInitializeWithItem e IInitializeWithFile en Windows Vista. El Shell usa estas interfaces para inicializar el controlador.

La interfaz IPersistFile debe implementarse mediante lo siguiente:

  • Controladores de iconos
  • Controladores de datos
  • Controladores de colocación

La interfaz IShellExtInit debe implementarse mediante lo siguiente:

  • Controladores de menú contextual
  • Controladores de arrastrar y colocar
  • Controladores de hoja de propiedades

En el resto de este tema se tratan los temas siguientes:

Implementación de IPersistFile

La interfaz IPersistFile está diseñada para permitir que un objeto se cargue o se guarde en un archivo de disco. Tiene seis métodos además de IUnknown, cinco propios, y el método GetClassID que hereda de IPersist. Con las extensiones de Shell, IPersist solo se usa para inicializar un objeto de controlador de extensión de Shell. Dado que normalmente no es necesario leer o escribir en el disco, solo los métodos GetClassID y Load requieren una implementación que no sea compatible.

El Shell llama primero a GetClassID y la función devuelve el identificador de clase (CLSID) del objeto de controlador de extensión. A continuación, Shell llama a Load y pasa dos valores. El primero, pszFile, es una cadena Unicode con el nombre del archivo o carpeta en la que Shell está a punto de funcionar. El segundo es dwMode, que indica el modo de acceso a archivos. Dado que normalmente no hay necesidad de acceder a los archivos, dwMode suele ser cero. El método almacena estos valores según sea necesario para la referencia posterior.

En el siguiente fragmento de código se muestra cómo un controlador de extensión de Shell típico implementa los métodos GetClassID y Load . Está diseñado para controlar ANSI o Unicode. CLSID_SampleExtHandler es el GUID del objeto de controlador de extensión y CSampleShellExtension es el nombre de la clase utilizada para implementar la interfaz. Las variables m_szFileName y m_dwMode son variables privadas que se usan para almacenar el nombre del archivo y las marcas de acceso.

class CSampleShellExtension : public IPersistFile
{
    // Method declarations not included

    private:
    WCHAR m_szFileName[MAX_PATH];    // The file name
    DWORD m_dwMode;                  // The file access mode
}

IFACEMETHODIMP CSampleShellExtension::GetClassID(__out CLSID *pCLSID)
{
    *pCLSID = CLSID_SampleExtHandler;
}

IFACEMETHODIMP CSampleShellExtension::Load(PCWSTR pszFile, DWORD dwMode)
{
    m_dwMode = dwMode;
    return StringCchCopy(m_szFileName, ARRAYSIZE(m_szFileName), pszFile); 
}

// The implementation sample is continued in the next section.

Implementación de IShellExtInit

La interfaz IShellExtInit solo tiene un método, IShellExtInit::Initialize, además de IUnknown. El método tiene tres parámetros que el Shell puede usar para pasar varios tipos de información. Los valores pasados dependen del tipo de controlador y algunos se pueden establecer en NULL.

  • pidlFolder contiene el puntero de una carpeta a una lista de identificadores de elemento (PIDL). Se trata de un PIDL absoluto. Para las extensiones de hoja de propiedades, este valor es NULL. Para las extensiones de menú contextual, es el PIDL de la carpeta que contiene el elemento cuyo menú contextual se muestra. En el caso de los controladores de arrastrar y colocar no predeterminados, es el PIDL de la carpeta de destino.
  • pDataObject contiene un puntero a la interfaz IDataObject de un objeto de datos. El objeto de datos contiene uno o varios nombres de archivo en formato CF_HDROP .
  • hRegKey contiene una clave del Registro para el objeto de archivo o el tipo de carpeta.

El método IShellExtInit::Initialize almacena el nombre de archivo, el puntero IDataObject y la clave del Registro según sea necesario para su uso posterior. En el fragmento de código siguiente se muestra una implementación de IShellExtInit::Initialize. Por motivos de simplicidad, en este ejemplo se supone que el objeto de datos contiene solo un único archivo. En general, el objeto de datos puede contener varios archivos, cada uno de los cuales tendrá que extraerse.

// This code continues the CSampleShellExtension sample shown in the
// "Implementing IPersistFile" section above.

class CSampleShellExtension : public IShellExtInit
{
    // Method declarations not included
    
    private:
    // IDList of the folder for extensions invoked on the folder, such as 
    // background context menu handlers or nondefault drag-and-drop handlers. 
    PIDLIST_ABSOLUTE m_pidlFolder;
    
    // The data object contains an expression of the items that the handler is 
    // being initialized for. Use SHCreateShellItemArrayFromDataObject to 
    // convert this object to an array of items. Use SHGetItemFromObject if you
    // are only interested in a single Shell item. If you need a file system
    // path, use IShellItem::GetDisplayName(SIGDN_FILESYSPATH, ...).
    IDataObject *m_pdtobj;
    
    // For context menu handlers, the registry key provides access to verb 
    // instance data that might be stored there. This is a rare feature to use 
    // so most extensions do not need this variable.
    HKEY m_hRegKey;             
}
    
// This method must be very efficient. Do not do any unnecessary work here.
// Use Initialize to acquire resources that will be used later.

IFACEMETHODIMP CSampleShellExtension::Initialize(__in_opt PCIDLIST_ABSOLUTE pidlFolder,
                                                 __in_opt IDataObject *pDataObject, 
                                                 __in_opt HKEY hRegKey) 
{ 
    // In some cases, handlers are initialized multiple times. Therefore, 
    // clear any previous state here.
    CoTaskMemFree(m_pidlFolder);
    m_pidlFolder = NULL;
    
    if (m_pdtobj)
    { 
        m_pdtobj->Release(); 
    }
    
    if (m_hRegKey)
    {
        RegCloseKey(m_hRegKey);
        m_hRegKey = NULL;
    }
    
    // Capture the inputs for use later.
    HRESULT hr = S_OK;
    
    if (pidlFolder)
    {
        m_pidlFolder = ILClone(pidlFolder);   // Make a copy to use later.
        hr = m_pidlFolder ? S_OK : E_OUTOFMEMORY;
    }
    
    if (SUCCEEDED(hr))
    {
        // If a data object pointer was passed into the method, save it and
        // extract the file name. 
        if (pDataObject) 
        { 
            m_pdtobj = pDataObject; 
            m_pdtobj->AddRef(); 
        }
    
        // It is uncommon to use the registry handle, but if you need it,
        // duplicate it now.
        if (hRegKey)
        {
            LSTATUS const result = RegOpenKeyEx(hRegKey, NULL, 0, KEY_READ, &m_hRegKey); 
            hr = HRESULT_FROM_WIN32(result);
        }
    }
    
    return hr;
}

Personalización de información sobre información

Hay dos maneras de personalizar la información sobre información. Una manera es implementar un objeto que admita IQueryInfo y, a continuación, registrar el objeto en la subclave adecuada en el Registro (consulte a continuación). Como alternativa, puede especificar una cadena fija o una lista de determinadas propiedades de archivo que se van a mostrar.

Para mostrar una cadena fija para una extensión de espacio de nombres, cree una subclave denominada InfoTip debajo de la clave CLSID de la extensión de espacio de nombres. Establezca los datos de esa subclave para que sea la cadena que desea mostrar.

HKEY_CLASSES_ROOT
   CLSID
      {CLSID}
         InfoTip = InfoTip string for your namespace extension

Para mostrar una cadena fija para un tipo de archivo, cree una subclave denominada Información sobre información bajo la clave ProgID del tipo de archivo para el que desea proporcionar información sobre información. Establezca los datos de esa subclave para que sea la cadena que desea mostrar.

HKEY_CLASSES_ROOT
   ProgID
      InfoTip = InfoTip string for all files of this type

Si desea que shell muestre determinadas propiedades de archivo en la información sobre información sobre un tipo de archivo específico, cree una subclave denominada InfoTip debajo de la clave ProgID de ese tipo de archivo. Establezca los datos de esa subclave para que sea una lista delimitados por punto y coma de nombres de propiedad canónicos o {fmtid}, pares pid donde propname es un nombre de propiedad canónico y {fmtid},pid es un par FMTID/PID.

HKEY_CLASSES_ROOT
   ProgID
      InfoTip = propname;propname;{fmtid},pid;{fmtid},pid

Se pueden usar los siguientes nombres de propiedad.

Nombre de propiedad Descripción Recuperado de
Autor Autor del documento PIDSI_AUTHOR
Título Título del documento PIDSI_TITLE
Asunto Resumen del asunto PIDSI_SUBJECT
Comentario Comentarios de documentos propiedades de PIDSI_COMMENT o carpeta/unidad
PageCount Número de páginas PIDSI_PAGECOUNT
Nombre Nombre descriptivo Vista de carpeta estándar
OriginalLocation Ubicación del archivo original Carpeta maletín y carpeta papelera de reciclaje
DateDeleted Se eliminó el archivo de fecha Carpeta papelera de reciclaje
Tipo Tipo de archivo Vista de detalles de carpeta estándar
Size Tamaño del archivo Vista de detalles de carpeta estándar
SyncCopyIn Igual que OriginalLocation Igual que OriginalLocation
Modificado Fecha de última modificación Vista de detalles de carpeta estándar
Creado Fecha de creación Vista de detalles de carpeta estándar
Acceso Fecha en la que se ha accedido por última vez Vista de detalles de carpeta estándar
InFolder Directorio que contiene el archivo Resultados de búsqueda de documentos
Rank Coincidencia de calidad de búsqueda Resultados de búsqueda de documentos
FreeSpace Espacio de almacenamiento disponible Unidades de disco
NumberOfVisits Número de visitas carpeta Favoritos
Atributos Atributos de archivo Vista de detalles de carpeta estándar
Compañía Nombre de la compañía PIDDSI_COMPANY
Category Categoría de documento PIDDSI_CATEGORY
Copyright Derechos de autor de los medios PIDMSI_COPYRIGHT
HTMLInfoTipFile Archivo de información sobre HTML Desktop.ini archivo para la carpeta

 

Registro de controladores de extensiones de shell