Теперь, когда .NET CLR 4.0 поддерживает параллельную работу (SxS), теперь стало возможным писать расширения оболочки в управляемом коде.Я попытался это сделать и успешно кодировал обработчик свойств, который реализует IPropertyStore, IInitializeWithStream и IPropertyStoreCapabilities.
Обработчик работает нормально и вызывается, как и ожидалось, при просмотре файлов через проводник.Он также отлично работает при отображении пользовательских свойств на панели предварительного просмотра и на панели «Свойства» свойств файла.
Однако, когда я пытаюсь отредактировать свойство на панели предварительного просмотра, а затем нажимаю «Сохранить», я получаю сообщение об ошибке «Файл используется», говорящий о том, что файл открыт в проводнике Windows.
Несколько лакомых кусочков:
- Когда проводник вызывает IInitializeWithStream.Initialize, свойство STGM имеет значение STGM_SHARE_DENY_WRITE.
- И ни разу обозреватель не вызывал IPropertyStore.SetVueIPropertyStore.Commit.
- Я вижу повторяющиеся вызовы моего обработчика в разных потоках для одних и тех же свойств файла.
Так что мне нужно изменить (или установить в реестре) наполучить свойство сохранить на работу?
Обновление:
Спасибо Бену, у меня все работает.«Трудной частью» (по крайней мере для меня) было понимание того, что COM-взаимодействие никогда не вызовет Dispose или Finalize для моего PropertyHandler.Это оставляло файлы, которые я обрабатывал, открытыми до запуска GC.
К счастью, «протокол обработчика свойств» работает так, что когда IInitializeWithSream.Initialize () вызывается для ReadValue (), 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;
}