2011-05-23 210 views
48

這裏的基本前提:如何將文件文件發送到打印機並進行打印?

我的用戶點擊一些小玩意兒,一個PDF文件被吐出到他的桌面。有沒有辦法讓我將這個文件發送到打印機隊列並將其打印到本地連接的打印機上?

string filePath = "filepathisalreadysethere"; 
SendToPrinter(filePath); //Something like this? 

他會做很多次這個過程。對於課堂中的每個學生,他都必須打印一張小小的成績單。所以我爲每個學生生成一個PDF,並且我希望自動化打印過程,而不是讓用戶生成PDF,打印,生成PDF,打印,生成PDF,打印。

關於如何解決這個問題的任何建議?我在Windows XP與Windows窗體運行.NET 4

我發現這個問題StackOverflow那裏接受的答案提示:

一旦你創建你的文件,你 可以通過打印出來一個命令行(你 使用 System.Diagnostics命名空間中發現 的Command類亦可)

我將如何做到這一點?

+0

爲什麼不合並PDF文檔並讓用戶打印單頁,多頁文檔?似乎不太容易出錯,並且很難錯過打印其中一個報告(例如,如果其中一個文件發生錯誤)。 – 2011-05-23 22:35:23

+0

@ 0xA3,我會研究,但現在我需要考慮發送文件到打印機。 – 2011-05-23 22:36:26

回答

53

你可以告訴Acrobat Reader來打印使用文件(如其他人已經這裏提到)「打印」動詞。您需要在此之後編程方式關閉Acrobat Reader軟件,太:

private void SendToPrinter() 
{ 
    ProcessStartInfo info = new ProcessStartInfo(); 
    info.Verb = "print"; 
    info.FileName = @"c:\output.pdf"; 
    info.CreateNoWindow = true; 
    info.WindowStyle = ProcessWindowStyle.Hidden; 

    Process p = new Process(); 
    p.StartInfo = info; 
    p.Start(); 

    p.WaitForInputIdle(); 
    System.Threading.Thread.Sleep(3000); 
    if (false == p.CloseMainWindow()) 
     p.Kill(); 
} 

這將打開Acrobat Reader軟件,並告訴它的PDF發送到默認打印機,然後在三秒鐘後關閉的Acrobat。

如果您願意使用您的應用程序發佈其他產品,那麼您可以使用GhostScript(免費)或命令行PDF打印機,如http://www.commandlinepdf.com/(商業版)。

注:示例代碼中打開PDF文件在註冊打印PDF文件應用電流,這是Adobe Acrobat Reader軟件在大多數人的機器。但是,他們可能會使用不同的PDF查看器,例如Foxit(http://www.foxitsoftware.com/pdf/reader/)。但示例代碼仍然可以工作。

+0

爲什麼此代碼在服務器端無法正常工作? – dev 2012-11-06 16:06:07

+1

@Mvcdev代碼依賴於:a)在服務器上安裝Acrobat(或其他閱讀器),以及b)調用交互式應用程序(例如Adobe Acrobat),如果您的代碼在用戶帳戶下運行,則可能不起作用互動。在這種情況下,一個命令行工具是你最好的選擇(如上所述www.commandlinepdf.com) – 2012-11-08 14:35:49

+0

其實它正在工作,但是如果我發佈該網站,我用iis做的事情並不好。此網站僅適用於內部網絡。我有幾個步驟。 1)我將應用程序池Asp.NET v4.0標識更改爲LocalSystem。 2)我在machine.config文件中的中應用了用戶名和密碼。 3)我已經使用此網站更改了註冊表(http://support.microsoft.com/?kbid=184291)。 N使用你的代碼對我來說工作正常。如果在這裏出了問題,請指教我? – dev 2012-11-08 16:09:09

3

System.Diagnostics.Process.Start可用於打印文檔。將UseShellExecute設置爲True並將動詞設置爲「打印」。

+0

你能詳細說明一下嗎?我不明白我應該將UseShellExecute設置爲true。 – 2011-05-23 22:33:40

+0

'過程。Start'方法可以將一個'ProcessStartInfo'對象作爲參數,它具有這些屬性。 – 2011-05-23 22:59:12

+0

@Tim Destan:我真的很茫然,這是Verb和UseShellExecute實際上是ProcessStartInfo類的屬性嗎?你有一些示例代碼? – 2011-05-23 23:05:12

9

這是一個稍作修改的解決方案。該進程在閒置至少1秒鐘後將被殺死。也許你應該添加一個X秒的時間並從一個單獨的線程調用該函數。

private void SendToPrinter() 
{ 
    ProcessStartInfo info = new ProcessStartInfo(); 
    info.Verb = "print"; 
    info.FileName = @"c:\output.pdf"; 
    info.CreateNoWindow = true; 
    info.WindowStyle = ProcessWindowStyle.Hidden; 

    Process p = new Process(); 
    p.StartInfo = info; 
    p.Start(); 

    long ticks = -1; 
    while (ticks != p.TotalProcessorTime.Ticks) 
    { 
    ticks = p.TotalProcessorTime.Ticks; 
    Thread.Sleep(1000); 
    } 

    if (false == p.CloseMainWindow()) 
    p.Kill(); 
} 
24

我所知道的標籤說:Windows Forms ...但是,如果有人有興趣在WPF應用方法,System.Printing的作品就像一個魅力。

var file = File.ReadAllBytes(pdfFilePath); 
var printQueue = LocalPrintServer.GetDefaultPrintQueue(); 

using (var job = printQueue.AddJob()) 
using (var stream = job.JobStream) 
{ 
    stream.Write(file, 0, file.Length); 
} 

只要記住包括System.Printing參考,如果它尚未包括在內。 現在,這種方法不適用於ASP.NETWindows Service。它不應該與Windows Forms一起使用,因爲它有System.Drawing.Printing。使用上面的代碼我沒有使用我的PDF打印的單個問題。

但是,我應該提到,如果您的打印機不支持直接打印PDF文件格式,那麼您使用此方法運氣不佳。

+2

這也適用於一個普通的控制檯項目。 – Jwosty 2015-08-10 14:47:22

+0

@Jwosty好點。 – 2015-09-25 21:32:26

+0

我試圖用我的_HP LaserJet CP1025nw_進行打印,但它不工作。一會兒,它會在狀態_spooling_的打印隊列中顯示打印作業,然後在沒有打印的情況下從其中消失 – sohaiby 2017-06-20 09:16:03

1

最簡單的辦法:

var pi=new ProcessStartInfo("C:\file.docx"); 
pi.UseShellExecute = true; 
pi.Verb = "print"; 
var process = System.Diagnostics.Process.Start(pi); 
4

這是一個遲到的回答,但你也可以使用System.IO命名空間的File.Copy方法頂部的文件發送到打印機:

System.IO.File.Copy(filename, printerName); 

這工作正常

+3

你能否詳述一下?我唯一得到的是一個寫入硬盤的文件,其名稱爲'printerName' ... – 2016-05-25 14:44:02

+2

例如:File.Copy(「myFileToPrint.pdf」,「\\ myPrintServerName \ myPrinterName」); – 2017-01-23 23:35:10

2

我知道埃德溫在上面回答,但他只打印一個文件。我使用此代碼打印來自給定目錄的所有文件。

public void PrintAllFiles() 
{ 
    System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo(); 
    info.Verb = "print"; 
    System.Diagnostics.Process p = new System.Diagnostics.Process(); 
    //Load Files in Selected Folder 
    string[] allFiles = System.IO.Directory.GetFiles(Directory); 
    foreach (string file in allFiles) 
    { 
     info.FileName = @file; 
     info.CreateNoWindow = true; 
     info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 
     p.StartInfo = info; 
     p.Start(); 
    } 
    //p.Kill(); Can Create A Kill Statement Here... but I found I don't need one 
    MessageBox.Show("Print Complete"); 
} 

它essentually通過指定目錄變量Directory中的每個文件的循環 - >對我來說是@「C:\用戶\用戶\文檔\ SalesVaultTesting \」和這些文件打印給您的默認打印機

22

爲此添加一個新的答案,因爲在.net中打印PDF的問題已經存在了很長時間,大多數答案都是在Google Pdfium庫之前完成的,該庫現在有一個.net包裝器。對我來說,我自己正在研究這個問題,並一直空白,試圖做出像生成Acrobat或其他PDF閱讀器的黑客解決方案,或運行到昂貴且沒有非常兼容的許可條款的商業庫中。但Google Pdfium庫和PdfiumViewer.net包裝都是開源的,所以對於很多開發者來說都是一個很好的解決方案,包括我自己在內。 PdfiumViewer獲得Apache 2.0許可。

你可以得到NuGet包這裏:

https://www.nuget.org/packages/PdfiumViewer/

,你可以找到源代碼在這裏:

https://github.com/pvginkel/PdfiumViewer

下面是一些簡單的代碼,會悄悄地打印任何數量的PDF文件副本的文件名。您也可以從流中加載PDF(這是我們通常的做法),並且您可以輕鬆地查看代碼或示例。還有一個WinForm PDF文件視圖,因此您也可以將PDF文件渲染到視圖中或對其進行打印預覽。對於我們來說,我只需要一種方法將PDF文件靜默地按需打印到特定的打印機。

public bool PrintPDF(
    string printer, 
    string paperName, 
    string filename, 
    int copies) 
{ 
    try { 
     // Create the printer settings for our printer 
     var printerSettings = new PrinterSettings { 
      PrinterName = printer, 
      Copies = (short)copies, 
     }; 

     // Create our page settings for the paper size selected 
     var pageSettings = new PageSettings(printerSettings) { 
      Margins = new Margins(0, 0, 0, 0), 
     }; 
     foreach (PaperSize paperSize in printerSettings.PaperSizes) { 
      if (paperSize.PaperName == paperName) { 
       pageSettings.PaperSize = paperSize; 
       break; 
      } 
     } 

     // Now print the PDF document 
     using (var document = PdfDocument.Load(filename)) { 
      using (var printDocument = document.CreatePrintDocument()) { 
       printDocument.PrinterSettings = printerSettings; 
       printDocument.DefaultPageSettings = pageSettings; 
       printDocument.PrintController = new StandardPrintController(); 
       printDocument.Print(); 
      } 
     } 
     return true; 
    } catch { 
     return false; 
    } 
} 
+0

這讓我在10分鐘左右的時間裏跑完了。 – 2017-01-27 13:54:23

+0

很好的解決方案,謝謝!還有一個非常好的Google庫,它也是開源的,所以它可能會停留更長時間。如果有人對雙面打印感興趣,可以使用'printerSettings.Duplex = Duplex.Vertical'輕鬆完成此工作,這對我們來說就像是一種魅力。 – Viorel 2017-03-14 09:06:40

+0

這是否也可以在IIS環境中使用?我有通過在IIS中託管的應用程序將pdf(從流生成)傳輸到網絡打印機的場景。我試着用這個代碼,我遇到的問題是:1.文檔正在排隊等待大小爲0字節的打印作業隊列。 2.文檔正在排隊到打印作業隊列,其所有者名稱爲machine_name。 – 2017-04-12 07:07:52

相關問題