从打印机本地端口获取数据

get data from printer local port

我用一些示例代码做了一个虚拟打印机。但是我不知道如何在它开始打印时从中获取数据。

当它开始打印时它给出打印错误的通知。 为什么有“C:/MyLocalPort.txt”.

任何人都可以帮助我获取此虚拟打印机设置为打印的数据。

示例代码如下:

using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Management;

namespace virtualPrinter
{
    public static class PrinterClass // class which carries SetDefaultPrinter function
    {
        [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool SetDefaultPrinter(string Printer);
    }

    class myPrinterClass
    {
       public static void getPrinterNames()
        {
            foreach (string printer in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
            {
                MessageBox.Show(printer);
            }
        }
        public static void installPrinter(string printerName) //works on win 7,8,8.1,10 on both x84 and x64
        {
            Winspool.AddLocalPort(@"C:\MyLocalPort.txt");

            //https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/rundll32-printui
            //  /if         Installs a printer by using an .inf file.
            //  /b[name]    Specifies the base printer name.
            //  /@[file]    Specifies a command-line argument file and directly inserts the text in that file into the command line.
            //  /f[file]    Species the Universal Naming Convention (UNC) path and name of the .inf file name or the output file name, depending on the task that you are performing. Use /F[file] to specify a dependent .inf file.
            //  /r[port]    Specifies the port name.
            //  /m[model]   Specifies the driver model name. (This value can be specified in the .inf file.)

            string arg;
            arg = "printui.dll , PrintUIEntry /if /b " + "\"" + printerName + "\"" + @" /f C:\Windows\inf\ntprint.inf /r " + "\"" + @"C:\MyLocalPort.txt" + "\"" + " /m " + "\"" + "Generic / Text Only" + "\""; //initial arg
            ProcessStartInfo p = new ProcessStartInfo();
            p.FileName = "rundll32.exe";
            p.Arguments = arg;
            p.WindowStyle = ProcessWindowStyle.Hidden;

            try
            {
                Process.Start(p);
                MessageBox.Show(printerName + " installed succesfully!");
            }

            catch (Exception ex)
            {
                MessageBox.Show("Something went wrong. Try again!" );
            }
        }
        public static bool printerExists(string printerName)
        {
            bool res = false;
            foreach (string printer in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
            {
                if (printer == printerName)
                {
                    res = true;
                }
            }
            return res;
        }
        public static void uninstallPrinter(string printerName)
        {
            string arg;
            ProcessStartInfo p = new ProcessStartInfo();
            arg = "printui.dll, PrintUIEntry /dl /n " + "\"" + printerName + "\"";
            if (printerExists(printerName))
            {
                p.FileName = "rundll32.exe";
                p.Arguments = arg;
                p.WindowStyle = ProcessWindowStyle.Hidden;
                try
                {
                    Process.Start(p);
                    MessageBox.Show(printerName + " unistalled successfully");
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.InnerException.ToString());
                }
                p = null;
            }
        }
       
        public static string GetLocalIPAddress() //erxomeno feature
        {
            var host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (var ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    return ip.ToString();
                }
            }
            throw new Exception("No network adapters with an IPv4 address in the system!");
        }

        public static class Winspool
        {
            [StructLayout(LayoutKind.Sequential)]
            private class PRINTER_DEFAULTS
            {
                public string pDatatype;
                public IntPtr pDevMode;
                public int DesiredAccess;
            }

            [DllImport("winspool.drv", EntryPoint = "XcvDataW", SetLastError = true)]
            private static extern bool XcvData(
                IntPtr hXcv,
                [MarshalAs(UnmanagedType.LPWStr)] string pszDataName,
                IntPtr pInputData,
                uint cbInputData,
                IntPtr pOutputData,
                uint cbOutputData,
                out uint pcbOutputNeeded,
                out uint pwdStatus);

            [DllImport("winspool.drv", EntryPoint = "OpenPrinterA", SetLastError = true)]
            private static extern int OpenPrinter(
                string pPrinterName,
                ref IntPtr phPrinter,
                PRINTER_DEFAULTS pDefault);

            [DllImport("winspool.drv", EntryPoint = "ClosePrinter")]
            private static extern int ClosePrinter(IntPtr hPrinter);

            public static int AddLocalPort(string portName)
            {
                PRINTER_DEFAULTS def = new PRINTER_DEFAULTS();

                def.pDatatype = null;
                def.pDevMode = IntPtr.Zero;
                def.DesiredAccess = 1; //Server Access Administer

                IntPtr hPrinter = IntPtr.Zero;

                int n = OpenPrinter(",XcvMonitor Local Port", ref hPrinter, def);
                if (n == 0)
                    return Marshal.GetLastWin32Error();

                if (!portName.EndsWith("[=10=]"))
                    portName += "[=10=]"; // Must be a null terminated string

                // Must get the size in bytes. Rememeber .NET strings are formed by 2-byte characters
                uint size = (uint)(portName.Length * 2);

                // Alloc memory in HGlobal to set the portName
                IntPtr portPtr = Marshal.AllocHGlobal((int)size);
                Marshal.Copy(portName.ToCharArray(), 0, portPtr, portName.Length);

                uint needed; // Not that needed in fact...
                uint xcvResult; // Will receive de result here

                XcvData(hPrinter, "AddPort", portPtr, size, IntPtr.Zero, 0, out needed, out xcvResult);

                ClosePrinter(hPrinter);
                Marshal.FreeHGlobal(portPtr);

                return (int)xcvResult;
            }
        }

    }
}


好的,我不能那样做。 首先,我必须创建一个我用过的端口监视器 mfilemon.dll 然后我用那个端口监视器创建了一个端口 然后将所有驱动程序文件粘贴到系统驱动程序字典中。 然后最后添加打印机并完成。 你可以参考这个 https://github.com/Gohulan/Virtual-Printer/blob/main/PrinterSetup/SpoolerHelper.cs 这包含创建虚拟打印机以打印到 pdf 虚拟打印机的所有步骤