2008-10-20 4 views
7

Мне было предложено, чтобы внутреннее веб-приложение отправляло документы на принтер прозрачно. Идея состоит в том, что пользователь может выбрать ближайший принтер, и веб-приложение отправит свои задания на печать на выбранный принтер.Отправить документ на принтер с C#

Первым принтером, с которым мы должны работать, являются каноны, поэтому мои вопросы: как я могу отправить документ для печати по сети конкретному Canon? Тип Cannon - вопрос iR5570, и документы, которые будут упомянуты, будут главным образом Word и PDF-файлы.

В настоящее время я работаю через ужасный, только IE-сайт разработчика Canon, но я как бы надеялся, что кто-то может указать мне в правильном направлении или указать мне на стороннюю сборку :)

ответ

6

Ключевая фраза в этом вопросе является 'веб-приложение'.

В обычном веб-приложении, использующем только HTML + Javascript через HTTP, вы не можете просто отправить документ непосредственно на принтер. Это одна из причин, по которой существуют веб-браузеры, и без этой функциональности каждый принтер будет собирать тот же самый мусор, который делает публичный факсимильный аппарат.

Так что вам нужно какое-то рабочее обхождение. Один из вариантов - создать общий плагин, например flash, silverlight, java-апплет или даже что-то вроде greasemonkey. Другой - это настраиваемый плагин, например, размещенный элемент управления winforms или пользовательское расширение браузера.

Вам очень повезло, что, похоже, у вас есть полный контроль (или знание) среды развертывания и что эта среда достаточно однородна. Это означает, что у вас есть дополнительный вариант, который другие начали изучать. Если вы можете установить все принтеры в своей среде на веб-сервер, то довольно просто использовать встроенные классы .Net-принтера (в пространстве имен System.Drawing.Printing), чтобы отобразить их, либо показать их пользователю, чтобы они могли выберите или сохраните какой-то IP-адрес в таблице сопоставления принтеров, а затем распечатайте его непосредственно на этом принтере из своего веб-приложения. Обратите внимание, что эта схема может потребовать от вашего приложения работать на более высоком уровне доверия, чем в противном случае.

Теперь речь идет о фактической печати документов PDF и документов. Для acrobat, проверьте эту ссылку:
http://support.adobe.com/devsup/devsup.nsf/docs/52080.htm (Wayback machine)
Обратите внимание, что это немного устарело, но я считаю, что концепция по-прежнему действительна. Вам нужно будет поэкспериментировать, чтобы убедиться, что он работает так, как ожидалось.

Для Word я обычно не являюсь поклонником Office interop/automation в веб-приложении. Но в этом случае вы не редактируете никаких документов: просто загрузите его достаточно долго, чтобы печатать. И тот факт, что вы полагаетесь на другой дефицитный ресурс (принтеры), должен держать это от масштабирования выше, чем может справиться ваш веб-сервер. Таким образом, у вас может быть редкий случай, когда автоматизация Office в веб-проекте имеет смысл.

1

PrintDocument документация содержит подробный пример печати из C#. Имя принтера должно указывать на локальный принтер или общий ресурс принтера. См. printing-to-a-pdf-printer-programatically для печати документов PDF.

+0

Это работает только с txt-файлом? – 2012-08-31 12:41:21

+0

1-й пример демонстрирует текст (строки), но класс PrintDocument использует объект Graphics для рисования. Это означает, что вы можете использовать пространство пространств имен System.Drawing (GDI +). – gimel 2012-08-31 13:19:21

+0

ах я вижу .. но я полагаю, что собственный формат (например, MS Word) не поддерживается этим классом? – 2012-08-31 14:24:17

1

Что-то должно перевести ваши документы Word и PDF во что-то, что понимает принтер. Обычно это было бы само Слово для первого и какой-то просмотрщик PDF для последнего. Затем эти программы должны быть проинструктированы о том, на каком принтере будет отправлен вывод.

Один из возможных способов - сохранить документы в виде файлов Postscript. Затем их можно отправить на принтер, поддерживающий Postscript, непосредственно из приложения C#. Вероятно, это был бы самый простой способ сделать это.

1

Возможно, стоит потратить 5 минут на проверку возможностей службы отчетности sql. Я использовал его в прошлом, чтобы сделать pdf прямо для печати.

http://blogs.msdn.com/bryanke/articles/71491.aspx

6

Многие принтеры и многофункциональные устройства сегодня поддерживают печать PDF-файлов напрямую, это может решить одну из ваших проблем. Просто отправьте PDF на принтер. На самом деле, некоторые даже поддерживают отправку URL-адреса, а затем принтер получает документ и печатает его. Lexmark точно это делает, и я думаю, что некоторые другие производители тоже. Это все равно означает, что вам нужно иметь дело с документом Word. Word 2007 поддерживает PDF (с add-in installed from Microsoft), и я использовал эту функцию с большим успехом на C#.

Вот код для этого:

Microsoft.Office.Interop.Word.ApplicationClass msWord = new Microsoft.Office.Interop.Word.ApplicationClass(); 

object paramUnknown = Type.Missing; 
object missing = Type.Missing; 
object paramSaveChangesNo = Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges; 
//object paramFonts = Microsoft.Office.Interop.Word.wde 
object paramFormatPDF = Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatPDF; 
object paramTrue = true; 
object paramReadOnly = true; 
object sourceDoc = @"c:\input.doc"        
object target = @"c:\output.pdf"; 

msWord.Visible = false; 

//open .doc 
msWord.Documents.Open(ref sourceDoc, ref paramUnknown, ref paramReadOnly, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown); 

//so it won't show on the taskbar 
msWord.Application.Visible = false; 
msWord.WindowState = Microsoft.Office.Interop.Word.WdWindowState.wdWindowStateMinimize; 

//save .doc to new target name and format 
msWord.ActiveDocument.SaveAs(ref targetDoc, ref paramFormatPDF, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramTrue, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown); 

msWord.ActiveDocument.Close(ref missing, ref missing, ref missing); 

msWord.Quit(ref paramSaveChangesNo, ref paramUnknown, ref paramUnknown); 

Наконец, если устройство не поддерживает PDF печать, то вы можете использовать Ghostscript или другие инструменты для преобразования PDF в PS или даже PCL. Не самое большое, так как это означает, что он запускает небольшой неуправляемый код или худший случай, обстреливая и выполняя командную строку GS, что, как говорится, мы в настоящее время делаем это в одном из наших веб-приложений, и оно работает хорошо. В стороне мы не делаем этого для печати, а скорее присоединяем несколько PDF-файлов togheter, но в итоге они будут работать одинаково.

-1

Этот код работает отлично Он использует самое Adobe Reader для печати

подсказки использовать 1- не забудьте указать свой собственный путь установки для читателя самана 2 Получить принтер имя из свойств принтера вы хотите печатать с

использовать класс как это:

PdfFilePrinter p = new PdfFilePrinter(); 

p.PdfFileName = @"c:\1.pdf"; 
p.Print(); 
p.PdfFileName = @"c:\2.pdf"; 
p.Print(); 

и класс:

public class PdfFilePrinter 
{ 
    /// <summary> 
    /// Initializes a new instance of the <see cref="PdfFilePrinter"/> class. 
    /// </summary> 
    public PdfFilePrinter() 
    { 
     adobeReaderPath = @"C:\Program Files\Adobe\Reader 9.0\Reader\AcroRd32.exe"; 
     printerName = "HP LaserJet P2055 Series PCL6"; 
    } 

    /// <summary> 
    /// Initializes a new instance of the <see cref="PdfFilePrinter"/> class. 
    /// </summary> 
    /// <param name="pdfFileName">Name of the PDF file.</param> 
    public PdfFilePrinter(string pdfFileName) 
    { 
     this.PdfFileName = pdfFileName; 
    } 

    /// <summary> 
    /// Initializes a new instance of the <see cref="PdfFilePrinter"/> class. 
    /// </summary> 
    /// <param name="pdfFileName">Name of the PDF file.</param> 
    /// <param name="printerName">Name of the printer.</param> 
    public PdfFilePrinter(string pdfFileName, string printerName) 
    { 
     this.pdfFileName = pdfFileName; 
     this.printerName = printerName; 
    } 

    /// <summary> 
    /// Gets or sets the name of the PDF file to print. 
    /// </summary> 
    public string PdfFileName 
    { 
     get { return this.pdfFileName; } 
     set { this.pdfFileName = value; } 
    } 
    string pdfFileName; 

    /// <summary> 
    /// Gets or sets the name of the printer. A typical name looks like '\\myserver\HP LaserJet PCL5'. 
    /// </summary> 
    /// <value>The name of the printer.</value> 
    public string PrinterName 
    { 
     get { return this.printerName; } 
     set { this.printerName = value; } 
    } 
    string printerName; 

    /// <summary> 
    /// Gets or sets the working directory. 
    /// </summary> 
    public string WorkingDirectory 
    { 
     get { return this.workingDirectory; } 
     set { this.workingDirectory = value; } 
    } 
    string workingDirectory; 

    /// <summary> 
    /// Prints the PDF file. 
    /// </summary> 
    public void Print() 
    { 
     Print(-1); 
    } 

    /// <summary> 
    /// Prints the PDF file. 
    /// </summary> 
    /// <param name="milliseconds">The number of milliseconds to wait for completing the print job.</param> 
    public void Print(int milliseconds) 
    { 
     if (this.printerName == null || this.printerName.Length == 0) 
      this.printerName = PdfFilePrinter.defaultPrinterName; 

     if (PdfFilePrinter.adobeReaderPath == null || PdfFilePrinter.adobeReaderPath.Length == 0) 
      throw new InvalidOperationException("No full qualified path to AcroRd32.exe or Acrobat.exe is set."); 

     if (this.printerName == null || this.printerName.Length == 0) 
      throw new InvalidOperationException("No printer name set."); 

     // Check whether file exists. 
     string fqName = String.Empty; 
     if (this.workingDirectory != null && this.workingDirectory.Length != 0) 
      fqName = Path.Combine(this.workingDirectory, this.pdfFileName); 
     else 
      fqName = Path.Combine(Directory.GetCurrentDirectory(), this.pdfFileName); 
     if (!File.Exists(fqName)) 
      throw new InvalidOperationException(String.Format("The file {0} does not exist.", fqName)); 

     // TODO: Check whether printer exists. 

     try 
     { 
      DoSomeVeryDirtyHacksToMakeItWork(); 

      //acrord32.exe /t   <- seems to work best 
      //acrord32.exe /h /p  <- some swear by this version 
      ProcessStartInfo startInfo = new ProcessStartInfo(); 
      startInfo.FileName = PdfFilePrinter.adobeReaderPath; 
      string args = String.Format("/t \"{0}\" \"{1}\"", this.pdfFileName, this.printerName); 
      //Debug.WriteLine(args); 
      startInfo.Arguments = args; 
      startInfo.CreateNoWindow = true; 
      startInfo.ErrorDialog = false; 
      startInfo.UseShellExecute = false; 
      if (this.workingDirectory != null && this.workingDirectory.Length != 0) 
       startInfo.WorkingDirectory = this.workingDirectory; 

      Process process = Process.Start(startInfo); 
      if (!process.WaitForExit(milliseconds)) 
      { 
       // Kill Adobe Reader/Acrobat 
       process.Kill(); 
      } 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
    } 

    /// <summary> 
    /// For reasons only Adobe knows the Reader seams to open and shows the document instead of printing it 
    /// when it was not already running. 
    /// If you use PDFsharp and have any suggestions to circumvent this function, please let us know. 
    /// </summary> 
    void DoSomeVeryDirtyHacksToMakeItWork() 
    { 
     if (PdfFilePrinter.runningAcro != null) 
     { 
      if (!PdfFilePrinter.runningAcro.HasExited) 
       return; 
      PdfFilePrinter.runningAcro.Dispose(); 
      PdfFilePrinter.runningAcro = null; 
     } 
     // Is any Adobe Reader/Acrobat running? 
     Process[] processes = Process.GetProcesses(); 
     int count = processes.Length; 
     for (int idx = 0; idx < count; idx++) 
     { 
      try 
      { 
       Process process = processes[idx]; 
       ProcessModule module = process.MainModule; 

       if (String.Compare(Path.GetFileName(module.FileName), Path.GetFileName(PdfFilePrinter.adobeReaderPath), true) == 0) 
       { 
        // Yes: Fine, we can print. 
        PdfFilePrinter.runningAcro = process; 
        break; 
       } 
      } 
      catch { } 
     } 
     if (PdfFilePrinter.runningAcro == null) 
     { 
      // No: Start an Adobe Reader/Acrobat. 
      // If you are within ASP.NET, good luck... 
      PdfFilePrinter.runningAcro = Process.Start(PdfFilePrinter.adobeReaderPath); 
      PdfFilePrinter.runningAcro.WaitForInputIdle(); 
     } 
    } 
    static Process runningAcro; 

    /// <summary> 
    /// Gets or sets the Adobe Reader or Adobe Acrobat path. 
    /// A typical name looks like 'C:\Program Files\Adobe\Adobe Reader 7.0\AcroRd32.exe'. 
    /// </summary> 
    static public string AdobeReaderPath 
    { 
     get { return PdfFilePrinter.adobeReaderPath; } 
     set { PdfFilePrinter.adobeReaderPath = value; } 
    } 
    static string adobeReaderPath; 

    /// <summary> 
    /// Gets or sets the name of the default printer. A typical name looks like '\\myserver\HP LaserJet PCL5'. 
    /// </summary> 
    static public string DefaultPrinterName 
    { 
     get { return PdfFilePrinter.defaultPrinterName; } 
     set { PdfFilePrinter.defaultPrinterName = value; } 
    } 
    static string defaultPrinterName; 
} 
Смежные вопросы