【问题标题】:Print html document from Windows Service without print dialog从没有打印对话框的 Windows 服务打印 html 文档
【发布时间】:2009-01-07 06:41:39
【问题描述】:

我正在使用 Windows 服务,我想在服务启动时打印一个 .html 页面。我正在使用此代码,并且打印效果很好。但是打印对话框来了,没有打印对话框怎么打印?

public void printdoc(string document)
{
    Process printjob = new Process();

    printjob.StartInfo.FileName = document;
    printjob.StartInfo.UseShellExecute = true;
    printjob.StartInfo.Verb = "print";
    printjob.StartInfo.CreateNoWindow = true;
    printjob.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

    printjob.Start();
}

有没有其他方法可以在不显示打印对话框的情况下打印它。


更新:回复this:

但是我已经使用过这个类但是当我调用时

axW.ExecWB(SHDocVw.OLECMDID.OLECMDID_PRINT,SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_PROMPTUSER , ref em, ref em);

当我从窗口服务使用时,我的程序在这里被阻塞,但它在 Windows 应用程序中运行良好。

【问题讨论】:

    标签: c# windows-services printing


    【解决方案1】:

    首先,代码如下:

    using System.Reflection;
    using System.Threading;
    using SHDocVw;
    
    namespace HTMLPrinting
    {
      public class HTMLPrinter
      {
        private bool documentLoaded;
        private bool documentPrinted;
    
        private void ie_DocumentComplete(object pDisp, ref object URL)
        {
          documentLoaded = true;
        }
    
        private void ie_PrintTemplateTeardown(object pDisp)
        {
          documentPrinted = true;
        }
    
        public void Print(string htmlFilename)
        {
          documentLoaded = false;
          documentPrinted = false;
    
          InternetExplorer ie = new InternetExplorerClass();
          ie.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(ie_DocumentComplete);
          ie.PrintTemplateTeardown += new DWebBrowserEvents2_PrintTemplateTeardownEventHandler(ie_PrintTemplateTeardown);
    
          object missing = Missing.Value;
    
          ie.Navigate(htmlFilename, ref missing, ref missing, ref missing, ref missing);
          while (!documentLoaded && ie.QueryStatusWB(OLECMDID.OLECMDID_PRINT) != OLECMDF.OLECMDF_ENABLED)
            Thread.Sleep(100);
    
          ie.ExecWB(OLECMDID.OLECMDID_PRINT, OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, ref missing, ref missing);
          while (!documentPrinted)
            Thread.Sleep(100);
    
          ie.DocumentComplete -= ie_DocumentComplete;
          ie.PrintTemplateTeardown -= ie_PrintTemplateTeardown;
          ie.Quit();
        }
      }
    }
    
    1. 您可以通过添加对“Microsoft Internet Controls”的引用来访问 SHDocVw 命名空间,该引用位于“添加引用”对话框的 COM 选项卡上。
    2. 有关 InternetExplorer 对象的更多信息,请访问 MSDN。
    3. Navigate() 方法将加载 HTML 文件。其他参数允许您指定可选参数,例如标志和标题。
    4. 在加载文档之前我们无法打印。在这里,我进入一个循环,等待 DocumentComplete 事件被调用,在该事件上设置一个标志,通知我们导航已完成。请注意,每当导航完成时都会调用 DocumentComplete - 成功或失败。
    5. 设置 documentLoaded 标志后,将通过 QueryStatusWB() 查询打印状态,直到启用打印。
    6. 使用 ExecWB() 调用开始打印。指定了OLECMDID_PRINT 命令以及选项OLECMDEXECOPT_DONTPROMPTUSER 以自动打印而无需用户交互。一个重要的注意事项是,这将打印到默认打印机。要指定打印机,您必须设置默认打印机(在代码中,您可以调用SetDefaultPrinter())。最后两个参数允许可选的输入和输出参数。
    7. 我们不想在打印完成之前退出,所以再次进入一个循环。触发 PrintTemplateTeardown 事件后,将设置 documentPrinted 标志。然后可以清理这些对象。

    【讨论】:

    • 有没有办法修改它以横向打印?
    • 在 Windows 8.1 上使用它,IE11 收到此错误:调用的对象已与其客户端断开连接。 (来自 HRESULT 的异常:0x80010108 (RPC_E_DISCONNECTED))
    • @seaDrive,你通过代码得到了改变方向属性的答案吗?请告诉我们答案
    【解决方案2】:

    来自这个网站http://www.ussbd.com/printhtm.html

    using HtmlPrinter;
    hpObj=new HtmlPrinter.HtmlPrinter();
    hpObj.PrintUrlFromMemory(txtUrl.Text);
    

    现在您在项目中添加代码以从其源文本打印 html 页面:

    HtmlPrinter.HtmlPrinter hpObj=new HtmlPrinter.HtmlPrinter();
    hpObj.PrintHtml(txtString.Text, true);
    

    如果您想在没有打印对话框的情况下进行打印,请使用以下行:

    hpObj.PrintHtml(txtString.Text, false); 
    

    【讨论】:

    • 我不确定这是否有效。当您单击“直接打印 URL”时,示例应用程序(也发布在 Code Project 上)会弹出打印机对话框,对于 Microsoft XPS Document Writer 等“打印到文件”打印机,“保存文件为”对话框。在“从浏览器打印 URL”的情况下,它只会弹出 MXDW 的“将文件另存为对话框”。
    【解决方案3】:

    这是另一种不带打印对话框的打印方式。您创建一个 PrintDialog 对象,对其进行初始化,然后调用 Print() 方法。

    下面的函数用于打印一个小的 2"x0.75" 条码标签。您需要想办法从 html 文件中获取 Document 对象。

    public void PrintToPrinter(string printerName)
    {
        PrintDialog pd = new PrintDialog();
        pd.Document = userControl11.PrintDoc; // <--- Update this line with your doc
        pd.PrinterSettings.PrinterName = printerName;
        try
        {
                pd.Document.DocumentName = "My Label";
                pd.Document.DefaultPageSettings.PaperSize = new System.Drawing.Printing.PaperSize("2-.75", 200, 75);
                pd.Document.DefaultPageSettings.Margins = new System.Drawing.Printing.Margins(0, 0, 0, 0);
                //pd.PrinterSettings.Copies = (short)mNumCopies;
                pd.Document.PrinterSettings.Copies = (short) mNumCopies;
                pd.Document.Print();
        }
        catch
        {
            MessageBox.Show("INVALID PRINTER SPECIFIED");
        }
    }
    

    【讨论】:

      【解决方案4】:

      您可以使用 System.Drawing.Printing 命名空间中的 PrintDocument 类来更好地控制打印,请参阅here 了解更多信息。

      例如,您可以执行以下操作:

      using (PrintDocument doc = new PrintDocument())
      {
          doc.PrintPage += this.Doc_PrintPage;
          doc.DefaultPageSettings.Landscape = true;
          doc.DocumentName = fileNameOfYourDocument;
          doc.Print();
      }
      

      然后为要打印的每一页引发一个函数,并为您提供一个要绘制的图形区域

      private void Doc_PrintPage(object sender, PrintPageEventArgs ev)
      {
          ....
          ev.Graphics.DrawImage(image, x, y, newWidth, newHeight);
      }
      

      这确实需要您将文本/图像上的实际绘图处理到页面,请参阅here 了解更多信息。

      【讨论】:

        【解决方案5】:

        OLECMDEXECOPT_PROMPTUSER 似乎强制提示用户选择打印机和所有相关的东西,我很确定服务不允许这样做。有人可以验证吗?

        【讨论】:

          猜你喜欢
          • 2010-09-29
          • 2015-06-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-01
          • 1970-01-01
          • 2010-09-05
          • 1970-01-01
          相关资源
          最近更新 更多