【问题标题】:DeviceCapabilities generates error: data is invalidDeviceCapabilities 产生错误:数据无效
【发布时间】:2015-11-11 03:38:21
【问题描述】:

我想获取打印机的纸张来源、纸张尺寸等列表。 我稍微修改了http://www.pinvoke.net/default.aspx/Enums/DeviceCapabilities.html?diff=y的代码 这些代码有时有效,有时无效。 问题是 DeviceCapabilities(DeviceName, strPort, DeviceCapabilitiesFlags.DC_BINNAMES, (IntPtr)null, (IntPtr)null) 返回-1。最后一个错误是“数据无效” 重新启动计算机可能无法解决问题。一旦遇到问题,下次可能OK,也可能不行。

那么这里的问题是什么?

ArrayList arrBinName;
string sError = "";
GetBins("\\Lindy-PC.MyCpmpany.local\HP LaserJet 4000 Series PCL 5", "LPT1", out arrBinName, out sError);

    public static bool GetBins(string DeviceName, string strPort, out ArrayList BinName, out string strError)
    {
        strError = "";
        BinName = new ArrayList();

        IntPtr pAddr = default(IntPtr);
        int offset = 0;

        int nRes = DeviceCapabilities(DeviceName, strPort, DeviceCapabilitiesFlags.DC_BINNAMES, (IntPtr)null, (IntPtr)null);  //Returns -1
        if (nRes >= 0)
        {
            try
            {
                pAddr = Marshal.AllocHGlobal((int)nRes * 24);
                nRes = DeviceCapabilities(DeviceName, strPort, DeviceCapabilitiesFlags.DC_BINNAMES, pAddr, (IntPtr)null);
                if (nRes < 0)
                {
                    strError = new Win32Exception(Marshal.GetLastWin32Error()).Message + "[" + DeviceName + ": " + strPort + ".DC_BINNAMES]";
                    return false;
                }

                offset = pAddr.ToInt32();
                for (int i = 0; i < nRes; i++)
                {
                    BinName.Add(Marshal.PtrToStringAnsi(new IntPtr(offset + i * 24)));
                }
            }
            finally
            {
                Marshal.FreeHGlobal(pAddr);
            }
        }
        else
            strError = new Win32Exception(Marshal.GetLastWin32Error()).Message + "[" + DeviceName + ": " + strPort + ".DC_BINNAMES]";

        return true;
    }

【问题讨论】:

  • 如果我没记错的话,你调用 DeviceCapabilities 两次。首先获取纸张设置 int nPaperCount = DeviceCapabilities(sPrintName, "LPT1", DC_PAPERS, NULL, DeviceMode);然后再次获取纸张类型 DeviceCapabilities(sPrintName, "LPT1", DC_PAPERS, moPT, &DeviceMode);

标签: c# windows winapi print-spooler-api


【解决方案1】:

正如 aggaton 在他或她的评论中提到的那样,DeviceCapabilities 在某些情况下需要两次调用,而检索 bin 名称就是其中之一。您应该首先阅读DeviceCapabilities 的文档。

然后返回并查看您使用的示例代码。你省略了一个关键步骤:

// BinNames
nRes = DeviceCapabilities(strDeviceName, strPort, DeviceCapabilitiesFlags.DC_BINNAMES, (IntPtr)null, (IntPtr)null);
pAddr = Marshal.AllocHGlobal((int)nRes * 24);
nRes = DeviceCapabilities(strDeviceName, strPort, DeviceCapabilitiesFlags.DC_BINNAMES, pAddr, (IntPtr)null);
if(nRes < 0)
{
    strError = new Win32Exception(Marshal.GetLastWin32Error()).Message + "["+ strDeviceName +": "+ strPort +"]";
    return false;
}

请注意,该代码中有 三个 调用 DeviceCapabilities。你需要这三个。 (我认为通过使每个调用单独的代码行,代码会更清晰,但这是一个样式问题。)DeviceCapabilities 的文档加上上面的示例代码应该让你回到正轨。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-28
    • 2020-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多