2017-10-05 475 views
0

我想获取发送到打印文档的内容。谷歌表示,唯一的办法就是使用WinAPI方法ReadPrinter()。 我已经实现了一个草图,但不能得到它的工作。 一个麻烦的是ReadPrinter()方法总是不返回任何内容。如何使用ReadPrinter方法读取打印作业内容

请给我一个提示什么是错的。

简体下面的代码:

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); 
+0

我们看不到任何P/Invoke签名。这些默认情况下是错误的。 – IInspectable

+0

我的不好,抱歉。添加签名。 –

回答

0

是一个driver's Print Processor component这里面的代码?如果没有,我认为它不会起作用。

因此,您要么使用打印驱动程序组件,要么从磁盘上的假脱机文件读取数据。 See here.

+0

感谢您的联系undocprint,尼克! 我不熟悉Windows打印体系结构。那是我的问题。 现在我看到我需要开发自定义打印处理器来做我想做的事情。 –

+0

并回答你的第一个问题:我的代码是在平常的控制台应用程序中。 –

+0

在我的情况下,spool是禁用的,所以通信应该直接打印到打印机 – AaA