GETJob() Win32 Print spooler api 64bit Параметр неверный, как исправить?

Я пытаюсь заставить работать getJob() из printerspooler api в 64bit.

Я использую следующее определение (как другие люди используют на 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 (4=>8 байт в 64-битной версии) и наоборот 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);
}

edit2

Кажется, не работает, иногда кажется, что он работает, но модульный тест не заметил изменений в файле csproj, поэтому я все еще тестировал 32-битную версию.

добавление следующей строки в csproj делает его работоспособным (он работает в 32-битном режиме, перевод в 64-битный - не работает)

<PlatformTarget>x86</PlatformTarget>

1 ответ

Похоже, это была проблема времени...

Я тестировал на нулевом принтере, так или иначе, на 32-битной версии это в основном работало, но если перейти на 64-битную версию, что-то должно было быть медленнее, поэтому он не работал, то же самое для отладки.

Работа уже была бы помещена в очередь, и поэтому запрос информации о работе больше не доступен.

Чтобы это исправить, вы можете установить: Хранить распечатанные документы.

введите описание изображения здесь

Другие вопросы по тегам