2015-09-29 101 views
1

我正在使用代碼獲取系統打印機圖標(我發現的唯一方法 - 就是使用IShellFolder),現在我想將它們與InstalledPrinters連接,但問題是 - 我無法找到找到真正的打印機名稱的方法(例如「\ ServerName \ PrinterName」),與顯示「設備和打印機」shell文件夾內容的名稱不同,並且只適用於PrinterSettings。如何從設備和打印機IShellFolder獲取打印機名稱?

的代碼我有使用以檢索打印機的圖標和打印機標題中的「設備和打印機」文件夾殼:

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(如「\服務器\ PrinterName的」網絡打印機)發送打印機名稱以IShellFolder.ParseDisplayName PARAM pszDisplayName,的IShellFolder「設備和打印機「與這個井一起工作。因此,在此之後,我們可以枚舉真實的打印機名稱(「\ ServerName \ PrinterName」),打印機顯示名稱(在「設備和打印機」中列出的打印機上的「PrinterName on ServerName」)和打印機圖標。

我將在這裏發佈完整的代碼,以便在進行一些編輯後進行父級搜索。

+0

我很好奇你結束了什麼。我有同樣的需要。 – jnm2

1

在循環,可以在當前rgelt[0]使用printersShellFolder.GetUIObjectOfIID_IDataObject"PrinterFriendlyName"調用IDataObject::GetData作爲剪貼板格式才能獲得真正的打印機名稱(STGMEDIUM編碼)。

您可以在當前pidl上使用printersShellFolder.GetUIObjectOf代替IID_IQueryInfo以獲取打印機狀態。

相關問題