public void MakePdf(string inputHtmlPath, string outputPdfPath, string paperSizeName,
			bool landscape, bool saveMemoryMode, Control owner, BackgroundWorker worker, DoWorkEventArgs doWorkEventArgs)
        {
            #if !__MonoCS__
            // Mono doesn't current provide System.Printing.  Leave the 'if' here to emphasize the
            // system specific nature of the following check.
            if (Platform.IsWindows)
            {
                // Check whether we have a default printer set (or for that matter, any printers).
                // Gecko on Windows requires a default printer for any print operation, even one
                // to a file.  See https://jira.sil.org/browse/BL-1237.
                string errorMessage = null;
                System.Printing.LocalPrintServer printServer = null;
                try
                {
                    printServer = new System.Printing.LocalPrintServer();
                }
                catch (Exception) // System.Printing.PrintQueueException isn't in our System.Printing assembly, so... using Exception
                {
                    // http://issues.bloomlibrary.org/youtrack/issue/BL-4060
                    Logger.WriteEvent("reproduced BL-4060 when trying to create LocalPrinterServer");
                }
                if (printServer == null || !printServer.GetPrintQueues().Any())
                {
                    errorMessage = GetNoDefaultPrinterErrorMessage();
                }
                else
                {
                    System.Printing.PrintQueue defaultPrinter;
                    // BL-2535 it's possible get past the above printQueues.Any() but then get
                    // a System.Printing.PrintQueueException exception with "Access Denied" error here, if
                    // the default printer for some reason is no longer "allowed".
                    try
                    {
                        defaultPrinter = System.Printing.LocalPrintServer.GetDefaultPrintQueue();

                        if(defaultPrinter == null || String.IsNullOrEmpty(defaultPrinter.FullName))
                        {
                            errorMessage = GetNoDefaultPrinterErrorMessage();
                        }
                    }
                    catch(Exception error) // System.Printing.PrintQueueException isn't in our System.Printing assembly, so... using Exception
                    {
                        defaultPrinter = null;
                        errorMessage = L10NSharp.LocalizationManager.GetDynamicString(@"Bloom", @"MakePDF.PrinterError",
                            "Bloom requires access to a printer in order to make a PDF, even though you are not printing.  Windows gave this error when Bloom tried to access the default printer: {0}",
                            @"Error message displayed in a message dialog box");
                        errorMessage = string.Format(errorMessage, error.Message);
                    }
                }
                if (errorMessage !=null)
                {
                    var exception = new ApplicationException(errorMessage);
                    // Note that if we're being run by a BackgroundWorker, it will catch the exception.
                    // If not, but the caller provides a DoWorkEventArgs, pass the exception through
                    // that object rather than throwing it.
                    if (worker != null || doWorkEventArgs == null)
                        throw exception;
                    doWorkEventArgs.Result = exception;
                    return;
                }
            }
            #endif
            var runner = new CommandLineRunner();
            string exePath;
            var bldr = new StringBuilder();
            // Codebase is reliable even when Resharper copies the EXE somewhere else for testing.
            var loc = Assembly.GetExecutingAssembly().CodeBase.Substring((Platform.IsUnix ? "file://" : "file:///").Length);
            var execDir = Path.GetDirectoryName(loc);
            var fromDirectory = String.Empty;
            var filePath = Path.Combine(execDir, "BloomPdfMaker.exe");
            if (!RobustFile.Exists(filePath))
            {
                var msg = LocalizationManager.GetString("InstallProblem.BloomPdfMaker",
                    "A component of Bloom, BloomPdfMaker.exe, seems to be missing. This prevents previews and printing. Antivirus software sometimes does this. You may need technical help to repair the Bloom installation and protect this file from being deleted again.");
                throw new FileNotFoundException(msg, "BloomPdfMaker.exe"); // must be this class to trigger the right reporting mechanism.
            }
            if (Platform.IsMono)
            {
                exePath = "mono";
                bldr.AppendFormat("--debug \"{0}\" ", filePath);
            }
            else
            {
                exePath = filePath;
            }
            SetArguments(bldr, inputHtmlPath, outputPdfPath, paperSizeName, landscape, saveMemoryMode);
            var arguments = bldr.ToString();
            var progress = new NullProgress();
            var res = runner.Start(exePath, arguments, Encoding.UTF8, fromDirectory, 3600, progress, null);
            if (res.DidTimeOut || !RobustFile.Exists (outputPdfPath))
            {
                Logger.WriteEvent(@"***ERROR PDF generation failed: res.StandardOutput = "+res.StandardOutput);

                var msg = L10NSharp.LocalizationManager.GetDynamicString(@"Bloom", @"MakePDF.Failed",
                    "Bloom was not able to create the PDF file ({0}).{1}{1}Details: BloomPdfMaker (command line) did not produce the expected document.",
                    @"Error message displayed in a message dialog box. {0} is the filename, {1} is a newline character.");

                // This message string is intentionally separate because it was added after the previous string had already been localized in most languages.
                var msg2 = L10NSharp.LocalizationManager.GetDynamicString(@"Bloom", @"MakePDF.TrySinglePage",
                    "The book's images might have exceeded the amount of RAM memory available. Please turn on the \"Use Less Memory\" option which is slower but uses less memory.",
                    @"Error message displayed in a message dialog box");

                var fullMsg = String.Format(msg, outputPdfPath, Environment.NewLine) + Environment.NewLine + msg2 + Environment.NewLine + res.StandardOutput;

                var except = new ApplicationException(fullMsg);
                // Note that if we're being run by a BackgroundWorker, it will catch the exception.
                // If not, but the caller provides a DoWorkEventArgs, pass the exception through
                // that object rather than throwing it.
                if (worker != null || doWorkEventArgs == null)
                    throw except;
                else
                    doWorkEventArgs.Result = except;
            }
        }
Пример #2
0
        /// <summary>
        ///
        /// </summary>
        /// <returns>false if it couldn't start</returns>
        public bool Start()
        {
            try
            {
                foreach (var hg in Process.GetProcessesByName("hg"))
                {
                    //EventLog.WriteEntry("Application", "Killing old hg...", EventLogEntryType.Information);
                    hg.Kill();
                    if (!hg.WaitForExit(10000))
                    {
                        //EventLog.WriteEntry("Application", "ChorusHub was unable to stop an old hg from running. It will now give up. You should stop the server and run it again after killing whatever 'hg.exe' process is running.", EventLogEntryType.Error);
                        return false;
                    }
                }

                //we make directories based on what we see in there, so start it afresh lest we re-create folder names
                //that the user long ago stopped using

                if (File.Exists(AccessLogPath))
                    File.Delete(AccessLogPath);

                if (!Directory.Exists(_rootFolder))
                    Directory.CreateDirectory(_rootFolder);

                //EventLog.WriteEntry("Application", "Starting Mercurial Server", EventLogEntryType.Information);

                WriteConfigFile(_rootFolder);

                var arguments = "serve -A accessLog.txt -E log.txt -p " + Port + " --verbose ";

                const float kHgVersion = (float)1.5;
                if (kHgVersion < 1.9)
                {
                    arguments += "--webdir-conf hgweb.config";
                }
                else
                {
                    arguments += "--web-conf hgweb.config";
                }

            #if CommandWindow
                _hgServeProcess = new Process();
                _hgServeProcess.StartInfo.WorkingDirectory = _rootFolder;
                _hgServeProcess.StartInfo.FileName = Chorus.MercurialLocation.PathToHgExecutable;
                _hgServeProcess.StartInfo.Arguments = arguments;
                _hgServeProcess.StartInfo.ErrorDialog = true;
                _hgServeProcess.StartInfo.UseShellExecute = false;
                _hgServeProcess.StartInfo.RedirectStandardOutput = true;
                _hgServeProcess.Start();
            #else
                _hgServeThread = new Thread(() =>
                                                {
                                                    var commandLineRunner = new CommandLineRunner();
                                                    try
                                                    {
                                                        var progress = new ConsoleProgress();
                                                        commandLineRunner.Start(
                                                            Chorus.MercurialLocation.PathToHgExecutable,
                                                            arguments,
                                                            Encoding.UTF8, _rootFolder, -1,
                                                            progress, s => progress.WriteMessage(s));
                                                    }
                                                    catch (ThreadAbortException)
                                                    {
                                                        //Progress.WriteVerbose("Hg Serve command Thread Aborting (that's normal when stopping)");
                                                        try
                                                        {
                                                            if (!commandLineRunner.Abort(1))
                                                            {
                                                                //EventLog.WriteEntry("Application", "Hg Serve might not have closed down.", EventLogEntryType.Information);
                                                            }
                                                        }
                                                        catch { }

                                                    }
                                                });
                _hgServeThread.Start();
            #endif

                return true;
            }
            catch (Exception error)
            {
                //EventLog.WriteEntry("Application", error.Message, EventLogEntryType.Error);
                return false;
            }
        }