本文介绍了如何获取 LAN 中打印机连接的计算机名称和 IP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在局域网中通常打印机是共享的,我们可以通过Windows添加远程打印机"将局域网中的这些共享计算机添加到我们的机器中.我想像这样获取添加的打印机列表,并通过 C# 获取在线状态和打印机设置.添加的打印机列表可以通过

In a LAN normally printers are shared, and we can add these shared computers in the LAN to our machine through Windows "Add Remote Printer". I want to get the list of added printer like this, and there online status and printer settings through C#. The list of added printers could be obtained by

System.Drawing.Printing.PrinterSettings.InstalledPrinters

通过此代码,我可以获得添加到组合框的打印机列表.问题是如何通过 c# 代码获取每台打印机的在线状态,以及其他可能的设置.请帮忙.

through this code I can get the list of added printers to a combobox. The problem is how can I get the online status of each printer, and there other possible settings through the c# code. Please help.

推荐答案

作为 WMI 的替代方案,您可以使用 Print Spooler API 以收集有关打印机的详细信息.API 的大部分 P/Invoke 签名可在 http://www.pinvoke.net 上获得.

As an alternative to WMI, you can use the Print Spooler API to gather detailed information about the printers. Most of the P/Invoke signatures for the API are available on http://www.pinvoke.net.

打开打印机的句柄:http://www.pinvoke.net/default.aspx/winspool.OpenPrinter

收集打印机信息:http://www.pinvoke.net/default.aspx/winspool.GetPrinterData

快速拼凑出您可以根据请求从 PrintSpoolerApi 收集的内容的示例.

Quickly smashed together an example of what you can gather from the PrintSpoolerApi as per request.

PrintSpoolerAPI 示例:

PrintSpoolerAPIExample:

创建新的控制台项目并将 Program.cs 中的所有代码替换为此(.NET 3.5 及更高版本,由于类型推断),机器(本地或网络)上可用的每台打印机的打印机详细信息将打印到安慰.状态值是您感兴趣的值.就绪"的状态代码是 0,通过禁用打印机和禁用与联网打印机的网络连接来查看状态变化来搞砸.

Create new console project and replace all code in Program.cs with this (.NET 3.5 and above, due to type inference), the printer details of each printer available on the machine (local or networked) will be printed to the console. The status value is what you are interested in. The status code for "Ready" is 0, mess around by disabling printers and disabling your network connection to networked printers to see the status change.

using System;
using System.Collections;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;

namespace PrintSpoolerAPIExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var printers = System.Drawing.Printing.PrinterSettings.InstalledPrinters as IEnumerable;

            foreach (string printer in printers)
            {
                var printerInfo = PrintSpoolerApi.GetPrinterProperty(printer);
                StringBuilder sb = new StringBuilder();
                sb.AppendLine(string.Format("ServerName:{0}", printerInfo.ServerName));
                sb.AppendLine(string.Format("PrinterName:{0}", printerInfo.PrinterName));
                sb.AppendLine(string.Format("ShareName:{0}", printerInfo.ShareName));
                sb.AppendLine(string.Format("PortName:{0}", printerInfo.PortName));
                sb.AppendLine(string.Format("DriverName:{0}", printerInfo.DriverName));
                sb.AppendLine(string.Format("Comment:{0}", printerInfo.Comment));
                sb.AppendLine(string.Format("Location:{0}", printerInfo.Location));
                sb.AppendLine(string.Format("DevMode:{0}", printerInfo.DevMode));
                sb.AppendLine(string.Format("SepFile:{0}", printerInfo.SepFile));
                sb.AppendLine(string.Format("PrintProcessor:{0}", printerInfo.PrintProcessor));
                sb.AppendLine(string.Format("Datatype:{0}", printerInfo.Datatype));
                sb.AppendLine(string.Format("Parameters:{0}", printerInfo.Parameters));
                sb.AppendLine(string.Format("Attributes:{0}", printerInfo.Attributes));
                sb.AppendLine(string.Format("Priority:{0}", printerInfo.Priority));
                sb.AppendLine(string.Format("DefaultPriority:{0}", printerInfo.DefaultPriority));
                sb.AppendLine(string.Format("StartTime:{0}", printerInfo.StartTime));
                sb.AppendLine(string.Format("UntilTime:{0}", printerInfo.UntilTime));
                sb.AppendLine(string.Format("Status:{0}", printerInfo.Status));
                sb.AppendLine(string.Format("Jobs:{0}", printerInfo.Jobs));
                sb.AppendLine(string.Format("AveragePpm:{0}", printerInfo.AveragePpm));
                Console.WriteLine(sb.ToString());
            }

            Console.ReadLine();
        }
    }

    class PrintSpoolerApi
    {
        [DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool OpenPrinter(
            [MarshalAs(UnmanagedType.LPTStr)]
            string printerName,
            out IntPtr printerHandle,
            PrinterDefaults printerDefaults);

        [DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool GetPrinter(
            IntPtr printerHandle,
            int level,
            IntPtr printerData,
            int bufferSize,
            ref int printerDataSize);

        [DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool ClosePrinter(
            IntPtr printerHandle);

        [StructLayout(LayoutKind.Sequential)]
        public struct PrinterDefaults
        {
            public IntPtr pDatatype;
            public IntPtr pDevMode;
            public int DesiredAccess;
        }

        public enum PrinterProperty
        {
            ServerName,
            PrinterName,
            ShareName,
            PortName,
            DriverName,
            Comment,
            Location,
            PrintProcessor,
            Datatype,
            Parameters,
            Attributes,
            Priority,
            DefaultPriority,
            StartTime,
            UntilTime,
            Status,
            Jobs,
            AveragePpm
        };

        public struct PrinterInfo2
        {
            [MarshalAs(UnmanagedType.LPTStr)]
            public string ServerName;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string PrinterName;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string ShareName;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string PortName;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string DriverName;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string Comment;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string Location;
            public IntPtr DevMode;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string SepFile;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string PrintProcessor;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string Datatype;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string Parameters;
            public IntPtr SecurityDescriptor;
            public uint Attributes;
            public uint Priority;
            public uint DefaultPriority;
            public uint StartTime;
            public uint UntilTime;
            public uint Status;
            public uint Jobs;
            public uint AveragePpm;
        }

        public static PrinterInfo2 GetPrinterProperty(string printerUncName)
        {
            var printerInfo2 = new PrinterInfo2();

            var pHandle = new IntPtr();
            var defaults = new PrinterDefaults();
            try
            {
                //Open a handle to the printer
                bool ok = OpenPrinter(printerUncName, out pHandle, defaults);

                if (!ok)
                {
                    //OpenPrinter failed, get the last known error and thrown it
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                //Here we determine the size of the data we to be returned
                //Passing in 0 for the size will force the function to return the size of the data requested
                int actualDataSize = 0;
                GetPrinter(pHandle, 2, IntPtr.Zero, 0, ref actualDataSize);

                int err = Marshal.GetLastWin32Error();

                if (err == 122)
                {
                    if (actualDataSize > 0)
                    {
                        //Allocate memory to the size of the data requested
                        IntPtr printerData = Marshal.AllocHGlobal(actualDataSize);
                        //Retrieve the actual information this time
                        GetPrinter(pHandle, 2, printerData, actualDataSize, ref actualDataSize);

                        //Marshal to our structure
                        printerInfo2 = (PrinterInfo2)Marshal.PtrToStructure(printerData, typeof(PrinterInfo2));
                        //We've made the conversion, now free up that memory
                        Marshal.FreeHGlobal(printerData);
                    }
                }
                else
                {
                    throw new Win32Exception(err);
                }

                return printerInfo2;
            }
            finally
            {
                //Always close the handle to the printer
                ClosePrinter(pHandle);
            }
        }
    }
}

如果需要,您可以从 API 中检索更多详细信息.

You can retrieve even more details from the API, if required.

这篇关于如何获取 LAN 中打印机连接的计算机名称和 IP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 02:20
查看更多