什么是实施托pipe属性处理程序shell扩展的正确方法?

现在,.NET CLR 4.0支持并行(SxS)操作,现在应该可以在托pipe代码中编写shell扩展了。 我已经尝试过,并成功地编写了一个Property Handler,它实现了IPropertyStore,IInitializeWithStream和IPropertyStoreCapabilities。

处理程序工作正常,并通过浏览器浏览文件时按预期调用。 在显示预览面板和文件属性“详细信息”面板中的自定义属性时,它也可以正常工作。

但是,当我尝试在预览面板中编辑属性,然后单击“保存”时,出现“文件正在使用”错误,说该文件在Windows资源pipe理器中打开。

一些花絮:

  1. 当资源pipe理器调用IInitializeWithStream.Initialize时,STGM属性被设置为STGM_SHARE_DENY_WRITE。
  2. 而资源pipe理器在任何时候都不会调用IPropertyStore.SetValue或IPropertyStore.Commit。
  3. 我看到在不同的线程对我的处理程序重复调用相同的文件属性。

那么,我需要改变(或在registry中设置)以使财产保存工作?

更新:

感谢本,我有它的工作。 “困难的部分”(至less对我来说)是理解COM互操作将永远不会调用我的PropertyHandler上的Dispose或Finalize。 这是我打开的文件,直到GC运行。

幸运的是,“属性处理程序协议”的工作原理是当为ReadValue()调用IInitializeWithSream.Initialize()时,streamMode是ReadOnly,当调用SetValue()时,streamMode将被调用ReadWrite和Commit()最后。

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; } 

Solutions Collecting From Web of "什么是实施托pipe属性处理程序shell扩展的正确方法?"

是的,你必须AddRef()流来保持它打开,并保持参考正确的。

请注意,索引器将使用您的属性处理程序来打开文件。 所以如果你泄漏流对象,文件将保持打开状态。 您可以使用sysinternals procexp来告诉哪个进程打开了该文件,或者使用procmon来告诉它使用了哪些调用和参数。

资源管理器试图确保它不会干扰可能打开文件的其他应用程序。 该文件是否可以被另一个应用程序合法地使用? 预览处理程序是否打开?

有时,我们会看到属性处理程序将其流保持打开时间超过必要时间(或基于文件的处理程序以限制性的权限打开文件)。 你能否验证你是否及时发布流?

最后,我不认为这与您的直接问题有关,但不支持使用.NET外壳扩展。 我们建议不要将其纳入任何产品。

-ben