在基于.NET的非GUI应用程序中如何打印?

3
假设我有一个基于.NET的Windows应用程序,没有GUI(例如Windows服务,控制台应用程序或Web服务),我需要在物理打印机上打印某些内容(例如自动生成的发票)。
我应该使用BCL的哪些类?到目前为止,我已经找到了以下信息:
- System.Drawing.Printing.PrintDocument:文档明确提到这是用于Windows Forms应用程序的打印。特别是,它提到WPF应用程序应改用System.Printing命名空间中的类。 - System.Printing命名空间:文档明确提到这些类“不支持在Windows服务或ASP.NET应用程序或服务中使用”。
那么,我应该使用什么来从非GUI应用程序打印?(而且为什么打印类与UI框架“绑定”在一起呢?)

我猜它们都依赖于UI库进行渲染和布局。构建打印文档所使用的许多对象与用于在屏幕上显示内容的对象相同。(而ASP不会渲染任何东西,它将其留给浏览器) - Robin Bennett
1个回答

1

从控制台应用程序上它应该能正常工作。但是,Windows服务或者ASP.NET并不那么容易。

这里有一些建议在这里,但不是很容易(比如使用P/Invoke调用C++库来打印,这是我的第一个想法)。你可以搜索一下看看是否有人已经完成了这个任务。

这个答案推荐了一个第三方产品:DevExpress的XtraReports

Reddit 上也有这个人描述了他是如何解决这个问题的。你可以给他发送消息并看是否能获得他的代码。

这个例子使用Microsoft.Office.Interop.Word来从Windows服务中打印Word文档。看起来有些“hacky”,但我不认为它不能正常工作:

public class WordPrintTask  
{  
 private static object locker = new Object();  
 public WordPrintTask() { }  
 public void PrintWord()  
 {  
   try  
   {  
     // Kill opened word instances.  
     if (KillProcess("WINWORD"))  
     {  
       // Thread safe.  
       lock (locker)  
       {  
         string fileName = "D:\\PrinterDocs\\TEST.docx";  
         string printerName = "\\\\10.0.0.89\\PRINTER1020";  
         if (File.Exists(fileName))  
         {  
           Application _application = new Application();  
           _application.Application.ActivePrinter = printerName;  
           object oSourceFilePath = (object)fileName;  
           object docType = WdDocumentType.wdTypeDocument;  
           object oFalse = (object)false;  
           object oMissing = System.Reflection.Missing.Value;  
           Document _document = _application.Documents.Open(ref oSourceFilePath,  
                              ref docType,  
                              ref oMissing,  
                              ref oMissing,  
                              ref oMissing,  
                              ref oMissing,  
                              ref oMissing,  
                              ref oMissing,  
                              ref oMissing,  
                              ref oMissing,  
                              ref oMissing,  
                              ref oMissing,  
                              ref oMissing,  
                              ref oMissing,  
                              ref oMissing,  
                              ref oMissing);  
           // Print  
           _application.PrintOut(ref oFalse, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,  
                             ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,  
                             ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing);  
           object saveOptions = WdSaveOptions.wdDoNotSaveChanges;  
           _document.Close(ref oFalse, ref oMissing, ref oMissing);  
           if (_application != null)  
           {  
             object oSave = false;  
             Object oMiss = System.Reflection.Missing.Value;  
             _application.Quit(ref oSave, ref oMiss, ref oMissing);  
             _application = null;  
           }  
           // Delete the file once it is printed  
           File.Delete(fileName);  
         }  
       }  
     }  
   }  
   catch (Exception ex)  
   {  
     KillProcess("WINWORD");  
   }  
   finally  
   {  
   }  
 }  
 private static bool KillProcess(string name)  
 {  
   foreach (Process clsProcess in Process.GetProcesses().Where(p => p.ProcessName.Contains(name)))  
   {  
     if (Process.GetCurrentProcess().Id == clsProcess.Id)  
       continue;  
     if (clsProcess.ProcessName.Contains(name))  
     {  
       clsProcess.Kill();  
       return true;  
     }  
   }  
   return true;  
 }  
}

哇,没想到会这么复杂。顺便说一下,从未经人工干预的代码自动化Office也不受支持,因此MS Word选项无效。 - Heinzi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接