static void Main(string[] args) { string[] files = new string[2]; int filesSeen = 0; Boolean postProcessPDF = false; Boolean postProcessPDFSecurity = false; Hashtable options = new Hashtable(); List <PDFBookmark> documentBookmarks = new List <PDFBookmark>(); // Loop through the input, grabbing switches off the command line options["hidden"] = false; options["markup"] = false; options["readonly"] = false; options["bookmarks"] = false; options["print"] = true; options["screen"] = false; options["pdfa"] = false; options["verbose"] = false; options["excludeprops"] = false; options["excludetags"] = false; options["noquit"] = false; options["merge"] = false; options["template"] = ""; options["password"] = ""; options["excel_show_formulas"] = false; options["excel_show_headings"] = false; options["excel_auto_macros"] = false; options["excel_template_macros"] = false; options["excel_active_sheet"] = false; options["excel_no_link_update"] = false; options["excel_no_recalculate"] = false; options["excel_max_rows"] = (int)0; options["excel_worksheet"] = (int)0; options["word_field_quick_update"] = false; options["word_field_quick_update_safe"] = false; options["word_no_field_update"] = false; options["word_header_dist"] = (float)-1; options["word_footer_dist"] = (float)-1; options["word_max_pages"] = (int)0; options["word_ref_fonts"] = false; options["word_keep_history"] = false; options["original_filename"] = ""; options["original_basename"] = ""; options["pdf_page_mode"] = null; options["pdf_layout"] = null; options["pdf_merge"] = (int)MergeMode.None; options["pdf_clean_meta"] = (int)MetaClean.None; options["pdf_owner_pass"] = ""; options["pdf_user_pass"] = ""; options["pdf_restrict_annotation"] = false; options["pdf_restrict_extraction"] = false; options["pdf_restrict_assembly"] = false; options["pdf_restrict_forms"] = false; options["pdf_restrict_modify"] = false; options["pdf_restrict_print"] = false; options["pdf_restrict_annotation"] = false; options["pdf_restrict_accessibility_extraction"] = false; options["pdf_restrict_full_quality"] = false; Regex switches = new Regex(@"^/(version|hidden|markup|readonly|bookmarks|merge|noquit|print|screen|pdfa|template|writepassword|password|help|verbose|exclude(props|tags)|excel_(max_rows|show_formulas|show_headings|auto_macros|template_macros|active_sheet|worksheet|no_recalculate|no_link_update)|word_(header_dist|footer_dist|ref_fonts|no_field_update|field_quick_update(_safe)?|max_pages|keep_history)|pdf_(page_mode|append|prepend|layout|clean_meta|owner_pass|user_pass|restrict_(annotation|extraction|assembly|forms|modify|print|accessibility_extraction|full_quality))|\?)$", RegexOptions.IgnoreCase); for (int argIdx = 0; argIdx < args.Length; argIdx++) { string item = args[argIdx]; // see if this starts with a / Match m = Regex.Match(item, @"^/"); if (m.Success) { // This is an option Match itemMatch = switches.Match(item); if (itemMatch.Success) { if (itemMatch.Groups[1].Value.ToLower().Equals("help") || itemMatch.Groups[1].Value.Equals("?")) { showHelp(); } switch (itemMatch.Groups[1].Value.ToLower()) { case "pdf_page_mode": if (argIdx + 2 < args.Length) { postProcessPDF = true; var pageMode = args[argIdx + 1]; pageMode = pageMode.ToLower(); switch (pageMode) { case "full": options["pdf_page_mode"] = PdfPageMode.FullScreen; break; case "none": options["pdf_page_mode"] = PdfPageMode.UseNone; break; case "bookmarks": options["pdf_page_mode"] = PdfPageMode.UseOutlines; break; case "thumbs": options["pdf_page_mode"] = PdfPageMode.UseThumbs; break; default: Console.WriteLine("Invalid PDF page mode ({0}). It must be one of full, none, outline or thumbs", args[argIdx + 1]); Environment.Exit((int)(ExitCode.Failed | ExitCode.InvalidArguments)); break; } argIdx++; } break; case "pdf_clean_meta": if (argIdx + 2 < args.Length) { postProcessPDF = true; var cleanType = args[argIdx + 1]; cleanType = cleanType.ToLower(); switch (cleanType) { case "basic": options["pdf_clean_meta"] = MetaClean.Basic; break; case "full": options["pdf_clean_meta"] = MetaClean.Full; break; default: Console.WriteLine("Invalid PDF meta-data clean value ({0}). It must be one of full or basic", args[argIdx + 1]); Environment.Exit((int)(ExitCode.Failed | ExitCode.InvalidArguments)); break; } argIdx++; } break; case "pdf_layout": if (argIdx + 2 < args.Length) { postProcessPDF = true; var pdfLayout = args[argIdx + 1]; pdfLayout = pdfLayout.ToLower(); switch (pdfLayout) { case "onecol": options["pdf_layout"] = PdfPageLayout.OneColumn; break; case "single": options["pdf_layout"] = PdfPageLayout.SinglePage; break; case "twocolleft": options["pdf_layout"] = PdfPageLayout.TwoColumnLeft; break; case "twocolright": options["pdf_layout"] = PdfPageLayout.TwoColumnRight; break; case "twopageleft": options["pdf_layout"] = PdfPageLayout.TwoPageLeft; break; case "twopageright": options["pdf_layout"] = PdfPageLayout.TwoPageRight; break; default: Console.WriteLine("Invalid PDF layout ({0}). It must be one of onecol, single, twocolleft, twocolright, twopageleft or twopageright", args[argIdx + 1]); Environment.Exit((int)(ExitCode.Failed | ExitCode.InvalidArguments)); break; } argIdx++; } break; case "pdf_owner_pass": case "pdf_user_pass": if (argIdx + 2 < args.Length) { postProcessPDF = true; postProcessPDFSecurity = true; var pass = args[argIdx + 1]; // Set the password options[itemMatch.Groups[1].Value.ToLower()] = pass; argIdx++; } break; case "template": // Only accept the next option if there are enough options if (argIdx + 2 < args.Length) { if (File.Exists(args[argIdx + 1])) { FileInfo templateInfo = new FileInfo(args[argIdx + 1]); options[itemMatch.Groups[1].Value.ToLower()] = templateInfo.FullName; } else { Console.WriteLine("Unable to find {0} {1}", itemMatch.Groups[1].Value.ToLower(), args[argIdx + 1]); } argIdx++; } break; case "excel_max_rows": // Only accept the next option if there are enough options if (argIdx + 2 < args.Length) { if (Regex.IsMatch(args[argIdx + 1], @"^\d+$")) { options[itemMatch.Groups[1].Value.ToLower()] = (int)Convert.ToInt32(args[argIdx + 1]); } else { Console.WriteLine("Maximum number of rows ({0}) is invalid", args[argIdx + 1]); Environment.Exit((int)(ExitCode.Failed | ExitCode.InvalidArguments)); } argIdx++; } break; case "excel_worksheet": // Only accept the next option if there are enough options if (argIdx + 2 < args.Length) { if (Regex.IsMatch(args[argIdx + 1], @"^\d+$")) { options[itemMatch.Groups[1].Value.ToLower()] = (int)Convert.ToInt32(args[argIdx + 1]); } else { Console.WriteLine("Excel worksheet ({0}) is invalid", args[argIdx + 1]); Environment.Exit((int)(ExitCode.Failed | ExitCode.InvalidArguments)); } argIdx++; } break; case "word_header_dist": case "word_footer_dist": // Only accept the next option if there are enough options if (argIdx + 2 < args.Length) { if (Regex.IsMatch(args[argIdx + 1], @"^[\d\.]+$")) { try { options[itemMatch.Groups[1].Value.ToLower()] = (float)Convert.ToDouble(args[argIdx + 1]); } catch (Exception) { Console.WriteLine("Header/Footer distance ({0}) is invalid", args[argIdx + 1]); Environment.Exit((int)(ExitCode.Failed | ExitCode.InvalidArguments)); } } else { Console.WriteLine("Header/Footer distance ({0}) is invalid", args[argIdx + 1]); Environment.Exit((int)(ExitCode.Failed | ExitCode.InvalidArguments)); } argIdx++; } break; case "word_max_pages": // Only accept the next option if there are enough options if (argIdx + 2 < args.Length) { if (Regex.IsMatch(args[argIdx + 1], @"^\d+$")) { options[itemMatch.Groups[1].Value.ToLower()] = (int)Convert.ToInt32(args[argIdx + 1]); } else { Console.WriteLine("Maximum number of pages ({0}) is invalid", args[argIdx + 1]); Environment.Exit((int)(ExitCode.Failed | ExitCode.InvalidArguments)); } argIdx++; } break; case "password": case "writepassword": // Only accept the next option if there are enough options if (argIdx + 2 < args.Length) { options[itemMatch.Groups[1].Value.ToLower()] = args[argIdx + 1]; argIdx++; } break; case "screen": options["print"] = false; options[itemMatch.Groups[1].Value.ToLower()] = true; break; case "print": options["screen"] = false; options[itemMatch.Groups[1].Value.ToLower()] = true; break; case "version": Assembly asm = Assembly.GetExecutingAssembly(); FileVersionInfo fv = System.Diagnostics.FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location); Console.WriteLine(String.Format("{0}", fv.FileVersion)); Environment.Exit((int)ExitCode.Success); break; case "pdf_append": if ((MergeMode)options["pdf_merge"] != MergeMode.None) { Console.WriteLine("Only one of /pdf_append or /pdf_prepend can be used"); Environment.Exit((int)(ExitCode.Failed | ExitCode.InvalidArguments)); } postProcessPDF = true; options["pdf_merge"] = MergeMode.Append; break; case "pdf_prepend": if ((MergeMode)options["pdf_merge"] != MergeMode.None) { Console.WriteLine("Only one of /pdf_append or /pdf_prepend can be used"); Environment.Exit((int)(ExitCode.Failed | ExitCode.InvalidArguments)); } postProcessPDF = true; options["pdf_merge"] = MergeMode.Prepend; break; case "pdf_restrict_annotation": case "pdf_restrict_extraction": case "pdf_restrict_assembly": case "pdf_restrict_forms": case "pdf_restrict_modify": case "pdf_restrict_print": case "pdf_restrict_full_quality": case "pdf_restrict_accessibility_extraction": postProcessPDFSecurity = true; options[itemMatch.Groups[1].Value.ToLower()] = true; break; default: options[itemMatch.Groups[1].Value.ToLower()] = true; break; } } else { Console.WriteLine("Unknown option: {0}", item); Environment.Exit((int)(ExitCode.Failed | ExitCode.InvalidArguments)); } } else if (filesSeen < 2) { files[filesSeen++] = item; } } // Need to error here, as we need input and output files as the // arguments to this script if (filesSeen != 1 && filesSeen != 2) { showHelp(); } // Make sure we only choose one of /screen or /print options if ((Boolean)options["screen"] && (Boolean)options["print"]) { Console.WriteLine("You can only use one of /screen or /print - not both"); Environment.Exit((int)(ExitCode.Failed | ExitCode.InvalidArguments)); } // Make sure the input file looks like something we can handle (i.e. has an office // filename extension) Regex fileMatch = new Regex(@"\.(((ppt|pps|pot|do[ct]|xls|xlt)[xm]?)|xlsb|od[spt]|rtf|csv|vsd[xm]?|vd[xw]|em[fz]|dwg|dxf|wmf|pub|msg|vcf|ics|mpp|svg|txt|html?|wpd)$", RegexOptions.IgnoreCase); if (fileMatch.Matches(files[0]).Count != 1) { Console.WriteLine("Input file can not be handled. Must be Word, PowerPoint, Excel, Outlook, Publisher or Visio"); Environment.Exit((int)(ExitCode.Failed | ExitCode.UnsupportedFileFormat)); } if (filesSeen == 1) { // If only one file is seen, we just swap the extension files[1] = Path.ChangeExtension(files[0], "pdf"); } else { // If the second file is a directory, then we want to create the PDF // with the same name as the original (changing the extension to pdf), // but in the directory given by the path if (Directory.Exists(files[1])) { files[1] = Path.Combine(files[1], Path.GetFileNameWithoutExtension(files[0]) + ".pdf"); } } String inputFile = ""; String outputFile = ""; String finalOutputFile = ""; // Make sure the input file exists and is readable FileInfo info; try { info = new FileInfo(files[0]); if (info == null || !info.Exists) { Console.WriteLine("Input file doesn't exist"); Environment.Exit((int)(ExitCode.Failed | ExitCode.FileNotFound)); } inputFile = info.FullName; options["original_filename"] = info.Name; options["original_basename"] = info.Name.Substring(0, info.Name.Length - info.Extension.Length); } catch { Console.WriteLine("Unable to open input file"); Environment.Exit((int)(ExitCode.Failed | ExitCode.FileOpenFailure)); } // Make sure the destination location exists FileInfo outputInfo = new FileInfo(files[1]); // Remove the destination unless we're doing a PDF merge if (outputInfo != null) { outputFile = finalOutputFile = 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 { Console.WriteLine("Unable to determine output location"); Environment.Exit((int)(ExitCode.Failed | ExitCode.DirectoryNotFound)); } if (!System.IO.Directory.Exists(outputInfo.DirectoryName)) { Console.WriteLine("Output directory does not exist"); Environment.Exit((int)(ExitCode.Failed | ExitCode.DirectoryNotFound)); } // Now, do the cleverness of determining what the extension is, and so, which // conversion class to pass it to int converted = (int)ExitCode.UnknownError; Match extMatch = fileMatch.Match(inputFile); if (extMatch.Success) { // Set and environment variable so Office application VBA // code can check for un-attended conversion and avoid showing // blocking dialogs Environment.SetEnvironmentVariable("OFFICE2PDF_AUTO_CONVERT", "1"); if ((Boolean)options["verbose"]) { Console.WriteLine("Converting {0} to {1}", inputFile, finalOutputFile); } switch (extMatch.Groups[1].ToString().ToLower()) { case "rtf": case "odt": case "doc": case "dot": case "docx": case "dotx": case "docm": case "dotm": case "txt": case "html": case "htm": case "wpd": // Word if ((Boolean)options["verbose"]) { Console.WriteLine("Converting with Word converter"); } converted = WordConverter.Convert(inputFile, outputFile, options); break; case "csv": case "ods": case "xls": case "xlsx": case "xlt": case "xltx": case "xlsm": case "xltm": case "xlsb": // Excel if ((Boolean)options["verbose"]) { Console.WriteLine("Converting with Excel converter"); } converted = ExcelConverter.Convert(inputFile, outputFile, options); break; case "odp": case "ppt": case "pptx": case "pptm": case "pot": case "potm": case "potx": case "pps": case "ppsx": case "ppsm": // Powerpoint if ((Boolean)options["verbose"]) { Console.WriteLine("Converting with Powerpoint converter"); } converted = PowerpointConverter.Convert(inputFile, outputFile, options, ref documentBookmarks); break; case "vsd": case "vsdm": case "vsdx": case "vdx": case "vdw": case "svg": case "emf": case "emz": case "dwg": case "dxf": case "wmf": // Visio if ((Boolean)options["verbose"]) { Console.WriteLine("Converting with Visio converter"); } converted = VisioConverter.Convert(inputFile, outputFile, options); break; case "pub": // Publisher if ((Boolean)options["verbose"]) { Console.WriteLine("Converting with Publisher converter"); } converted = PublisherConverter.Convert(inputFile, outputFile, options, ref documentBookmarks); break; case "msg": case "vcf": case "ics": // Outlook if ((Boolean)options["verbose"]) { Console.WriteLine("Converting with Outlook converter"); } converted = OutlookConverter.Convert(inputFile, outputFile, options); break; case "mpp": // Project if ((Boolean)options["verbose"]) { Console.WriteLine("Converting with Project converter"); } converted = ProjectConverter.Convert(inputFile, outputFile, options); break; } } if (converted != (int)ExitCode.Success) { Console.WriteLine("Did not convert"); // Return the general failure code and the specific failure code Environment.Exit((int)ExitCode.Failed | converted); } else { if ((Boolean)options["verbose"]) { Console.WriteLine("Completed Conversion"); } if (documentBookmarks.Count > 0) { addPDFBookmarks(outputFile, documentBookmarks, options, null); } // Determine if we have to post-process the PDF if (postProcessPDF) { postProcessPDFFile(outputFile, finalOutputFile, options, postProcessPDFSecurity); } Environment.Exit((int)ExitCode.Success); } }
public static int ConvertOfficeToPDF(string[] args) { string[] files = new string[2]; int filesSeen = 0; Hashtable options = new Hashtable { // Loop through the input, grabbing switches off the command line ["hidden"] = false, ["markup"] = false, ["readonly"] = false, ["bookmarks"] = false, ["print"] = true, ["screen"] = false, ["pdfa"] = false, ["verbose"] = false, ["excludeprops"] = false, ["excludetags"] = false, ["noquit"] = false, ["merge"] = false, ["template"] = "", ["password"] = "", ["excel_show_formulas"] = false, ["excel_show_headings"] = false, ["excel_auto_macros"] = false, ["excel_max_rows"] = (int)0, ["word_header_dist"] = (float)-1, ["word_footer_dist"] = (float)-1 }; Regex switches = new Regex(@"^/(hidden|markup|readonly|bookmarks|merge|noquit|print|screen|pdfa|template|writepassword|password|help|verbose|exclude(props|tags)|excel_max_rows|excel_show_formulas|excel_show_headings|excel_auto_macros|word_header_dist|word_footer_dist|\?)$", RegexOptions.IgnoreCase); for (int argIdx = 0; argIdx < args.Length; argIdx++) { string item = args[argIdx]; // see if this starts with a / Match m = Regex.Match(item, @"^/"); if (m.Success) { // This is an option Match itemMatch = switches.Match(item); if (itemMatch.Success) { if (itemMatch.Groups[1].Value.ToLower().Equals("help") || itemMatch.Groups[1].Value.Equals("?")) { ShowHelp(); } switch (itemMatch.Groups[1].Value.ToLower()) { case "template": // Only accept the next option if there are enough options if (argIdx + 2 < args.Length) { if (File.Exists(args[argIdx + 1])) { FileInfo templateInfo = new FileInfo(args[argIdx + 1]); options[itemMatch.Groups[1].Value.ToLower()] = templateInfo.FullName; } else { message = "Unable to find " + itemMatch.Groups[1].Value.ToLower() + " " + args[argIdx + 1]; } argIdx++; } break; case "excel_max_rows": // Only accept the next option if there are enough options if (argIdx + 2 < args.Length) { if (Regex.IsMatch(args[argIdx + 1], @"^\d+$")) { options[itemMatch.Groups[1].Value.ToLower()] = (int)Convert.ToInt32(args[argIdx + 1]); } else { message = "Maximum number of rows (" + args[argIdx + 1] + ") is invalid"; return((int)(ExitCode.Failed | ExitCode.InvalidArguments)); } argIdx++; } break; case "word_header_dist": case "word_footer_dist": // Only accept the next option if there are enough options if (argIdx + 2 < args.Length) { if (Regex.IsMatch(args[argIdx + 1], @"^[\d\.]+$")) { try { options[itemMatch.Groups[1].Value.ToLower()] = (float)Convert.ToDouble(args[argIdx + 1]); } catch (Exception) { message = "Header/Footer distance (" + args[argIdx + 1] + ") is invalid"; return((int)(ExitCode.Failed | ExitCode.InvalidArguments)); } } else { message = "Header/Footer distance (" + args[argIdx + 1] + ") is invalid"; return((int)(ExitCode.Failed | ExitCode.InvalidArguments)); } argIdx++; } break; case "password": case "writepassword": // Only accept the next option if there are enough options if (argIdx + 2 < args.Length) { options[itemMatch.Groups[1].Value.ToLower()] = args[argIdx + 1]; argIdx++; } break; case "screen": options["print"] = false; options[itemMatch.Groups[1].Value.ToLower()] = true; break; case "print": options["screen"] = false; options[itemMatch.Groups[1].Value.ToLower()] = true; break; default: options[itemMatch.Groups[1].Value.ToLower()] = true; break; } } else { message = "Unknown option: " + item; return((int)(ExitCode.Failed | ExitCode.InvalidArguments)); } } else if (filesSeen < 2) { files[filesSeen++] = item; } } // Need to error here, as we need input and output files as the // arguments to this script if (filesSeen != 1 && filesSeen != 2) { ShowHelp(); } // Make sure we only choose one of /screen or /print options if ((Boolean)options["screen"] && (Boolean)options["print"]) { message = "You can only use one of /screen or /print - not both"; return((int)(ExitCode.Failed | ExitCode.InvalidArguments)); } // Make sure the input file looks like something we can handle (i.e. has an office // filename extension) Regex fileMatch = new Regex(@"\.(((ppt|pps|pot|do[ct]|xls|xlt)[xm]?)|od[cpt]|rtf|csv|vsd[xm]?|pub|msg|vcf|ics|mpp|svg|txt|html?)$", RegexOptions.IgnoreCase); if (fileMatch.Matches(files[0]).Count != 1) { message = "Input file can not be handled. Must be Word, PowerPoint, Excel, Outlook, Publisher or Visio"; return((int)(ExitCode.Failed | ExitCode.UnsupportedFileFormat)); } if (filesSeen == 1) { files[1] = Path.ChangeExtension(files[0], "pdf"); } String inputFile = ""; String outputFile; // Make sure the input file exists and is readable FileInfo info; try { info = new FileInfo(files[0]); if (info == null || !info.Exists) { message = "Input file doesn't exist"; return((int)(ExitCode.Failed | ExitCode.FileNotFound)); } inputFile = info.FullName; } catch { message = "Unable to open input file"; return((int)(ExitCode.Failed | ExitCode.FileOpenFailure)); } // Make sure the destination location exists FileInfo outputInfo = new FileInfo(files[1]); if (outputInfo != null && outputInfo.Exists) { System.IO.File.Delete(outputInfo.FullName); } if (!System.IO.Directory.Exists(outputInfo.DirectoryName)) { message = "Output directory does not exist"; return((int)(ExitCode.Failed | ExitCode.DirectoryNotFound)); } outputFile = outputInfo.FullName; // Now, do the cleverness of determining what the extension is, and so, which // conversion class to pass it to int converted = (int)ExitCode.UnknownError; Match extMatch = fileMatch.Match(inputFile); if (extMatch.Success) { if ((Boolean)options["verbose"]) { message = "Converting " + inputFile + " to " + outputFile; } switch (extMatch.Groups[1].ToString().ToLower()) { case "rtf": case "odt": case "doc": case "dot": case "docx": case "dotx": case "docm": case "dotm": case "txt": case "html": case "htm": // Word if ((Boolean)options["verbose"]) { message = "Converting with Word converter"; } converted = WordConverter.Convert(inputFile, outputFile, options); break; case "csv": case "odc": case "xls": case "xlsx": case "xlt": case "xltx": case "xlsm": case "xltm": // Excel if ((Boolean)options["verbose"]) { message = "Converting with Excel converter"; } converted = ExcelConverter.Convert(inputFile, outputFile, options); break; case "odp": case "ppt": case "pptx": case "pptm": case "pot": case "potm": case "potx": case "pps": case "ppsx": case "ppsm": // Powerpoint if ((Boolean)options["verbose"]) { message = "Converting with Powerpoint converter"; } converted = PowerpointConverter.Convert(inputFile, outputFile, options); break; case "vsd": case "vsdm": case "vsdx": case "svg": // Visio if ((Boolean)options["verbose"]) { message = "Converting with Visio converter"; } converted = VisioConverter.Convert(inputFile, outputFile, options); break; case "pub": // Publisher if ((Boolean)options["verbose"]) { message = "Converting with Publisher converter"; } converted = PublisherConverter.Convert(inputFile, outputFile, options); break; case "msg": case "vcf": case "ics": // Outlook if ((Boolean)options["verbose"]) { message = "Converting with Outlook converter"; } converted = OutlookConverter.Convert(inputFile, outputFile, options); break; case "mpp": // Project if ((Boolean)options["verbose"]) { message = "Converting with Project converter"; } converted = ProjectConverter.Convert(inputFile, outputFile, options); break; } } if (converted != (int)ExitCode.Success) { message = "Did not convert"; // Return the general failure code and the specific failure code return((int)ExitCode.Failed | converted); } else if ((Boolean)options["verbose"]) { message = "Completed Conversion"; } return((int)ExitCode.Success); }