This project is read-only.
1

Closed

A generic error occurred in GDI+

description

Hi

I was trying to write a demo for a grid (just displaying name/icon) and are getting GDI+ Exceptions in the following part (after scrolling for a while in the grid (so requesting quite some icons).

It happens in the following lines (the return statement to be exact) of Icon.GetIcons.cs:
            using (Stream stream = assembly.GetManifestResourceStream(assemblyResourceName))
            {
                var bipmap = new Bitmap(stream);
                return Icon.FromHandle(bipmap.GetHicon());
            }
I kinda looks like running out of handles.

regards
wvdvegt
Closed Jun 4, 2014 at 1:41 AM by Jonathan_Magnan

comments

Jonathan_Magnan wrote Feb 21, 2014 at 12:18 PM

Hello,

I was able to reproduce this bug, I have found at least one workaround.

http://connect.microsoft.com/VisualStudio/feedback/details/345656/a-generic-error-occurred-in-gdi-at-system-drawing-bitmap-gethicon#

I will try to google for a better solution this week-end.

A new version will be release at the start of the next week with this correction.

Thank

Jonathan.

wrote Feb 21, 2014 at 12:19 PM

Jonathan_Magnan wrote Feb 23, 2014 at 3:31 PM

After some research,

Its look like this bug is well known and none seem to have completely solved this issue yet.

The workaround work but not completely (Cloning and destroying the Initial Icon Handle). I still cannot keep all icon in a list or something similar (still the same error) however, I don’t have any more an error when assigning the Icon to my Form.Icon since the Icon is disposed every time.

To solve your problem, you will need to dispose your icon once you don’t need them anymore (will only work on next release which is very soon!) or use Bitmap/Image instead.

I hope this helped you.

wvd_vegt wrote Feb 24, 2014 at 11:03 AM

Hi

Indeed a nasty problem. I found this that may help a bit (convert Bitmap to Icon using a stream). I have not tried it though.

http://www.codeproject.com/Articles/7122/Dynamically-Generating-Icons-safely

This may also help (assign the icon to a new one and destroy the original icon before returning it):

http://msdn.microsoft.com/en-us/library/system.drawing.icon.fromhandle(v=vs.110).aspx

For my demo app I already switched to Bitmaps for the time being.

regards
wvdvegt

wvd_vegt wrote Feb 24, 2014 at 7:57 PM

HI

I think the following change to the code will make the GetIcon work.
    [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = CharSet.Auto)]
    extern static bool DestroyIcon(IntPtr handle);
and inside the GetIcon methods:
using (Stream stream = assembly.GetManifestResourceStream(assemblyResourceName))
            {
                if (stream != null)
                {
                    //var bipmap = new Bitmap(stream);
                    //return Icon.FromHandle(bipmap.GetHicon());

                    using (Bitmap bipmap = new Bitmap(stream))
                    {
                        IntPtr Hicon = bipmap.GetHicon();
                        using (Icon ico = Icon.FromHandle(Hicon))
                        {
                            Icon clone = (Icon)ico.Clone();

                            DestroyIcon(ico.Handle);

                            return clone;
                        }
                    }
                }
            }
Also note that there is nu real use for the var keywork (typing it is faster as far as I know).

This adjusted code lets me scroll all icons at least two times compared to 2/3 of the icons with the old code. If you comment the DestroyIcon line the old behavior is back.

The code above also shows the null stream safeguard I put it.

Another optimization of the code might be to use the Bitmap Extension methods inside GetIcon16/32 and getImage16/32 as the basic code to get the resource s the same.

regards
wvdvegt

wrote Feb 25, 2014 at 2:10 AM

Jonathan_Magnan wrote Feb 25, 2014 at 2:20 AM

I have found also the article on code project, however I feel like this solution will cause more trouble than solution.

For your second suggestion, to clone and destroy the initial icon, this is exactly what I'm doing in the new release.

By destroying the initial icon, we are now able to dispose of the cloning icon which was not possible before. As I said in my earlier post, this solution is not perfect since the GDI+ can still throw an error (Icon always use a handle and must be disposed by the application).

I will put this issue as resolved since your solution is the only one possible for now even if the GDI+ can still raise an error.

Thank a lot for all your feedback, this helped me a lot.

wvd_vegt wrote Feb 25, 2014 at 2:41 PM

Hi

The only solution against the GDI+ errors after this fix seems a try/catch block and return a null icon like I suggested for the other types too.

Glad to be of help!

regards
wvdvegt

wrote Jun 4, 2014 at 1:41 AM