@EvilBeaver
упоротый гик

Как правильно пользоваться ISharedBitmap в c#?

Есть задача получить эскизы фотографий из системного кэша (thumbnails).
Код на C# WPF. COM-Интерфейс IThumbnailCache возвращает хитрый ISharedBitmap, который имеет непонятное мне время жизни. Вот код:
public System.Windows.Media.ImageSource GetThumbnail(string imagePath)
        {

            IShellItem shItem;
            Guid iIdIShellItem = new Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe");
            var hr = SHCreateItemFromParsingName(imagePath, IntPtr.Zero, iIdIShellItem, out shItem);
            if (hr == 0)
            {
                Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");
                Guid CLSID_LocalThumbnailCache = new Guid("50EF4544-AC9F-4A8E-B21B-8A26180DB13F");

                var type = Type.GetTypeFromCLSID(CLSID_LocalThumbnailCache);
                var tbCache = (IThumbnailCache)Activator.CreateInstance(type);

                ISharedBitmap bmp = null;
                WTS_CACHEFLAGS cFlags;
                WTS_THUMBNAILID bmpId;
                hr = (int)tbCache.GetThumbnail(shItem, 128, WTS_FLAGS.WTS_EXTRACT, out bmp, out cFlags, out bmpId);
                if (hr == 0)
                {
                    var bmpPtr = IntPtr.Zero;
                    if (bmp.GetSharedBitmap(out bmpPtr) == 0)
                    {
                         SIZE size;
                         bmp.GetSize(out size);
                         var iSrc = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                               bmpPtr, IntPtr.Zero, Int32Rect.Empty,
                               System.Windows.Media.Imaging.BitmapSizeOptions.FromWidthAndHeight(size.cx, size.cy));
                    }
                    else
                    {
                        return null;
                    }
                }
                else
                {
                    return null;
                }

            }

            return null;

вызов CreateBitmapSourceFromHBitmap падает с HRESULT: 0x88982F94.
Я сделал обертку на C++/CLI и возвращал в C# HBITMAP, полученный методом ISharedBitmap::GetSharedBitmap().
Опытным путем выяснил, что данный HRESULT: 0x88982F94 выдается, если на стороне С++ вызван ISharedBitmap->Release(). То есть, если битмап освобожден, то WPF выдаст данное исключение. Однако, в приведенном коде нет освобождения для ISharedBitmap. Почему он как-будто освобожден к моменту вызова CreateBitmapSourceFromHBitmap?
Как вообще регулируется время жизни COM-объектов, подключенных через P/Invoke?
  • Вопрос задан
  • 2770 просмотров
Решения вопроса 1
@EvilBeaver Автор вопроса
упоротый гик
Вопрос решился следующим образом:
Вместо GetSharedBitmap получил битмап с помощью Detach, который в MSDN описан, как "Retrieves the bitmap contained in an ISharedBitmap object, and returns a copy if the contained bitmap resides in shared memory. After calling this method the bitmap is no longer associated with this ISharedBitmap" Получившийся "отсоединенный" битмап работает ожидаемо, после использования его освобождаю через DeleteObject.
Как правильно пользоваться "shared" битмапом так и не понял.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@markeshov
Попробуй использовать Marshal.AddRef и Marshal.Release
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы