¿Cuál es la forma correcta de implementar una extensión de shell de manejador de propiedades administradas?

StackOverflow https://stackoverflow.com/questions/3200245

Pregunta

Ahora que .NET CLR 4.0 admite la operación de lado a lado (SXS), ahora debería ser posible escribir Shell Extensiones en código administrado. He intentado esto y codificado con éxito un controlador de propiedades. Eso implementa iPropertyStore, IinitializeWithStream y iPropertyStorecAcabilidades.

el manejador Funciona bien y se llama como se espera al navegar por los archivos a través del Explorador. También funciona bien en mostrar el Propiedades personalizadas en el panel de vista previa y el panel de propiedades de los archivos "Detalle".

Sin embargo, cuando intento Edite una propiedad en el panel de vista previa y luego haga clic en "Guardar", obtenga un error "Archivo en uso" que dice que El archivo está abierto en el Explorador de Windows.

A pocos tidbits:

  1. Cuando el explorador llama a IinitializeWithStream.initializar la propiedad STGM se establece en STGM_SHARE_DENYY_WRITE.
  2. y en ningún momento llamaron a explorador ipropertystore.setvalue o ipropertystore.commit.
  3. Veo llamadas repetidas a mi controlador en diferentes hilos para las mismas propiedades de archivo.
  4. Entonces, ¿qué necesito para cambiar (o establecer en el Registro) para que la propiedad ahorre para trabajar?

    Actualización:

    Gracias a Ben, lo tengo trabajando. La "parte difícil" (al menos para mí) estaba entendiendo que COM INTEROP nunca llamaría a disponer o finalizaría en mi propiedad. Esto estaba dejando los archivos que procesé abierta hasta que el GC corrió.

    Afortunadamente, el "Protocolo del manejador de propiedades" funciona de manera que, cuando cuando, cuando se encuentran, se le llama readvalue (), el código de transmisión se realiza de forma gratuita, y cuando se llama a un setvalue (), el código StreamMode se le prepara y comete () será llamado al final.

    int IInitializeWithStream.Initialize( IStream stream, uint grfMode )
    {
        _stream = stream;
        _streamMode = (Stgm)grfMode;
    
        Load();
    
        // We release here cause if this is a read operation we won't get called back, 
        // and our finializer isn't called. 
        if ( ( _streamMode & Stgm.ReadWrite ) != Stgm.ReadWrite )
        {
            Marshal.ReleaseComObject( _stream );
            _stream = null;
        }
        return HResult.S_OK;
    }
    
    int IPropertyStore.Commit()
    {
        bool result = false;
    
        if ( _stream != null )
        {
            result = WriteStream( _stream );
            Marshal.ReleaseComObject( _stream );
            _stream = null;
        }
    
        return result ? HResult.S_OK : HResult.E_FAIL;
    }
    

¿Fue útil?

Solución

Sí, tiene que addref () el flujo para mantenerlo abierto y mantener la referencia con vida correctamente.

Tenga en cuenta que el indexador utilizará el controlador de su propiedad para abrir el archivo también.Entonces, si fugas el objeto Stream, el archivo permanecerá abierto.Puede usar el Procedente SysInternals para decir qué proceso tiene el archivo abierto, o Procon para saber qué llamadas y parámetros utilizó.

Otros consejos

Explorer intenta asegurarse de que no interfiera con otras aplicaciones que puedan abrir el archivo.¿Podría el archivo estar legítimamente en uso por otra aplicación?¿Hay un manejador de vista previa abierto?

A veces, vemos manejadores de propiedades que mantienen sus corrientes abiertas más tiempo de lo necesario (o manejadores basados en archivos que abren el archivo con permisos restrictivos).¿Puedes verificar si está lanzando la secuencia de manera oportuna?

Finalmente, no creo que esto esté relacionado con su problema inmediato, pero el uso de extensiones de shell .NET no está compatible.Recomendamos que esto no se incorpore a ningún producto.

-ben

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top