2015-09-29 5 views
1

Я получаю значки системных принтеров с помощью кода (только для того, чтобы найти IShellFolder), теперь я хочу подключить их к InstalledPrinters, но проблема в том, что я не могу найти способ найти настоящее имя принтера (например, «\ ServerName \ PrinterName»), отличается от отображаемого имени содержимого папки «Устройства и принтеры» и только корректно используется с PrinterSettings.Как я могу получить имя принтера с устройства и принтеров IShellFolder?

код я должен использовать для retrive иконки принтера и подписи принтера в папке «Устройства и принтеры» оболочки:

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 printerDisplayName = strDisplay.ToString(); 

           Shell32.SHFILEINFO shinfo = new Shell32.SHFILEINFO(); 
           Shell32.SHGetFileInfo(this._pidl, 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); 

           // HOW TO GET PRINTER NAME (\\ServerName\printername) WITH IS DIFFERENT FROM A PRINTER NAME IN "DEVICES AND PRINTERS" SYSTEM FOLDER 
          } 
         } 
        } 
        finally 
        { 
         Marshal.ReleaseComObject(objEnumIDList); 
        } 
       } 
       finally 
       { 
        Marshal.ReleaseComObject(objPrintersShellFolder); 
       } 
      } 
      finally 
      { 
       Shell32.ILFree(pidlPrintersFolder); 
      } 
    } 
    finally 
    { 
     Marshal.ReleaseComObject(iDesktopFolder); 
    } 

спасибо за любую помощь.

ответ

1

Найти ответ самостоятельно.

Для перечисления принтеров в IShellFolder мы должны использовать метод IShellFolder.ParseDisplayName, не EnumObjects, и отправить имя принтера из PrinterSettings.IntalledPrinters (например, «\ ServerName \ ИмяПринтер» для сетевых принтеров) к IShellFolder.ParseDisplayName паров pszDisplayName, IShellFolder " Устройства и принтеры работают с этой скважиной.

Итак, после этого мы можем перечислить имена реальных принтеров («\ имя_сервера \ имя_принтера»), имена дисплеев принтера («имя_сервера на имя сервера» в качестве принтеров, перечисленных в «Устройствах и принтерах») и значки принтера.

Я отправлю полный код здесь для поиска отца после некоторых изменений.

+0

Мне любопытно, в чем вы оказались. У меня такая же потребность. – jnm2

1

В цикле можно использовать printersShellFolder.GetUIObjectOf для IID_IDataObject на текущий rgelt[0] и вызвать IDataObject::GetData с "PrinterFriendlyName" как формат буфера обмена, чтобы получить реальное имя принтера (закодированный в STGMEDIUM).

Вы можете использовать printersShellFolder.GetUIObjectOf для IID_IQueryInfo на текущем pidl, чтобы получить статус принтера.