BCUninstaller/Bulk-Crap-Uninstaller · error · ArgumentException
Icon handle must not be zero
Error message
Icon handle must not be zero
What it means
Thrown by DrawingTools.CreateOwnedIconFromHandle(IntPtr handle) when handle == IntPtr.Zero. The method clones the native icon into a managed Icon and then always calls DestroyIcon on the handle in a finally block, so passing zero would both be meaningless and would leak/destroy an invalid handle; it fails fast with ArgumentException(nameof(handle)).
Source
Thrown at source/KlocTools/Tools/DrawingTools.cs:65
var iconPath = new StringBuilder(260);
iconPath.Append(filePath);
var index = 0;
var handle = SafeNativeMethods.ExtractAssociatedIcon(new HandleRef(null, IntPtr.Zero), iconPath, ref index);
if (handle != IntPtr.Zero)
return CreateOwnedIconFromHandle(handle);
}
return null;
}
/// <summary>
/// Clone an icon handle into a managed icon instance and release the original native handle.
/// </summary>
public static Icon CreateOwnedIconFromHandle(IntPtr handle)
{
if (handle == IntPtr.Zero)
throw new ArgumentException("Icon handle must not be zero", nameof(handle));
try
{
using (var temporaryIcon = Icon.FromHandle(handle))
{
return (Icon)temporaryIcon.Clone();
}
}
finally
{
SafeNativeMethods.DestroyIcon(handle);
}
}
/// <summary>
/// This class suppresses stack walks for unmanaged code permission.
/// (System.Security.SuppressUnmanagedCodeSecurityAttribute is applied to this class.) View on GitHub (pinned to 608321de98)
Solutions
- Check for IntPtr.Zero before calling and skip/null-return instead.
- Use the calling code's own guard (the snippet already shows the caller does `if (handle != IntPtr.Zero) return CreateOwnedIconFromHandle(handle);`).
- Log why the source extraction returned zero (bad file path, missing resource) and handle upstream.
Example fix
// before var icon = DrawingTools.CreateOwnedIconFromHandle(h); // h may be Zero // after Icon icon = h == IntPtr.Zero ? null : DrawingTools.CreateOwnedIconFromHandle(h);
Defensive patterns
Strategy: validation
Validate before calling
Icon icon = handle == IntPtr.Zero ? null : DrawingTools.CreateOwnedIconFromHandle(handle);
Type guard
static bool IsValidIconHandle(IntPtr h) => h != IntPtr.Zero;
Prevention
- Always test native icon-extraction results for IntPtr.Zero before forwarding.
- Treat zero as 'no icon' and return null upstream rather than throwing.
- Log the source of zero handles (missing file/resource) for diagnosis.
When it happens
Trigger: Passing IntPtr.Zero (a sentinel for 'no icon') into CreateOwnedIconFromHandle instead of checking first. Common after ExtractIcon/LoadImage return zero on failure.
Common situations: Calling the API after a native icon-extraction call that returned zero (file has no associated icon, missing resource, wrong type), or forwarding an uninitialised IntPtr.
Related errors
- Font size must be higher than 0
- Minimum value must be lower than or equal to the maximum val
- Not a Windows .exe file.
- Failed to parse the input
- Process name can't be null or empty
AI-assisted analysis of BCUninstaller/Bulk-Crap-Uninstaller@608321de98 (2026-08-13).
Data as JSON: /api/errors/ac03366ea8a4f930.
Report an issue: GitHub.