首页 文章

使用C#将文档发送到打印机

提问于
浏览
7

我已经被要求内部Web应用程序透明地将文档发送到打印机 . 我们的想法是用户可以选择最近的打印机,Web应用程序会将打印作业发送到他们选择的打印机 .

我们要推出的第一台打印机是Canons,所以我的问题是:我如何发送文件打印网络到特定的佳能? Cannon的类型问题是iR5570,将要说的文件主要是Word和PDF

我目前正在通过可怕的,IE浏览器唯一的佳能开发者网站工作,但我有点希望有人可以指出我正确的方向或指向我在第三方组装:)

7 回答

  • 1

    该问题的关键词是“网络应用程序” .

    在仅使用HTML Javascript over HTTP的普通Web应用程序中,您不能直接将文档发送到打印机 . 那台's one of the reasons web browsers exist, and without that functionality everyone'的打印机会收集与公共传真机相同的垃圾 .

    所以你需要某种解决方法 . 一种选择是 Build 一个通用的插件,如flash,silverlight,java applet,甚至像greasemonkey . 另一种是自定义插件,如托管的winforms控件或自定义浏览器扩展 .

    您非常幸运,因为您看起来已完全控制(或了解)部署环境,并且此环境非常均匀 . 这意味着您还有其他人已经开始探索的其他选项 . 如果您可以将环境中的所有打印机安装到Web服务器,那么使用内置的.Net打印机类(在 System.Drawing.Printing 命名空间中)列出这些打印机相当容易,或者向用户显示它们以便它们可以选择或保留某种IP到打印机映射表,然后从您的Web应用程序直接打印到该打印机 . 请注意,此方案可能要求您的应用程序以比其他方式更高的信任级别运行 .

    现在,实际打印PDF和Word文档 . 对于acrobat,请检查以下链接:
    http://support.adobe.com/devsup/devsup.nsf/docs/52080.htm(Wayback machine)
    请注意,它必须尝试一些以确保它按预期工作 .

    对于Word,我通常不喜欢Web应用程序中的Office互操作/自动化 . 但在这种情况下,您不会编辑任何文档:只需加载足够长的时间即可打印 . 而你依赖于另一种稀缺资源(打印机)的事实应该使其不会超出你的网络服务器所能应付的范围 . 因此,您可能会遇到一个罕见的情况,即Web项目中的Office自动化是有意义的 .

  • 1

    如今许多打印机和多功能设备都支持直接打印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命令行,也就是说,我们目前在我们的一个Web应用程序中执行此操作并且运行良好 . 顺便说一句,我们不是为了打印而是为了加入许多PDF文件,但最终它的工作原理是相同的 .

  • 0

    PrintDocument文档包含从C#打印的详细示例 . 打印机名称应指向本地打印机或打印机共享 . 有关打印PDF文档的信息,请参见printing-to-a-pdf-printer-programatically .

  • -1

    有些东西必须将您的Word和PDF文档翻译成打印机能够理解的内容 . 通常情况下,这将是前者的Word本身,以及后者的某种PDF查看器 . 然后需要指示那些程序将输出发送到哪台打印机 .

    一种可能的方法是将文档保存为Postscript文件 . 然后可以直接从C#应用程序将它们发送到支持Postscript的打印机 . 这可能是最简单的方法 .

  • 1

    检查sql报告服务的功能可能值5分钟 . 我过去曾用它来直接渲染pdf .

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

  • 6

    如果窗口已知有问题的文档类型(应该是DOC和PDF),您可以使用Windows动词来执行此操作吗?

    Codeproject PDF example : Automated PDF Conversion using the PDF995 and FreePDF_XP Freeware Printers MSDN : Verbs and File Associations

  • 6

    此代码完美运行它使用Adobe阅读器本身进行打印

    使用提示1-不要忘记为adobe reader提供自己的安装路径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;
    }
    

相关问题