C# código para esta tarea:
public static class PrinterIcons
{
public static Dictionary<string, Icon> GetPrintersWithIcons(IntPtr hwndOwner)
{
Dictionary<string, Icon> result = new Dictionary<string, Icon>();
Shell32.IShellFolder iDesktopFolder = Shell32.GetDesktopFolder();
try
{
IntPtr pidlPrintersFolder;
if (Shell32.SHGetFolderLocation(hwndOwner, (int)Shell32.CSIDL.CSIDL_PRINTERS, IntPtr.Zero, 0, out pidlPrintersFolder) == 0)
try
{
StringBuilder strDisplay = new StringBuilder(260);
Guid guidIShellFolder = Shell32.IID_IShellFolder;
IntPtr ptrPrintersShellFolder;
iDesktopFolder.BindToObject(pidlPrintersFolder, IntPtr.Zero, ref guidIShellFolder, out ptrPrintersShellFolder);
Object objPrintersShellFolder = Marshal.GetTypedObjectForIUnknown(ptrPrintersShellFolder, Shell32.ShellFolderType);
try
{
Shell32.IShellFolder printersShellFolder = (Shell32.IShellFolder)objPrintersShellFolder;
IntPtr ptrObjectsList;
printersShellFolder.EnumObjects(hwndOwner, Shell32.ESHCONTF.SHCONTF_NONFOLDERS, out ptrObjectsList);
Object objEnumIDList = Marshal.GetTypedObjectForIUnknown(ptrObjectsList, Shell32.EnumIDListType);
try
{
Shell32.IEnumIDList iEnumIDList = (Shell32.IEnumIDList)objEnumIDList;
IntPtr[] rgelt = new IntPtr[1];
IntPtr pidlPrinter;
int pceltFetched;
Shell32.STRRET ptrString;
while (iEnumIDList.Next(1, rgelt, out pceltFetched) == 0 && pceltFetched == 1)
{
printersShellFolder.GetDisplayNameOf(rgelt[0],
Shell32.ESHGDN.SHGDN_NORMAL, out ptrString);
if (Shell32.StrRetToBuf(ref ptrString, rgelt[0], strDisplay,
(uint)strDisplay.Capacity) == 0)
{
pidlPrinter = Shell32.ILCombine(pidlPrintersFolder, rgelt[0]);
string printerDisplayNameInPrintersFolder = strDisplay.ToString();
Shell32.SHFILEINFO shinfo = new Shell32.SHFILEINFO();
Shell32.SHGetFileInfo(pidlPrinter, 0, out shinfo, (uint)Marshal.SizeOf(shinfo), Shell32.SHGFI.PIDL | Shell32.SHGFI.AddOverlays | Shell32.SHGFI.Icon);
Icon printerIcon = (Icon)Icon.FromHandle(shinfo.hIcon).Clone();
Shell32.DestroyIcon(shinfo.hIcon);
result.Add(printerDisplayNameInPrintersFolder, printerIcon);
}
}
}
finally
{
Marshal.ReleaseComObject(objEnumIDList);
}
}
finally
{
Marshal.ReleaseComObject(objPrintersShellFolder);
}
}
finally
{
Shell32.ILFree(pidlPrintersFolder);
}
}
finally
{
Marshal.ReleaseComObject(iDesktopFolder);
}
return result;
}
}
cuidado, que los nombres de la impresora en el diccionario de resultado serán nombres de impresora muestran en la carpeta de shell Impresoras, y pueden ser diferentes de nombres de impresoras, usados en la clase PrinterSettings (por ejemplo, las impresoras de red en la carpeta de shell de Impresoras pueden mostrarse como "activadas", y la palabra "activada" depende de la localización de Windows y puede no ser el nombre de red de la máquina). Aún no sé cómo obtener el nombre de la impresora "real" de IShellFolder para usarlo con la clase estándar PrinterSettings.
De todos modos, este código carga los iconos del sistema de impresoras, por lo que puede usarlo para su tarea.
UPD: código de clase Shell32, que se utiliza en este código se puede encontrar aquí (demasiado grande para respuesta): http://pastebin.com/thJuWx45
Esta solución parece ser un buen comienzo, puede empezar a jugar con P/Invoca: http: //stackoverflow.com/questions/1063874/winapi-retrieving-icons-of-current-user-printers –