65.9K
CodeProject 正在变化。 阅读更多。
Home

通过 XcvData 和 C# 添加本地端口

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (8投票s)

2010 年 7 月 9 日

CPOL
viewsIcon

35292

你知道什么是“万能函数”吗? 如果你不知道,我就告诉你:绝对是一场灾难。 Winspool 的 XcvData 函数就是这方面的典型例子:它可以用于许多不同的事情,而且文档记录非常糟糕,以至于使用它会变得非常痛苦。 我只想添加一个本地端口……如果你想这样做,也许你愿意尝试这种方法
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("\0"))
            portName += "\0"; // 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;
    }
}
我想这可能会为一些人节省很多时间。 使用这个类,你只需要调用 AddLocalPort 方法,传递你想要端口的名称。 它将返回一个系统错误代码(0 表示 ERROR_SUCCESS)。 期待与你分享…
© . All rights reserved.