Esempio n. 1
0
        public int Convert(string inputFile, ref string outputFile)
        {
            if (!_initialized)
            {
                throw new Exception("ConverService is not initialized");
            }

            // if no output is provided, use the source file and change to a PDF extension
            if (string.IsNullOrEmpty(outputFile))
            {
                outputFile = Path.ChangeExtension(inputFile, "pdf");
            }
            else
            {
                // if the outputFile spec is a directory, put the file in the directory with same name and new extension
                if (Directory.Exists(outputFile))
                {
                    outputFile = Path.Combine(outputFile, Path.GetFileNameWithoutExtension(inputFile) + ".pdf");
                }
            }

            // confirm that the input file exists and convert to component path elements in options
            FileInfo inputInfo;

            try
            {
                inputInfo = new FileInfo(inputFile);
            }
            catch
            {
                inputInfo = null;
            }
            if (inputInfo == null || !inputInfo.Exists)
            {
                throw new Exception("Input file not found");
            }
            inputFile = inputInfo.FullName;
            _options["original_filename"] = inputInfo.Name;
            _options["original_basename"] = inputInfo.Name.Substring(0, inputInfo.Name.Length - inputInfo.Extension.Length);

            // handle the output file existing or path existing
            FileInfo outputInfo = new FileInfo(outputFile);

            // Remove the destination unless we're doing a PDF merge
            if (outputInfo != null)
            {
                outputFile = outputInfo.FullName;
                if (outputInfo.Exists)
                {
                    if ((MergeMode)_options["pdf_merge"] == MergeMode.None)
                    {
                        // We are not merging, so delete the final destination
                        System.IO.File.Delete(outputInfo.FullName);
                    }
                    else
                    {
                        // We are merging, so make a temporary file
                        outputFile = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".pdf";
                    }
                }
                else
                {
                    // If there is no current output, no need to merge
                    _options["pdf_merge"] = MergeMode.None;
                }
            }
            else
            {
                throw new Exception("Unable to determine outputFile location");
            }
            if (!System.IO.Directory.Exists(outputInfo.DirectoryName))
            {
                throw new Exception("Output directory does not exist");
            }

            // actually do the conversion, finally
            int converted = WordConverter.Convert(inputFile, outputFile, _options);

            return(converted);
        }
Esempio n. 2
0
        /// <summary>
        /// Convert a Word file to PDF
        /// </summary>
        /// <param name="inputFile">Full path of the input Word file</param>
        /// <param name="outputFile">Full path of the output PDF</param>
        /// <returns></returns>
        public static new int Convert(String inputFile, String outputFile, Hashtable options)
        {
            Boolean          running  = (Boolean)options["noquit"];
            Application      word     = null;
            object           oMissing = System.Reflection.Missing.Value;
            Template         tmpl;
            String           temporaryStorageDir = null;
            float            wordVersion         = 0;
            List <AppOption> wordOptionList      = new List <AppOption>();

            try
            {
                String  filename           = (String)inputFile;
                Boolean hasSignatures      = WordConverter.HasDigitalSignatures(filename);
                Boolean visible            = !(Boolean)options["hidden"];
                Boolean openAndRepair      = !(Boolean)options["word_no_repair"];
                Boolean nowrite            = (Boolean)options["readonly"];
                Boolean includeProps       = !(Boolean)options["excludeprops"];
                Boolean includeTags        = !(Boolean)options["excludetags"];
                Boolean bitmapMissingFonts = !(Boolean)options["word_ref_fonts"];
                Boolean autosave           = options.ContainsKey("IsTempWord") && (Boolean)options["IsTempWord"];
                bool    pdfa          = (Boolean)options["pdfa"] ? true : false;
                String  writePassword = "";
                String  readPassword  = "";
                int     maxPages      = 0;

                WdExportOptimizeFor     quality    = WdExportOptimizeFor.wdExportOptimizeForPrint;
                WdExportItem            showMarkup = WdExportItem.wdExportDocumentContent;
                WdExportCreateBookmarks bookmarks  = (Boolean)options["bookmarks"] ?
                                                     WdExportCreateBookmarks.wdExportCreateHeadingBookmarks :
                                                     WdExportCreateBookmarks.wdExportCreateNoBookmarks;
                Options   wdOptions      = null;
                Documents documents      = null;
                Template  normalTemplate = null;

                tmpl = null;
                try
                {
                    word = (Microsoft.Office.Interop.Word.Application)Marshal.GetActiveObject("Word.Application");
                }
                catch (System.Exception)
                {
                    int tries = 10;
                    word    = new Microsoft.Office.Interop.Word.Application();
                    running = false;
                    while (tries > 0)
                    {
                        try
                        {
                            // Try to set a property on the object
                            word.ScreenUpdating = false;
                        }
                        catch (COMException)
                        {
                            // Decrement the number of tries and have a bit of a snooze
                            tries--;
                            Thread.Sleep(500);
                            continue;
                        }
                        // Looks ok, so bail out of the loop
                        break;
                    }
                    if (tries == 0)
                    {
                        ReleaseCOMObject(word);
                        return((int)ExitCode.ApplicationError);
                    }
                }

                wdOptions          = word.Options;
                word.DisplayAlerts = WdAlertLevel.wdAlertsNone;
                // Issue #48 - we should allow control over whether the history is lost
                if (!(Boolean)options["word_keep_history"])
                {
                    word.DisplayRecentFiles = false;
                }
                word.DisplayDocumentInformationPanel = false;
                word.FeatureInstall = Microsoft.Office.Core.MsoFeatureInstall.msoFeatureInstallNone;
                wordVersion         = (float)System.Convert.ToDecimal(word.Version, new CultureInfo("en-US"));

                // Set the Word options in a way that allows us to reset the options when we finish
                try
                {
                    wordOptionList.Add(new AppOption("AlertIfNotDefault", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("AllowReadingMode", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("PrecisePositioning", true, ref wdOptions));
                    wordOptionList.Add(new AppOption("UpdateFieldsAtPrint", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("UpdateLinksAtPrint", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("UpdateLinksAtOpen", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("UpdateFieldsWithTrackedChangesAtPrint", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("WarnBeforeSavingPrintingSendingMarkup", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("BackgroundSave", true, ref wdOptions));
                    wordOptionList.Add(new AppOption("SavePropertiesPrompt", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("DoNotPromptForConvert", true, ref wdOptions));
                    wordOptionList.Add(new AppOption("PromptUpdateStyle", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("ConfirmConversions", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("CheckGrammarAsYouType", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("CheckGrammarWithSpelling", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("CheckSpellingAsYouType", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("DisplaySmartTagButtons", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("EnableLivePreview", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("ShowReadabilityStatistics", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("SuggestSpellingCorrections", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("AllowDragAndDrop", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("EnableMisusedWordsDictionary", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("ShowFormatError", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("StoreRSIDOnSave", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("SaveNormalPrompt", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("AllowFastSave", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("BackgroundOpen", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("ShowMarkupOpenSave", false, ref wdOptions));
                    wordOptionList.Add(new AppOption("SaveInterval", 0, ref wdOptions));
                    wordOptionList.Add(new AppOption("PrintHiddenText", (Boolean)options["word_show_hidden"], ref wdOptions));
                }
                catch (SystemException)
                {
                }

                // Set up the PDF output quality
                if ((Boolean)options["print"])
                {
                    quality = WdExportOptimizeFor.wdExportOptimizeForPrint;
                }
                if ((Boolean)options["screen"])
                {
                    quality = WdExportOptimizeFor.wdExportOptimizeForOnScreen;
                }

                if ((Boolean)options["markup"])
                {
                    showMarkup = WdExportItem.wdExportDocumentWithMarkup;
                }

                if (!String.IsNullOrEmpty((String)options["password"]))
                {
                    readPassword = (String)options["password"];
                }

                if (!String.IsNullOrEmpty((String)options["writepassword"]))
                {
                    writePassword = (String)options["writepassword"];
                }

                // Large Word files may simply not print reliably - if the word_max_pages
                // configuration option is set, then we must close up and forget about
                // converting the file.
                maxPages = (int)options[@"word_max_pages"];

                documents      = word.Documents;
                normalTemplate = word.NormalTemplate;

                // Check for password protection and no password
                if (IsPasswordProtected(inputFile) && String.IsNullOrEmpty(readPassword))
                {
                    normalTemplate.Saved = true;
                    throw new Exception("Unable to open password protected file");
                }

                // If we are opening a document with a write password and no read password, and
                // we are not in read only mode, we should follow the document properties and
                // enforce a read only open. If we do not, Word pops up a dialog
                if (!nowrite && String.IsNullOrEmpty(writePassword) && IsReadOnlyEnforced(inputFile))
                {
                    nowrite = true;
                }

                // Having signatures means we should open the document very carefully
                if (hasSignatures)
                {
                    nowrite       = true;
                    autosave      = false;
                    openAndRepair = false;
                }

                Document doc = null;
                try
                {
                    if ((bool)options["merge"] && !String.IsNullOrEmpty((string)options["template"]) &&
                        File.Exists((string)options["template"]) &&
                        System.Text.RegularExpressions.Regex.IsMatch((string)options["template"], @"^.*\.dot[mx]?$", System.Text.RegularExpressions.RegexOptions.IgnoreCase))
                    {
                        // Create a new document based on a template
                        doc = documents.Add((string)options["template"]);
                        Object rStart = 0;
                        Object rEnd   = 0;
                        Range  range  = doc.Range(rStart, rEnd);
                        range.InsertFile(inputFile);
                        ReleaseCOMObject(range);
                        // Make sure we save the file with the original filename so
                        // filename fields update correctly
                        temporaryStorageDir = Path.GetTempFileName();
                        File.Delete(temporaryStorageDir);
                        Directory.CreateDirectory(temporaryStorageDir);
                        doc.SaveAs(Path.Combine(temporaryStorageDir, Path.GetFileName(inputFile)));
                    }
                    else
                    {
                        // Open the source document
                        doc = documents.OpenNoRepairDialog(FileName: filename, ReadOnly: nowrite, PasswordDocument: readPassword, WritePasswordDocument: writePassword, Visible: visible, OpenAndRepair: openAndRepair);
                    }
                }
                catch (COMException)
                {
                    throw new Exception("Unable to open file");
                }

                // Check if there are signatures in the document which changes how we do things
                if (hasSignatures)
                {
                    // Add in a delay to allow signatures to load
                    Thread.Sleep(500);
                }
                else
                {
                    Window docWin     = null;
                    View   docWinView = null;

                    doc.Activate();
                    // Check if there are too many pages
                    if (maxPages > 0)
                    {
                        var pageCount = doc.ComputeStatistics(WdStatistic.wdStatisticPages, false);
                        doc.Saved = true;
                        if (pageCount > maxPages)
                        {
                            throw new Exception(String.Format("Too many pages to process ({0}). More than {1}", pageCount, maxPages));
                        }
                    }

                    // Prevent "property not available" errors, see http://blogs.msmvps.com/wordmeister/2013/02/22/word2013bug-not-available-for-reading/
                    docWin     = doc.ActiveWindow;
                    docWinView = docWin.View;
                    if (wordVersion >= 15)
                    {
                        docWinView.ReadingLayout = false;
                    }

                    // Sometimes the print view will not be available (e.g. for a blog post)
                    // Try and switch view
                    try
                    {
                        docWinView.Type = WdViewType.wdPrintPreview;
                    }
                    catch (Exception) { }

                    // Handle markup
                    if ((Boolean)options["word_show_all_markup"])
                    {
                        options["word_show_comments"]       = true;
                        options["word_show_revs_comments"]  = true;
                        options["word_show_format_changes"] = true;
                        options["word_show_ink_annot"]      = true;
                        options["word_show_ins_del"]        = true;
                    }
                    if ((Boolean)options["word_show_comments"] ||
                        (Boolean)options["word_show_revs_comments"] ||
                        (Boolean)options["word_show_format_changes"] ||
                        (Boolean)options["word_show_ink_annot"] ||
                        (Boolean)options["word_show_ins_del"] ||
                        showMarkup == WdExportItem.wdExportDocumentWithMarkup)
                    {
                        docWinView.MarkupMode = (Boolean)options["word_markup_balloon"] ?
                                                WdRevisionsMode.wdBalloonRevisions : WdRevisionsMode.wdInLineRevisions;
                    }
                    word.PrintPreview                     = false;
                    docWinView.RevisionsView              = WdRevisionsView.wdRevisionsViewFinal;
                    docWinView.ShowRevisionsAndComments   = (Boolean)options["word_show_revs_comments"];
                    docWinView.ShowComments               = (Boolean)options["word_show_comments"];
                    docWinView.ShowFormatChanges          = (Boolean)options["word_show_format_changes"];
                    docWinView.ShowInkAnnotations         = (Boolean)options["word_show_ink_annot"];
                    docWinView.ShowInsertionsAndDeletions = (Boolean)options["word_show_ins_del"];

                    // Try to avoid Word thinking any changes are happening to the document
                    doc.SpellingChecked = true;
                    doc.GrammarChecked  = true;

                    // Changing these properties may be disallowed if the document is protected
                    // and is not signed
                    if (doc.ProtectionType == WdProtectionType.wdNoProtection && !hasSignatures)
                    {
                        if (autosave)
                        {
                            doc.Save(); doc.Saved = true;
                        }
                        doc.TrackMoves      = false;
                        doc.TrackRevisions  = false;
                        doc.TrackFormatting = false;

                        if ((Boolean)options["word_fix_table_columns"])
                        {
                            FixWordTableColumnWidths(doc);
                        }
                    }

                    normalTemplate.Saved = true;

                    // Hide the document window if need be
                    if ((Boolean)options["hidden"])
                    {
                        word.Visible = false;
                        var activeWin = word.ActiveWindow;
                        activeWin.Visible     = false;
                        activeWin.WindowState = WdWindowState.wdWindowStateMinimize;
                        ReleaseCOMObject(activeWin);
                    }

                    // Check if we have a template file to apply to this document
                    // The template must be a file and must end in .dot, .dotx or .dotm
                    if (!String.IsNullOrEmpty((String)options["template"]) && !(bool)options["merge"])
                    {
                        string template = (string)options["template"];
                        if (File.Exists(template) && System.Text.RegularExpressions.Regex.IsMatch(template, @"^.*\.dot[mx]?$"))
                        {
                            doc.set_AttachedTemplate(template);
                            doc.UpdateStyles();
                            tmpl = doc.get_AttachedTemplate();
                        }
                        else
                        {
                            // Console.WriteLine("Invalid template '{0}'", template);
                        }
                    }

                    // See if we have to update fields
                    if (!(Boolean)options["word_no_field_update"])
                    {
                        UpdateDocumentFields(doc, word, inputFile, options);
                    }

                    var pageSetup = doc.PageSetup;
                    if ((float)options["word_header_dist"] >= 0)
                    {
                        pageSetup.HeaderDistance = (float)options["word_header_dist"];
                    }
                    if ((float)options["word_footer_dist"] >= 0)
                    {
                        pageSetup.FooterDistance = (float)options["word_footer_dist"];
                    }
                    ReleaseCOMObject(pageSetup);
                    try
                    {
                        // Make sure we are not in a header footer view
                        docWinView.SeekView = WdSeekView.wdSeekPrimaryHeader;
                        docWinView.SeekView = WdSeekView.wdSeekPrimaryFooter;
                        docWinView.SeekView = WdSeekView.wdSeekMainDocument;
                    }
                    catch (Exception)
                    {
                        // We might fail when switching views
                    }

                    normalTemplate.Saved = true;
                    if (autosave)
                    {
                        doc.Save();
                    }
                    doc.Saved = true;
                    ReleaseCOMObject(docWinView);
                    ReleaseCOMObject(docWin);
                }

                // Set up a delegate function if we're using a printer
                PrintDocument printFunc = delegate(string destination, string printerName)
                {
                    word.ActivePrinter = printerName;
                    doc.PrintOut(Background: false, OutputFileName: destination);
                };

                // Enable screen updating before exporting to ensure that Word
                // renders borders correctly
                word.ScreenUpdating = true;

                if (String.IsNullOrEmpty((string)options["printer"]))
                {
                    // No printer given, so export
                    try
                    {
                        doc.ExportAsFixedFormat(outputFile, WdExportFormat.wdExportFormatPDF, false,
                                                quality, WdExportRange.wdExportAllDocument,
                                                1, 1, showMarkup, includeProps, true, bookmarks, includeTags, bitmapMissingFonts, pdfa);
                    } catch (Exception)
                    {
                        // Couldn't export, so see if there is a fallback printer
                        if (!String.IsNullOrEmpty((string)options["fallback_printer"]))
                        {
                            PrintToGhostscript((string)options["fallback_printer"], outputFile, printFunc);
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
                else
                {
                    PrintToGhostscript((string)options["printer"], outputFile, printFunc);
                }

                if (tmpl != null)
                {
                    tmpl.Saved = true;
                }

                object saveChanges = autosave? WdSaveOptions.wdSaveChanges : WdSaveOptions.wdDoNotSaveChanges;
                if (nowrite)
                {
                    doc.Saved = true;
                }
                normalTemplate.Saved = true;
                ((_Document)doc).Close(ref saveChanges, ref oMissing, ref oMissing);

                // Reset options
                foreach (AppOption opt in wordOptionList)
                {
                    opt.ResetValue(ref wdOptions);
                }

                ReleaseCOMObject(wdOptions);
                ReleaseCOMObject(documents);
                ReleaseCOMObject(doc);
                ReleaseCOMObject(tmpl);
                ReleaseCOMObject(normalTemplate);

                return((int)ExitCode.Success);
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
            finally
            {
                if (temporaryStorageDir != null && Directory.Exists(temporaryStorageDir))
                {
                    try
                    {
                        if (File.Exists(Path.Combine(temporaryStorageDir, Path.GetFileName(inputFile))))
                        {
                            File.Delete(Path.Combine(temporaryStorageDir, Path.GetFileName(inputFile)));
                        }
                        Directory.Delete(temporaryStorageDir);
                    }
                    catch (Exception) { }
                }
                if (word != null && !running)
                {
                    CloseWordApplication(word);
                }
                ReleaseCOMObject(word);
            }
        }