Hi.

Does anyone know how I can create a new printer port in C#? At the moment I've got this, which uses WMI (System.Management):

ManagementClass portClass = new ManagementClass("Win32_TCPIPPrinterPort");
            ManagementObject portObject = portClass.CreateInstance();

            portObject["Name"] = portName;
            portObject["HostAddress"] = "174.30.164.15";
            portObject["PortNumber"] = portNumber;
            portObject["Protocol"] = 1;
            portObject["SNMPCommunity"] = "public";
            portObject["SNMPEnabled"] = true;
            portObject["SNMPDevIndex"] = 1;

            PutOptions options = new PutOptions();
            options.Type = PutType.UpdateOrCreate;
            //put a newly created object to WMI objects set             
            portObject.Put(options);

This code works fine, but it creates a TCP/IP printer port. I need to create a printer port of any given existing type (more specifically, I need to create a redirected port, a port type which is created by RedMon).
Is it possible to write a method of the form

void AddPrinterPort(string portName,string portType)

which adds a new printer port with the name portName and the port type with the name portType, assuming that such a port type exists?

For the record, here it is:

First we marshal in the necessary functions from winspool.drv. Here are the structures that we need:

private const int MAX_PORTNAME_LEN = 64;
        private const int MAX_NETWORKNAME_LEN = 49;
        private const int MAX_SNMP_COMMUNITY_STR_LEN = 33;
        private const int MAX_QUEUENAME_LEN = 33;
        private const int MAX_IPADDR_STR_LEN = 16;
        private const int RESERVED_BYTE_ARRAY_SIZE = 540;
        
        private enum PrinterAccess
        {
            ServerAdmin=0x01,
            ServerEnum=0x02,
            PrinterAdmin=0x04,
            PrinterUse=0x08,
            JobAdmin=0x10,
            JobRead=0x20,
            StandardRightsRequired=0x000f0000,
            PrinterAllAccess=(StandardRightsRequired | PrinterAdmin | PrinterUse)
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct PrinterDefaults
        {
            public IntPtr pDataType;
            public IntPtr pDevMode;
            public PrinterAccess DesiredAccess;
        }

        [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]
        private struct PortData
        {
            [MarshalAs(UnmanagedType.ByValTStr,SizeConst=MAX_PORTNAME_LEN)]
            public string sztPortName;
            public UInt32 dwVersion;
            public UInt32 dwProtocol;
            public UInt32 cbSize;
            public UInt32 dwReserved;
            [MarshalAs(UnmanagedType.ByValTStr,SizeConst=MAX_NETWORKNAME_LEN)]
            public string sztHostAddress;
            [MarshalAs(UnmanagedType.ByValTStr,SizeConst=MAX_SNMP_COMMUNITY_STR_LEN)]
            public string sztSNMPCommunity;
            public UInt32 dwDoubleSpool;
            [MarshalAs(UnmanagedType.ByValTStr,SizeConst=MAX_QUEUENAME_LEN)]
            public string sztQueue;
            [MarshalAs(UnmanagedType.ByValTStr,SizeConst=MAX_IPADDR_STR_LEN)]
            public string sztIPAddress;
            [MarshalAs(UnmanagedType.ByValArray,SizeConst=RESERVED_BYTE_ARRAY_SIZE)]
            public byte[] Reserved;
            public UInt32 dwPortNumber;
            public UInt32 dwSNMPEnabled;
            public UInt32 dwSNMPDevIndex;
        }

And here are the declarations of the Windows API functions that we'll need:

[DllImport("winspool.drv")]
        private static extern bool OpenPrinter(string printerName,out IntPtr phPrinter,ref PrinterDefaults printerDefaults);

        [DllImport("winspool.drv")]
        private static extern bool ClosePrinter(IntPtr phPrinter);

        [DllImport("winspool.drv",CharSet=CharSet.Unicode)]
        private static extern bool XcvDataW(IntPtr hXcv,string pszDataName,IntPtr pInputData,UInt32 cbInputData,out IntPtr pOutputData,UInt32 cbOutputData,out UInt32 pcbOutputNeeded,out UInt32 pdwStatus);

And here is the function which adds the monitor port:

/**
         * <summary>Adds a monitor printer port with the given name and type.</summary>
         * <param name="portName">The name of the new port (must end with ':').</param>
         * <param name="portType">The type of the new port (ex. "Redirected Port").</param>
         */
        public static void AddMonitorPrinterPort(string portName,string portType)
        {
            IntPtr printerHandle;
            PrinterDefaults defaults = new PrinterDefaults { DesiredAccess = PrinterAccess.ServerAdmin };
            if (! OpenPrinter(",XcvMonitor "+portType,out printerHandle,ref defaults))
                throw new Exception("Could not open printer for the monitor port "+portType+"!");
            try
            {
                PortData portData = new PortData
                {
                    dwVersion = 1,
                    dwProtocol = 1, // 1 = RAW, 2 = LPR
                    dwPortNumber = 9100, // 9100 = default port for RAW, 515 for LPR
                    dwReserved = 0,
                    sztPortName = portName,
                    sztIPAddress = "172.30.164.15",
                    sztSNMPCommunity = "public",
                    dwSNMPEnabled = 1,
                    dwSNMPDevIndex = 1
                };
                uint size = (uint) Marshal.SizeOf(portData);
                portData.cbSize = size;
                IntPtr pointer = Marshal.AllocHGlobal((int) size);
                Marshal.StructureToPtr(portData,pointer,true);
                IntPtr outputData;
                UInt32 outputNeeded,status;
                try
                {
                    if (! XcvDataW(printerHandle,"AddPort",pointer,size,out outputData,0,out outputNeeded,out status))
                        throw new PrinterPortException("Could not add port (error code "+status+")!");
                }
                finally
                {
                    Marshal.FreeHGlobal(pointer);
                }
            }
            finally
            {
                ClosePrinter(printerHandle);
            }
        }

Hi.

Does anyone know how I can create a new printer port in C#? At the moment I've got this, which uses WMI (System.Management):

ManagementClass portClass = new ManagementClass("Win32_TCPIPPrinterPort");
            ManagementObject portObject = portClass.CreateInstance();

            portObject["Name"] = portName;
            portObject["HostAddress"] = "174.30.164.15";
            portObject["PortNumber"] = portNumber;
            portObject["Protocol"] = 1;
            portObject["SNMPCommunity"] = "public";
            portObject["SNMPEnabled"] = true;
            portObject["SNMPDevIndex"] = 1;

            PutOptions options = new PutOptions();
            options.Type = PutType.UpdateOrCreate;
            //put a newly created object to WMI objects set             
            portObject.Put(options);

This code works fine, but it creates a TCP/IP printer port. I need to create a printer port of any given existing type (more specifically, I need to create a redirected port, a port type which is created by RedMon).
Is it possible to write a method of the form

void AddPrinterPort(string portName,string portType)

which adds a new printer port with the name portName and the port type with the name portType, assuming that such a port type exists?

Hi,

Thank you for this post. Is this to create a RedMon like port redirector or just is it just to create a new port and use Redmon?

This article has been dead for over six months. Start a new discussion instead.