如何使用 ReadPrinter 方法读取打印作业内容
How to read print job content using ReadPrinter method
我想获取要打印的文档的内容。
Google 表示唯一的方法是使用 WinAPI 方法 ReadPrinter()。
我已经实现了草图,但无法正常工作。
麻烦是 ReadPrinter() 方法总是 returns 什么都没有。
有什么问题请指教
下面的简化代码:
string printerName = "Microsoft XPS Document Writer";
const uint firstJob = 0u;
const uint noJobs = 10u;
const uint level = 1u;
uint bytesNeeded;
uint returned;
uint bytesCopied;
uint structsCopied;
// Open printer
IntPtr printerHandle = OpenPrinterW(printerName.Normalize(), out printerHandle, IntPtr.Zero);
// Get byte size required for a data
EnumJobsW(printerHandle, firstJob, noJobs, level, IntPtr.Zero, 0, out bytesNeeded, out returned);
// Now we know how much memory we need to read the data (bytesNeeded value)
IntPtr pJob = Marshal.AllocHGlobal((int)bytesNeeded);
// Read the data
EnumJobsW(printerHandle, firstJob, noJobs, level, pJob, bytesNeeded, out bytesCopied, out structsCopied);
// Convert pJob to jobInfos
JOB_INFO_1W[] jobInfos = null;
// ... actual convert code missed ...
// Iterate through the jobs and try to get their content
foreach (JOB_INFO_1W jobInfo in jobInfos)
{
// Open print job
string printJobName = string.Format("{0}, Job {1}", printerName, jobInfo.JobId);
IntPtr printJobHandle;
OpenPrinterW(printJobName.Normalize(), out printJobHandle, IntPtr.Zero);
// Read print job
const int printJobBufLen = 1024;
StringBuilder printJobSb = new StringBuilder(printJobBufLen);
int printJobBytesRead = 0;
while (printJobBytesRead == 0)
{
ReadPrinter(printJobHandle, printJobSb, printJobBufLen, out printJobBytesRead);
// !!! printJobBytesRead is 0 and printJobSb is empty
}
// Close print job
ClosePrinter(printJobHandle);
}
// Close printer
ClosePrinter(printerHandle);
P/Invoke 签名:
[DllImport("winspool.drv", EntryPoint = "OpenPrinterW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern int OpenPrinterW(
[In] string pPrinterName,
[Out] out IntPtr phPrinter,
[In] IntPtr pDefault);
[DllImport("spoolss.dll", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern int ClosePrinter(
[In] IntPtr hPrinter);
[DllImport("winspool.drv", EntryPoint = "EnumJobsW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern int EnumJobsW(
[In] IntPtr hPrinter,
[In] uint FirstJob,
[In] uint NoJobs,
[In] uint Level,
[Out] IntPtr pJob,
[In] uint cbBuf,
[Out] out uint pcbNeeded,
[Out] out uint pcReturned);
[DllImport("spoolss.dll", EntryPoint = "ReadPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern int ReadPrinter(
[In] IntPtr hPrinter,
[Out] StringBuilder data,
[In] Int32 cbBuf,
[Out] out Int32 pNoBytesRead);
此代码是否在 driver's Print Processor component 中?如果没有,我认为它不会起作用。
所以您要么使用打印驱动程序组件,要么从磁盘上的假脱机文件中读取。
我想获取要打印的文档的内容。 Google 表示唯一的方法是使用 WinAPI 方法 ReadPrinter()。 我已经实现了草图,但无法正常工作。 麻烦是 ReadPrinter() 方法总是 returns 什么都没有。
有什么问题请指教
下面的简化代码:
string printerName = "Microsoft XPS Document Writer";
const uint firstJob = 0u;
const uint noJobs = 10u;
const uint level = 1u;
uint bytesNeeded;
uint returned;
uint bytesCopied;
uint structsCopied;
// Open printer
IntPtr printerHandle = OpenPrinterW(printerName.Normalize(), out printerHandle, IntPtr.Zero);
// Get byte size required for a data
EnumJobsW(printerHandle, firstJob, noJobs, level, IntPtr.Zero, 0, out bytesNeeded, out returned);
// Now we know how much memory we need to read the data (bytesNeeded value)
IntPtr pJob = Marshal.AllocHGlobal((int)bytesNeeded);
// Read the data
EnumJobsW(printerHandle, firstJob, noJobs, level, pJob, bytesNeeded, out bytesCopied, out structsCopied);
// Convert pJob to jobInfos
JOB_INFO_1W[] jobInfos = null;
// ... actual convert code missed ...
// Iterate through the jobs and try to get their content
foreach (JOB_INFO_1W jobInfo in jobInfos)
{
// Open print job
string printJobName = string.Format("{0}, Job {1}", printerName, jobInfo.JobId);
IntPtr printJobHandle;
OpenPrinterW(printJobName.Normalize(), out printJobHandle, IntPtr.Zero);
// Read print job
const int printJobBufLen = 1024;
StringBuilder printJobSb = new StringBuilder(printJobBufLen);
int printJobBytesRead = 0;
while (printJobBytesRead == 0)
{
ReadPrinter(printJobHandle, printJobSb, printJobBufLen, out printJobBytesRead);
// !!! printJobBytesRead is 0 and printJobSb is empty
}
// Close print job
ClosePrinter(printJobHandle);
}
// Close printer
ClosePrinter(printerHandle);
P/Invoke 签名:
[DllImport("winspool.drv", EntryPoint = "OpenPrinterW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern int OpenPrinterW(
[In] string pPrinterName,
[Out] out IntPtr phPrinter,
[In] IntPtr pDefault);
[DllImport("spoolss.dll", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern int ClosePrinter(
[In] IntPtr hPrinter);
[DllImport("winspool.drv", EntryPoint = "EnumJobsW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern int EnumJobsW(
[In] IntPtr hPrinter,
[In] uint FirstJob,
[In] uint NoJobs,
[In] uint Level,
[Out] IntPtr pJob,
[In] uint cbBuf,
[Out] out uint pcbNeeded,
[Out] out uint pcReturned);
[DllImport("spoolss.dll", EntryPoint = "ReadPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern int ReadPrinter(
[In] IntPtr hPrinter,
[Out] StringBuilder data,
[In] Int32 cbBuf,
[Out] out Int32 pNoBytesRead);
此代码是否在 driver's Print Processor component 中?如果没有,我认为它不会起作用。
所以您要么使用打印驱动程序组件,要么从磁盘上的假脱机文件中读取。