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-битную версию, что-то должно было быть медленнее, поэтому он не работал, то же самое для отладки.
Работа уже была бы помещена в очередь, и поэтому запрос информации о работе больше не доступен.
Чтобы это исправить, вы можете установить: Хранить распечатанные документы.