/// <summary> /// Creates this object and sets it's needed properties /// </summary> /// <param name="chromeExeFileName">When set then this has to be tThe full path to the chrome executable. /// When not set then then the converter tries to find Chrome.exe by first looking in the path /// where this library exists. After that it tries to find it by looking into the registry</param> /// <param name="portRange"> /// Force the converter to pick a port from the given range. When not set then the port range 9222 /// - 9322 is used /// </param> /// <param name="userProfile"> /// If set then this directory will be used to store a user profile. /// Leave blank or set to <c>null</c> if you want to use the default Chrome userprofile location /// </param> /// <param name="logStream">When set then logging is written to this stream</param> /// <exception cref="FileNotFoundException">Raised when <see cref="chromeExeFileName" /> does not exists</exception> /// <exception cref="DirectoryNotFoundException"> /// Raised when the <paramref name="userProfile" /> directory is given but /// does not exists /// </exception> public Converter(string chromeExeFileName = null, PortRangeSettings portRange = null, string userProfile = null, Stream logStream = null) { _logStream = logStream; ResetArguments(); if (string.IsNullOrWhiteSpace(chromeExeFileName)) { chromeExeFileName = ChromeLocation; } if (string.IsNullOrEmpty(chromeExeFileName)) { throw new FileNotFoundException("Could not find chrome.exe"); } _chromeExeFileName = chromeExeFileName; _portRange = portRange; if (!string.IsNullOrWhiteSpace(userProfile)) { var userProfileDirectory = new DirectoryInfo(userProfile); if (!userProfileDirectory.Exists) { throw new DirectoryNotFoundException( $"The directory '{userProfileDirectory.FullName}' does not exists"); } SetDefaultArgument("user-data-dir", $"\"{userProfileDirectory.FullName}\""); } }
/// <summary> /// This function is started from a <see cref="Task"/> and processes <see cref="ConversionItem"/>'s /// that are in the <see cref="_itemsToConvert"/> queue /// </summary> /// <param name="options"></param> /// <param name="portRangeSettings"></param> /// <param name="instanceId"></param> private static void ConvertWithTask(Options options, PortRangeSettings portRangeSettings, string instanceId) { var pageSettings = GetPageSettings(options); using (var converter = new Converter(options.ChromeLocation, portRangeSettings, logStream: Console.OpenStandardOutput())) { converter.InstanceId = instanceId; SetConverterSettings(converter, options); while (!_itemsToConvert.IsEmpty) { if (!_itemsToConvert.TryDequeue(out var itemToConvert)) { continue; } try { converter.ConvertToPdf(itemToConvert.InputUri, itemToConvert.OutputFile, pageSettings, options.WaitForNetworkIdle); itemToConvert.SetStatus(ConversionItemStatus.Success); } catch (Exception exception) { itemToConvert.SetStatus(ConversionItemStatus.Failed, exception); } _itemsConverted.Enqueue(itemToConvert); } } }
/// <summary> /// Parses the port(range) settings from the commandline /// </summary> /// <param name="options"><see cref="Options"/></param> /// <param name="result"></param> /// <param name="portRangeSettings"><see cref="PortRangeSettings"/></param> /// <returns><c>true</c> when the portrange options are valid</returns> private static bool GetPortRangeSettings(Options options, out string result, out PortRangeSettings portRangeSettings) { int start; var end = 0; result = string.Empty; portRangeSettings = null; var portRangeParts = options.PortRange.Split('-'); if (portRangeParts.Length > 2) { result = "Portrange should only contain 1 or 2 parts, e.g 9222 or 9222-9322"; return(false); } switch (portRangeParts.Length) { case 2: if (!int.TryParse(portRangeParts[0], out start)) { result = $"The start port {portRangeParts[0]} is not valid"; return(false); } if (!int.TryParse(portRangeParts[1], out end)) { result = $"The end port {portRangeParts[1]} is not valid"; return(false); } if (start >= end) { result = "The end port needs to be bigger then the start port"; return(false); } break; case 1: if (!int.TryParse(portRangeParts[0], out start)) { result = $"The port {portRangeParts[0]} is not valid"; return(false); } break; default: result = "Port(range) is blank"; return(false); } portRangeSettings = new PortRangeSettings(start, end); return(true); }
/// <summary> /// Parses the commandline parameters and returns these as an <paramref name="options"/> and /// <paramref name="portRangeSettings"/> object /// </summary> /// <param name="args"></param> /// <param name="options"><see cref="Options"/></param> /// <param name="portRangeSettings"><see cref="PortRangeSettings"/></param> private static void ParseCommandlineParameters(IEnumerable <string> args, out Options options, out PortRangeSettings portRangeSettings) { Options tempOptions = null; options = null; var errors = false; var parser = new Parser(settings => { settings.CaseInsensitiveEnumValues = true; settings.CaseSensitive = true; settings.HelpWriter = null; settings.IgnoreUnknownArguments = false; settings.ParsingCulture = CultureInfo.InvariantCulture; }); var parserResult = parser.ParseArguments <Options>(args).WithNotParsed(notParsed => { errors = notParsed.Any(); } ).WithParsed(parsed => { tempOptions = parsed; }); options = tempOptions; portRangeSettings = null; string result = null; if (errors || !GetPortRangeSettings(options, out result, out portRangeSettings)) { var helpText = HelpText.AutoBuild(parserResult); helpText.AddPreOptionsText("Example usage:"); helpText.AddPreOptionsText(" ChromeHtmlToPdf --input https://www.google.nl --output c:\\google.pdf"); if (!string.IsNullOrWhiteSpace(result)) { helpText.AddPreOptionsText(result); } helpText.AddEnumValuesToHelpText = true; helpText.AdditionalNewLineAfterOption = false; helpText.AddOptions(parserResult); helpText.AddPostOptionsLine("Contact:"); helpText.AddPostOptionsLine(" If you experience bugs or want to request new features please visit"); helpText.AddPostOptionsLine(" https://github.com/Sicos1977/ChromeHtmlToPdf/issues"); helpText.AddPostOptionsLine(string.Empty); Console.Error.Write(helpText); Environment.Exit(1); } }
/// <summary> /// Convert a single <see cref="ConversionItem"/> to PDF /// </summary> /// <param name="options"></param> /// <param name="portRangeSettings"></param> private static void Convert(Options options, PortRangeSettings portRangeSettings) { var pageSettings = GetPageSettings(options); using (var converter = new Converter(options.ChromeLocation, portRangeSettings, logStream: Console.OpenStandardOutput())) { SetConverterSettings(converter, options); converter.ConvertToPdf(new Uri(options.Input), options.Output, pageSettings, options.WaitForNetworkIdle, options.WaitForWindowStatus, options.WaitForWindowStatusTimeOut); } }
/// <summary> /// Returns an unused port /// </summary> /// <param name="portRange">The port range to use</param> /// <returns></returns> private static int GetUnusedPort(PortRangeSettings portRange) { var startPort = 9222; var endPort = 9322; if (portRange != null) { startPort = portRange.Start; endPort = portRange.End; } var properties = IPGlobalProperties.GetIPGlobalProperties(); var tcpEndPoints = properties.GetActiveTcpListeners(); var usedPorts = tcpEndPoints.Select(p => p.Port).ToList(); var unusedPort = Enumerable.Range(startPort, endPort - startPort) .FirstOrDefault(port => !usedPorts.Contains(port)); return(unusedPort); }