现在 .NET CLR 4.0 支持并行 (SxS) 操作,现在应该可以编写 shell
托管代码中的扩展。我已经尝试过并成功编码了属性处理程序
实现 IPropertyStore、IInitializeWithStream 和 IPropertyStoreCapability。
处理程序
工作正常,并在通过资源管理器浏览文件时按预期调用。它也可以很好地显示
预览面板和文件属性“详细信息”面板中的自定义属性。
然而,当我尝试
在预览面板中编辑属性,然后单击“保存”我收到“文件正在使用”错误,指出
该文件已在 Windows 资源管理器中打开。
一些花絮:
- 当资源管理器调用 IInitializeWithStream.Initialize 时,STGM 属性设置为 STGM_SHARE_DENY_WRITE。
- 浏览器从未调用 IPropertyStore.SetValue 或 IPropertyStore.Commit。
- 我看到在不同线程上重复调用相同文件属性的处理程序。
那么我需要更改什么(或在注册表中设置)才能使属性保存正常工作?
Update:
感谢本,我已经成功了。 “困难的部分”(至少对我来说)是理解 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;
}
是的,您必须 AddRef() 流以使其保持打开状态并保持引用正确活动。
请注意,索引器也将使用您的属性处理程序来打开文件。因此,如果泄漏流对象,文件将保持打开状态。您可以使用 sysinternals procexp 来告诉哪个进程打开了文件,或者使用 procmon 来告诉它使用了哪些调用和参数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)