Of Icon handle lifetime and when is it truly disposed

T

Terry

There are a number of things about using unmanaged resources in Windows
Forms programming that is unclear to me.

In C++, if you loaded an icon resource using "ExtractIcon()", the resource
was valid until you called "DestroyIcon()". If you didn't, you had a leak.

In C#, I need to load icons from unmanaged programs (.exe, dll) at run time
and I want to make sure I'm not leaking resources, but it's not clear to me
how to insure that I'm not.

I've imported "ExtractIcon" and "DestroyIcon" like so:

[DllImport("Shell32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr ExtractIcon(IntPtr hInstance, string
strFileName, uint uiIconIndex);

[DllImport("User32.dll", CharSet=CharSet.Auto)]
public static extern bool DestroyIcon(IntPtr hIcon);

I load a number of icons from the file system and stuff them into an "Icon"
object and then into an ImageList.

public static Icon extractIcon(string strPath, int nIndex)
{
Icon icon = null;
IntPtr hIcon = WindowsAPI.ExtractIcon(IntPtr.Zero, strPath,
(uint)nIndex);
if (IntPtr.Zero != hIcon)
{
icon = Icon.FromHandle(hIcon);
}
return icon;
}

At this point, I've got an unmanaged recource being held by that "Icon"
object. What exactly is going on here? Does the "FromHandle()" call make a
copy of the resource into a *managed* resource? i.e. can I call
"DestroyIcon" on the unmanaged hIcon at this point? Or would that destroy
something that particular Icon object needs yet?

Let's say I never call "DestroyIcon" - will the unmanaged Icon resource get
cleaned up when the Icon's "Dispose()" method is called? (I know not to
rely on the Dispose for resource cleanup, I'm just asking out of curiosity).

Could someone please clear this up? I want to do this right.



Thanks,

Terry
 
N

Nicholas Paldino [.NET/C# MVP]

Terry,

You don't need the call to DestroyHandle. If you get a handle to an
icon, and then pass it to an Icon instance (through a call to the static
FromHandle method on the Icon class), then the Icon class will be
responsible for calling DestroyHandle.

If you want to destroy the handle, you can call the Dispose method on
the Icon class. If the instance is part of an imagelist, then you will have
to still call the Dispose method, as I believe the imagelist creates
duplicates of the images to work with.

Hope this helps.
 
T

Terry

Awesome! Thank you! Would anyone have a recommendation or a pointer to a
good article/book that explains this behavior? The SDK docs for the
ImageList and Icon classes really don't say anything about it.

(PS - Your name looks familiar - are you involved with the Mono project?)

Nicholas Paldino said:
Terry,

You don't need the call to DestroyHandle. If you get a handle to an
icon, and then pass it to an Icon instance (through a call to the static
FromHandle method on the Icon class), then the Icon class will be
responsible for calling DestroyHandle.

If you want to destroy the handle, you can call the Dispose method on
the Icon class. If the instance is part of an imagelist, then you will have
to still call the Dispose method, as I believe the imagelist creates
duplicates of the images to work with.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Terry said:
There are a number of things about using unmanaged resources in Windows
Forms programming that is unclear to me.

In C++, if you loaded an icon resource using "ExtractIcon()", the resource
was valid until you called "DestroyIcon()". If you didn't, you had a leak.

In C#, I need to load icons from unmanaged programs (.exe, dll) at run time
and I want to make sure I'm not leaking resources, but it's not clear to me
how to insure that I'm not.

I've imported "ExtractIcon" and "DestroyIcon" like so:

[DllImport("Shell32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr ExtractIcon(IntPtr hInstance, string
strFileName, uint uiIconIndex);

[DllImport("User32.dll", CharSet=CharSet.Auto)]
public static extern bool DestroyIcon(IntPtr hIcon);

I load a number of icons from the file system and stuff them into an "Icon"
object and then into an ImageList.

public static Icon extractIcon(string strPath, int nIndex)
{
Icon icon = null;
IntPtr hIcon = WindowsAPI.ExtractIcon(IntPtr.Zero, strPath,
(uint)nIndex);
if (IntPtr.Zero != hIcon)
{
icon = Icon.FromHandle(hIcon);
}
return icon;
}

At this point, I've got an unmanaged recource being held by that "Icon"
object. What exactly is going on here? Does the "FromHandle()" call
make
a
copy of the resource into a *managed* resource? i.e. can I call
"DestroyIcon" on the unmanaged hIcon at this point? Or would that destroy
something that particular Icon object needs yet?

Let's say I never call "DestroyIcon" - will the unmanaged Icon resource get
cleaned up when the Icon's "Dispose()" method is called? (I know not to
rely on the Dispose for resource cleanup, I'm just asking out of curiosity).

Could someone please clear this up? I want to do this right.



Thanks,

Terry
 
N

Nicholas Paldino [.NET/C# MVP]

Terry,

I have not done anything for the Mono project, although if you look
around here, you might see it from time to time.

As for books explaining this behavior, there isn't a guideline per se.
Unless the documentation says so, it basically comes down to intuition and a
lot of trial and error to figure out what it is (and for those who are more
unscrupulous, a decompiling as well).

However, a book on interop might be a good idea. You can try ".NET and
COM: The Complete Interoperability Guide" by Adam Nathan, located at (watch
for line wrap):

http://www.amazon.com/exec/obidos/t...104-8621847-0671969?v=glance&s=books&n=507846

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Terry said:
Awesome! Thank you! Would anyone have a recommendation or a pointer to a
good article/book that explains this behavior? The SDK docs for the
ImageList and Icon classes really don't say anything about it.

(PS - Your name looks familiar - are you involved with the Mono project?)

message news:[email protected]...
Terry,

You don't need the call to DestroyHandle. If you get a handle to an
icon, and then pass it to an Icon instance (through a call to the static
FromHandle method on the Icon class), then the Icon class will be
responsible for calling DestroyHandle.

If you want to destroy the handle, you can call the Dispose method on
the Icon class. If the instance is part of an imagelist, then you will have
to still call the Dispose method, as I believe the imagelist creates
duplicates of the images to work with.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Terry said:
There are a number of things about using unmanaged resources in Windows
Forms programming that is unclear to me.

In C++, if you loaded an icon resource using "ExtractIcon()", the resource
was valid until you called "DestroyIcon()". If you didn't, you had a leak.

In C#, I need to load icons from unmanaged programs (.exe, dll) at run time
and I want to make sure I'm not leaking resources, but it's not clear
to
me
how to insure that I'm not.

I've imported "ExtractIcon" and "DestroyIcon" like so:

[DllImport("Shell32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr ExtractIcon(IntPtr hInstance, string
strFileName, uint uiIconIndex);

[DllImport("User32.dll", CharSet=CharSet.Auto)]
public static extern bool DestroyIcon(IntPtr hIcon);

I load a number of icons from the file system and stuff them into an "Icon"
object and then into an ImageList.

public static Icon extractIcon(string strPath, int nIndex)
{
Icon icon = null;
IntPtr hIcon = WindowsAPI.ExtractIcon(IntPtr.Zero, strPath,
(uint)nIndex);
if (IntPtr.Zero != hIcon)
{
icon = Icon.FromHandle(hIcon);
}
return icon;
}

At this point, I've got an unmanaged recource being held by that "Icon"
object. What exactly is going on here? Does the "FromHandle()" call
make
a
copy of the resource into a *managed* resource? i.e. can I call
"DestroyIcon" on the unmanaged hIcon at this point? Or would that destroy
something that particular Icon object needs yet?

Let's say I never call "DestroyIcon" - will the unmanaged Icon
resource
get
cleaned up when the Icon's "Dispose()" method is called? (I know not to
rely on the Dispose for resource cleanup, I'm just asking out of curiosity).

Could someone please clear this up? I want to do this right.



Thanks,

Terry
 
T

Terry

Sorry to keep flogging this, but after some playing around, I'm not quite
sure I understand what's happening. Either the resources are not really
getting cleaned up like I thought they would or what I'm using to measure
the resources isn't accurate, or there's something else going on.

I'm using Task Manager and added the column for "GDI Objects". I created a
little test Form and added some code to load an icon in various ways, and
then Dispose(). I basically performed three tests.

1. Load an icon using "ExtractIcon()" (the IconLoader.extractIcon is just a
static method I wrote that does the actual ExtractIcon and then creates an
"Icon" object using FromHandle() and returns the icon)

Icon icon = IconLoader.extractIcon(@"F:\Media\Icons\go.ico", 0);
icon.Dispose();

What happens is on the "extractIcon()" call I see the GDI handle count go up
by 2. The GDI handle count remains the same after the "Dispose()".

2. Load an icon using "ExtractIcon()" but use "DestroyIcon()" to clean up
the icon resource
Icon icon = IconLoader.extractIcon(@"F:\Media\Icons\go.ico", 0);
IconLoader.destroyIcon(icon.Handle);

What happens here, is on the "extractIcon()" call the GDI handle count goes
up by 2 and on the "destroyIcon()" call, it goes down by 2.

3. Load an icon from an embedded resource and call "Dispose()"
Stream s =
this.GetType().Assembly.GetManifestResourceStream("TestResourceUsage.go.ico"
);
Icon icon = new Icon( s );
icon.Dispose();

What happens here is on the "new Icon(s)" line, the GDI handle count goes up
by 2 and on the "Dispose()" call it goes down by 2.

The way I'm reading the results of these three tests is that if you load a
resource using a Win32 API call like "ExtractIcon()" then you *must* call
"DestroyIcon()" to free the resource.

I'm still confused when it comes to ImageLists. When I watch the GDI Handle
count as I'm adding an image or icon to an ImageList, I see the GDI handle
count go up by 2 (which corresponds to what Nicholas had said about the
ImageList making a copy of the resource) but no matter what I do, I'm unable
to recover the resources that are allocated by the ImageList. Even if I
clear the Images collection, call "Dispose()" on the ImageList and set it's
reference to "null" the allocated GDI handles are never recovered - even if
the image is loaded from the managed manifest. I would expect that clearing
the ImageList would also call Dispose() on each of the images contained in
the ImageList (but maybe it doesn't).

Maybe what I'm doing is not a valid test, but it makes me uncomfortable when
I get behavior that doesn't seem consistent. Are my tests invalid? My
conclusions wrong? Or is there something else going on here that I'm
unaware of?

Thanks,
Terry

Nicholas Paldino said:
Terry,

I have not done anything for the Mono project, although if you look
around here, you might see it from time to time.

As for books explaining this behavior, there isn't a guideline per se.
Unless the documentation says so, it basically comes down to intuition and a
lot of trial and error to figure out what it is (and for those who are more
unscrupulous, a decompiling as well).

However, a book on interop might be a good idea. You can try ".NET and
COM: The Complete Interoperability Guide" by Adam Nathan, located at (watch
for line wrap):

http://www.amazon.com/exec/obidos/tg/detail/-/067232170X/qid=1075146976//ref
=sr_8_xs_ap_i7_xgl14/104-8621847-0671969?v=glance&s=books&n=507846

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Terry said:
Awesome! Thank you! Would anyone have a recommendation or a pointer to a
good article/book that explains this behavior? The SDK docs for the
ImageList and Icon classes really don't say anything about it.

(PS - Your name looks familiar - are you involved with the Mono project?)

message news:[email protected]...
Terry,

You don't need the call to DestroyHandle. If you get a handle to an
icon, and then pass it to an Icon instance (through a call to the static
FromHandle method on the Icon class), then the Icon class will be
responsible for calling DestroyHandle.

If you want to destroy the handle, you can call the Dispose method on
the Icon class. If the instance is part of an imagelist, then you
will
have
to still call the Dispose method, as I believe the imagelist creates
duplicates of the images to work with.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

There are a number of things about using unmanaged resources in Windows
Forms programming that is unclear to me.

In C++, if you loaded an icon resource using "ExtractIcon()", the resource
was valid until you called "DestroyIcon()". If you didn't, you had a
leak.

In C#, I need to load icons from unmanaged programs (.exe, dll) at run
time
and I want to make sure I'm not leaking resources, but it's not
clear
to
me
how to insure that I'm not.

I've imported "ExtractIcon" and "DestroyIcon" like so:

[DllImport("Shell32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr ExtractIcon(IntPtr hInstance, string
strFileName, uint uiIconIndex);

[DllImport("User32.dll", CharSet=CharSet.Auto)]
public static extern bool DestroyIcon(IntPtr hIcon);

I load a number of icons from the file system and stuff them into an
"Icon"
object and then into an ImageList.

public static Icon extractIcon(string strPath, int nIndex)
{
Icon icon = null;
IntPtr hIcon = WindowsAPI.ExtractIcon(IntPtr.Zero, strPath,
(uint)nIndex);
if (IntPtr.Zero != hIcon)
{
icon = Icon.FromHandle(hIcon);
}
return icon;
}

At this point, I've got an unmanaged recource being held by that "Icon"
object. What exactly is going on here? Does the "FromHandle()"
call
make
a
copy of the resource into a *managed* resource? i.e. can I call
"DestroyIcon" on the unmanaged hIcon at this point? Or would that destroy
something that particular Icon object needs yet?

Let's say I never call "DestroyIcon" - will the unmanaged Icon resource
get
cleaned up when the Icon's "Dispose()" method is called? (I know
not
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top