如何从设备和打印机 IShellFolder 获取打印机名称?
How I can get printer name from device and printers IShellFolder?
我正在使用代码获取系统打印机图标(我找到的唯一方法是使用 IShellFolder ),现在我想将它们与 InstalledPrinters 连接,但问题是 - 我找不到找到真实打印机名称的方法(例如“\ServerName\PrinterName”),与 "Devices and printers" shell 文件夹内容的显示名称不同,只有与 PrinterSettings 一起使用才正确。
我用来在 "Devices and printers" shell 文件夹中检索打印机图标和打印机标题的代码:
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);
}
感谢您的帮助。
自己找答案
要枚举 IShellFolder 中的打印机,我们必须使用 IShellFolder.ParseDisplayName 方法,而不是 EnumObjects,并将打印机名称从 PrinterSettings.IntalledPrinters(例如网络打印机的“\ServerName\PrinterName”)发送到 IShellFolder.ParseDisplayName param pszDisplayName, IShellFolder "Devices and printers" 使用这个很好。
因此,在此之后我们可以枚举真实的打印机名称(“\ServerName\PrinterName”)、打印机显示名称("PrinterName on ServerName" 作为 "Devices and printers" 中列出的打印机)和打印机图标。
我会 post 完整的代码在这里进行一些编辑后供父亲搜索。
在循环中,您可以在当前 rgelt[0]
上对 IID_IDataObject
使用 printersShellFolder.GetUIObjectOf
,并使用 "PrinterFriendlyName"
作为剪贴板格式调用 IDataObject::GetData
以获得真正的打印机名称(编码为 STGMEDIUM
)。
您也可以在当前 pidl 上使用 printersShellFolder.GetUIObjectOf
for IID_IQueryInfo
来获取打印机状态。
我正在使用代码获取系统打印机图标(我找到的唯一方法是使用 IShellFolder ),现在我想将它们与 InstalledPrinters 连接,但问题是 - 我找不到找到真实打印机名称的方法(例如“\ServerName\PrinterName”),与 "Devices and printers" shell 文件夹内容的显示名称不同,只有与 PrinterSettings 一起使用才正确。
我用来在 "Devices and printers" shell 文件夹中检索打印机图标和打印机标题的代码:
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);
}
感谢您的帮助。
自己找答案
要枚举 IShellFolder 中的打印机,我们必须使用 IShellFolder.ParseDisplayName 方法,而不是 EnumObjects,并将打印机名称从 PrinterSettings.IntalledPrinters(例如网络打印机的“\ServerName\PrinterName”)发送到 IShellFolder.ParseDisplayName param pszDisplayName, IShellFolder "Devices and printers" 使用这个很好。
因此,在此之后我们可以枚举真实的打印机名称(“\ServerName\PrinterName”)、打印机显示名称("PrinterName on ServerName" 作为 "Devices and printers" 中列出的打印机)和打印机图标。
我会 post 完整的代码在这里进行一些编辑后供父亲搜索。
在循环中,您可以在当前 rgelt[0]
上对 IID_IDataObject
使用 printersShellFolder.GetUIObjectOf
,并使用 "PrinterFriendlyName"
作为剪贴板格式调用 IDataObject::GetData
以获得真正的打印机名称(编码为 STGMEDIUM
)。
您也可以在当前 pidl 上使用 printersShellFolder.GetUIObjectOf
for IID_IQueryInfo
来获取打印机状态。