2017-10-05 78 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

相關問題