【问题标题】:GETJob() Win32 Print spooler api 64bit The parameter is incorrect, how to fix?GETJob() Win32 Print spooler api 64bit 参数不正确,如何解决?
【发布时间】:2019-04-06 13:56:36
【问题描述】:

我正在尝试让getJob() 在 64 位的 printerspooler api 中工作。

我使用以下定义(正如其他人在 SO 上使用的那样)

[DllImport("winspool.drv", EntryPoint = "GetJob", SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
public static extern bool GetJob([In] IntPtr hPrinter, [In] Int32 dwJobId, [In] Int32 Level, [Out] IntPtr lpJob, [In] Int32 cbBuf, ref IntPtr lpbSizeNeeded);

但这仅在我不调试且我不在 64 位时才有效。

在 64 位我得到 windows 错误:参数不正确。

我该如何解决这个问题?

我尝试将 Int32 更改为 IntPtr(64 位中 4=>8 个字节)和相反的 IntPtr => Int32。没用。。

文档在这里:https://docs.microsoft.com/en-us/windows/desktop/printdocs/getjob:

BOOL GetJob(
  _In_  HANDLE  hPrinter,
  _In_  DWORD   JobId,
  _In_  DWORD   Level,
  _Out_ LPBYTE  pJob,
  _In_  DWORD   cbBuf,
  _Out_ LPDWORD pcbNeeded
);

我也尝试将 ref 更改为 out 并将 ref/out 设置为 lpJob 参数,但即使这样似乎也不起作用。

接下来我可以尝试什么?

编辑

似乎可行的是:

[DllImport("winspool.drv", EntryPoint = "GetJob", SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
public static extern bool GetJob([In] IntPtr hPrinter, [In] Int32 dwJobId, [In] Int32 Level, [Out] byte[] lpJob, [In] Int32 cbBuf, ref Int32 lpbSizeNeeded);

并按如下方式使用它:

public JOB_INFO_1(IntPtr hPrinter, Int32 dwJobId)
{
  var BytesWritten = new Int32();
  var ptBuf = new byte[0];


  if (PrinterMonitorComponent.ComponentTraceSwitch.TraceVerbose)
    Console.WriteLine("JOB_INFO_1 new(" + hPrinter.ToString() + "," + dwJobId.ToString() + ")");


  // \\ Get the required buffer size
  if (!UnsafeNativeMethods.GetJob(hPrinter, dwJobId, 1, ptBuf, 0, ref BytesWritten))
  {
    if (BytesWritten == 0)
    {
      var ex = new Win32Exception();
      if (PrinterMonitorComponent.ComponentTraceSwitch.TraceError)
        Console.WriteLine("{0} GetJob for JOB_INFO_1 failed on handle: {1} for job: {2} - {3}", this.GetType().ToString(), hPrinter, dwJobId, ex.Message);
      throw ex;
    }
  }

  // \\ Allocate a buffer the right size
  if (BytesWritten > 0)
    ptBuf = new byte[BytesWritten]; // Marshal.AllocHGlobal(BytesWritten);

  //Console.WriteLine($"Buffer {BytesWritten} x"); // uncommenting this code somehow breaks it again -.-
  // \\ Populate the JOB_INFO_1 structure
  if (!UnsafeNativeMethods.GetJob(hPrinter, dwJobId, 1, ptBuf, BytesWritten, ref BytesWritten))
  {
    if (PrinterMonitorComponent.ComponentTraceSwitch.TraceError)
      Console.WriteLine("GetJob for JOB_INFO_1 failed on handle: " + hPrinter.ToString() + " for job: " + dwJobId, this.GetType().ToString());
    throw new Win32Exception();
  }
  else
  {
    GCHandle handle = GCHandle.Alloc(ptBuf, GCHandleType.Pinned);
    Marshal.PtrToStructure(handle.AddrOfPinnedObject(), this);
    handle.Free();
    //Marshal.PtrToStructure(ptBuf, this);

  }

  // \\ Free the allocated memory
  //Marshal.FreeHGlobal(ptBuf);
}

编辑2

似乎不起作用,有时它似乎起作用,但单元测试没有注意到 csproj 文件的变化,所以我最终还是针对 32 位进行测试。

在 csproj 中添加以下行使其工作(它在 32 位运行,将其置于 64 位,它会失败)

<PlatformTarget>x86</PlatformTarget>

【问题讨论】:

  • 所有DWORDs 应该是Int32UInt32(通常无关紧要)。最后,LPDWORD,应该是ref Int32ref UInt32。我认为pJob 参数应该可以像你现在一样是[Out] IntPtr,或者[Out] byte[](也可以在没有[Out] 属性的情况下尝试它们)
  • @VisualVincent 将 pcbNeeded 更改为 ref int32 不起作用。我担心文档可能不正确,在获取打印机通知时遇到相同类型的问题(文档不正确)。
  • 好吧,我怀疑最后一个参数是他发出的,但ref (U)Int32 是它的正确声明。试试我的pJob 建议,不管有没有[Out]。 -- 顺便说一句,我发现了这个 API 的托管版本:docs.microsoft.com/en-us/dotnet/api/…
  • 您收到的确切(完整)错误消息是什么?您能否在您的问题中分享它以及可验证的代码示例?
  • 笨拙的 LPBYTE 参数在 C 语言中是必需的,因为该函数可以返回不同的结构。你在 C# 中根本没有这个限制,它支持方法重载。因此,尽可能多地声明,现在使用ref JobInfo1,其中 JobInfo1 是您对 JOB_INFO_1 结构的声明。等等。

标签: c# 64-bit print-spooler-api


【解决方案1】:

这似乎主要是时间问题......

我正在使用空打印机进行测试,不知何故,它在 32 位中大部分都可以工作,但与转到 64 位相比,某些东西一定会变得更慢,这就是它会失败的原因,调试也是如此。

该作业已经被假脱机,因此请求该作业信息不再可用。

要解决此问题,您可以设置:保留打印的文档

【讨论】:

  • 或暂停作业或队列。
  • @NickWestgate 我只是想确保作业已假脱机并打印没有错误,最好的方法是什么?
  • 如果“保留打印的文档”对您有用,那么坚持下去。否则你必须使用FindFirstPrinterChangeNotification etc to watch for job status printed
  • @NickWestgate 我正在使用它,但似乎没有给我足够的信息消息。当我想知道信息时,我得到了工作信息,但工作已经消失了。
  • 我的答案链接到几个例子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-22
相关资源
最近更新 更多