/// <summary>
        /// Gets the implementation of the individual logging framework's logger.
        /// </summary>
        /// <param name="logLocation">The log location.</param>
        /// <returns>TLoggerImplementation.</returns>
        protected override ILogger PerformGetLogger(LogLocation logLocation)
        {
            var     fullName = logLocation.LoggingClassType.FullName;
            ILogger logger;

            if (loggers.TryGetValue(fullName, out logger))
            {
                return(logger);
            }

            var allLoggers = LogManager.GetCurrentLoggers().ToDictionary(log => log.Logger.Name, log => log.Logger);
            var partName   = fullName;

            while (true)
            {
                if (allLoggers.TryGetValue(partName, out logger))
                {
                    loggers[fullName] = logger;
                    return(logger);
                }

                var lastDotPos = partName.LastIndexOf('.');
                if (lastDotPos < 0)
                {
                    break;
                }

                partName = partName.Substring(0, lastDotPos);
            }

            loggers[fullName] = defaultLogger;
            return(defaultLogger);
        }
Exemplo n.º 2
0
        public override void Log(LogLevel logLevel, LogLocation logLocation, string context, string message, Exception exception, params object[] parameters)
        {
            if (message == null)
            {
                return;
            }

            switch (logLevel)
            {
            case LogLevel.Info:
                log.LogMessage(context, null, null, logLocation.File, logLocation.Line, logLocation.Column, 0, 0, Microsoft.Build.Framework.MessageImportance.Normal, message, parameters);
                break;

            case LogLevel.Warning:
                log.LogWarning(context, null, null, logLocation.File, logLocation.Line, logLocation.Column, 0, 0, message, parameters);
                if (exception != null)
                {
                    log.LogWarningFromException(exception);
                }
                break;

            case LogLevel.Error:
            case LogLevel.Fatal:
                log.LogError(context, null, null, logLocation.File, logLocation.Line, logLocation.Column, 0, 0, message, parameters);
                if (exception != null)
                {
                    log.LogErrorFromException(exception, true, true, null);
                }
                break;

            default:
                break;
            }
        }
Exemplo n.º 3
0
        static void Main(string[] args)
        {
            XmlConfigurator.Configure();

            appender = LogManager.GetRepository()
                       .GetAppenders()
                       .OfType <MemoryAppender>()
                       .Single();

            var now = DateTime.UtcNow;

            // Log message through LogBridge
            Time("LogBridge simple message: {0}", () => Log.Warning("Message"));

            // Log formatted message through LogBridge
            Time("LogBridge formatted message: {0}", () => Log.Warning("Message {0} {1} {2} {3}", 42, "87", now, 87.42));

            // Log message with location through LogBridge
            Time("LogBridge simple message with location: {0}", () => Log.Warning(LogLocation.Here(typeof(Program)), "Message"));

            // Log formatted message with location through LogBridge
            Time("LogBridge formatted message with location: {0}", () => Log.Warning(LogLocation.Here(typeof(Program)), "Message {0} {1} {2} {3}", 42, "87", now, 87.42));

            var logger = LogManager.GetLogger("RootLogger");

            // Log message directly through log4net
            Time("Log4Net simple message: {0}", () => logger.WarnFormat("Message"));

            // Log formatted message directly through log4net
            Time("Log4Net formatted message: {0}", () => logger.WarnFormat("Message {0} {1} {2} {3}", 42, "87", now, 87.42));

            Console.WriteLine("Press ENTER to exit.");
            Console.ReadLine();
        }
Exemplo n.º 4
0
 public static LogLocation GetInstacne()
 {
     if (m_Instance == null)
     {
         m_Instance = new LogLocation();
     }
     return(m_Instance);
 }
 private LocationInfo ToLog4NetLocationInfo(LogLocation logLocation)
 {
     return(new LocationInfo(
                logLocation.LoggingClassType.FullName,
                logLocation.MethodName,
                logLocation.FileName,
                logLocation.LineNumber));
 }
Exemplo n.º 6
0
 private static bool OnOpenAsset(int instanceID, int line)
 {
     if (instanceID == LogLocation.GetInstacne().m_DebugerFileInstanceId)//打开资产的id如果是Loger(①通过log打开,②双击打开文件)
     {
         return(GetInstacne().FindCode());
     }
     return(false);
 }
Exemplo n.º 7
0
        public override void Log(LogLevel logLevel, LogLocation logLocation, string context, string message, Exception exception, params object[] parameters)
        {
            string lineMessage = FormatMessage(logLevel, logLocation, context, message, exception, parameters);

            output.WriteLine(lineMessage);

            if (exception != null)
            {
                LogException(logLocation, exception);
            }
        }
Exemplo n.º 8
0
        public override void Log(LogLevel logLevel, LogLocation logLocation, string context, string code, string message, Exception exception, params object[] parameters)
        {
            LoggerCodesEncountered.Add(code);
            string lineMessage = FormatMessage(logLevel, logLocation, context, message, exception, parameters);

            output.WriteLine(lineMessage);

            if (exception != null)
            {
                output.WriteLine(exception.ToString());
            }
        }
Exemplo n.º 9
0
        public void Log(LogLevel logLevel, LogLocation logLocation, string context, string code, string message, Exception exception, params object[] parameters)
        {
            var lineMessage = LogUtilities.FormatMessage(logLevel, logLocation, context, message, exception, parameters);

            MessageLog.Add(new XUnitLogEvent(code, lineMessage, exception, logLevel));

            output.WriteLine(lineMessage);

            if (exception != null)
            {
                output.WriteLine(exception.ToString());
            }
        }
        public TelemetryLogger(string logFilePath, LogLocation logLocation, LogLevel level)
        {
            _logFileFullPath = Path.Combine(logFilePath, LOGFILENAME + ".txt");
            _logLocation     = logLocation;
            _logLevel        = level;
            _ticker          = 0;

            string tdVersion = typeof(TelemetryLogger).Assembly.GetName().Version.ToString();

            tdVersion = tdVersion.Substring(0, tdVersion.Length - 2);
            tdVersion = " v" + tdVersion;
            if (tdVersion.Length > 30)
            {
                throw new Exception("Version number is way too long.");
            }
            while (tdVersion.Length < 30)
            {
                tdVersion += ' ';
            }

            try
            {
                if (File.Exists(_logFileFullPath))
                {
                    File.Delete(_logFileFullPath);
                }
                using (StreamWriter sw = new StreamWriter(_logFileFullPath))
                {
                    sw.WriteLine("--------------------------------");
                    sw.WriteLine("| Telemetry Dashboard log file |");
                    sw.WriteLine("|" + tdVersion + "|");
                    sw.WriteLine("| " + DateTime.UtcNow.ToString("o") + " |");
                    sw.WriteLine("--------------------------------");
                    sw.WriteLine(_logFileFullPath + '\n');
                }
            }
            catch (UnauthorizedAccessException unauthorizedException)
            {
                throw new LoggingException("Unauthorized Access Exception thrown.", unauthorizedException);
            }
            catch (IOException ioException)
            {
                throw new LoggingException("IO Exception thrown.", ioException);
            }
            catch (Exception ex)
            {
                throw new LoggingException("Unhandled exception thrown", ex);
            }
        }
        /// <summary>
        /// Gets the Enterprise Library LogWriter.
        /// </summary>
        /// <param name="logLocation">The log location.</param>
        /// <returns>LogWriter.</returns>
        protected override LogWriter PerformGetLogger(LogLocation logLocation)
        {
            try
            {
                return(GetLogger());
            }
            catch (Exception ex)
            {
                if (DiagnosticsEnabled)
                {
                    Trace.WriteLine("Could not instantiate a '{0}'. Possible Enterprise Library Configuration error. {1}.".FormatInvariant(this.GetType().FullName, ex.ToString()));
                }

                throw;
            }
        }
Exemplo n.º 12
0
    /// <summary>
    /// Formats the message.
    /// </summary>
    /// <param name="logLevel">The log level.</param>
    /// <param name="logLocation">The log location.</param>
    /// <param name="context">The context.</param>
    /// <param name="message">The message.</param>
    /// <param name="exception">The exception.</param>
    /// <param name="parameters">The parameters.</param>
    /// <returns></returns>
    public static string FormatMessage(LogLevel logLevel, LogLocation logLocation, string context, string message, Exception exception, params object[] parameters)
    {
        var lineMessage = new StringBuilder();

        if (logLocation != null)
        {
            lineMessage.AppendFormat("{0}({1},{2}): ", logLocation.File, logLocation.Line, logLocation.Column);
        }

        // Write log parsable by Visual Studio
        var levelName = Enum.GetName(typeof(LogLevel), logLevel).ToLower();

        lineMessage.AppendFormat("{0}:{1}{2}", levelName, (context != null) ? $" in {context} " : "", message != null ? string.Format(message, parameters) : "");

        return(lineMessage.ToString());
    }
Exemplo n.º 13
0
        public Logger(string application, Type type = null)
        {
            Application = application;
            Type        = type;

            var consoleOutputTemplate =
                $"[{application}" + " {Timestamp:HH:mm:ss.ff} {Level:u3}] {Message:lj}{NewLine}{Exception}";
            var loggerConfiguration = new LoggerConfiguration()
                                      .WriteTo.Console(outputTemplate: consoleOutputTemplate)
                                      .MinimumLevel.Debug();

            // if (Utilities.IsRunningOnTcAdmin)
            // {
            //     var arCommonSettings = ModuleConfiguration.GetModuleConfiguration(Globals.ModuleId, "ArCommonSettings").Parse<ArCommonSettings>();
            //     loggerConfiguration.MinimumLevel.Is(arCommonSettings.MinimumLogLevel);
            //     _logBaseLocation = _logBaseLocation.Replace("./", Path.Combine(Utility.GetLogPath(), "../"));
            // }

            if (Type != null)
            {
                var assemblyName = Type.Assembly.GetName().Name;
                LogLocation =
                    Path.Combine(
                        _logBaseLocation
                        .Replace("{0}", assemblyName)
                        .Replace("{1}", Type.Namespace?.Replace(assemblyName, "").Trim('.'))
                        .Replace("{2}", application));
                loggerConfiguration.WriteTo.File(LogLocation, rollingInterval: RollingInterval.Day, shared: true);
            }
            else
            {
                LogLocation = $"./Components/Misc/Logs/{application}/{application}.log";
                loggerConfiguration.WriteTo.File(LogLocation, rollingInterval: RollingInterval.Day, shared: true);
            }

            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings.Get("TCAdmin.LogPath")))
            {
                LogLocation = LogLocation.Replace("./", Path.Combine(ConfigurationManager.AppSettings["TCAdmin.LogPath"], "../"));
            }

            InternalLogger = loggerConfiguration.CreateLogger();
        }
Exemplo n.º 14
0
        /// <summary>
        /// Logs the specified log message.
        /// </summary>
        /// <param name="logLevel">The log level</param>
        /// <param name="logLocation">The log location.</param>
        /// <param name="context">The context.</param>
        /// <param name="message">The message.</param>
        /// <param name="exception">The exception.</param>
        /// <param name="parameters">The parameters.</param>
        public override void Log(LogLevel logLevel, LogLocation logLocation, string context, string message, Exception exception, params object[] parameters)
        {
            lock (this)
            {
                if (Output == null)
                {
                    return;
                }

                string lineMessage = FormatMessage(logLevel, logLocation, context, message, exception, parameters);

                Output.WriteLine(lineMessage);
                Output.Flush();

                if (exception != null)
                {
                    LogException(logLocation, exception);
                }
            }
        }
Exemplo n.º 15
0
        public void Log(LogLevel logLevel, LogLocation logLocation, string context, string code, string message, Exception exception, params object[] parameters)
        {
            var sb = new StringBuilder();

            sb.Append($"[{context ?? "System"}] ");

            if (message != null)
            {
                sb.Append(string.Format(message, parameters));
            }

            if (exception != null)
            {
                sb.Append($"exception =\"{exception}\"");
            }

            Console.ForegroundColor = exception is null ? ConsoleColor.Cyan : ConsoleColor.Yellow;
            Console.WriteLine(sb.ToString());
            Console.ForegroundColor = ConsoleColor.White;
        }
Exemplo n.º 16
0
 protected override TestLogWrapper PerformGetLogger(LogLocation logLocation)
 {
     return(this);
 }
Exemplo n.º 17
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="prefix">
        /// The prefix to add to log files
        /// (prefix_file_name.log)
        /// </param>
        public AppLogger(string prefix, LogLocation logEndpoint)
        {
            // Save the prefix
            _prefix = prefix;

            // Save the log endpoint
            _logEndpoint = logEndpoint;

            // If we are logging to a file, set up our log path
            if ((_logEndpoint & LogLocation.File) == LogLocation.File)
            {
                // Get the log dir path
                _logDirPath = System.IO.Path.GetDirectoryName(
                                 System.Reflection.Assembly.GetExecutingAssembly()
                                 .GetName().CodeBase.Substring(8).Replace("/", @"\"))
                                 + "\\logs";

                // Create the log directory if it doesn't exist
                if (!Directory.Exists(_logDirPath))
                    Directory.CreateDirectory(_logDirPath);
            }
        }
Exemplo n.º 18
0
        static int Main(string[] args)
        {
            DateTime startTime = DateTime.UtcNow;

            // Load dlls
            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

            // Setup Args and Logging
            bool isCMDRun = GetConsoleProcessList(new uint[1], 1) == 2;

            try
            {
                ArgsManager = new ArgumentManager(args, isCMDRun);
            }
            catch (ArgumentManagerException argManagerEx)
            {
                Console.WriteLine("Error handling arguments:\n" + argManagerEx.Message);
                return(1);
            }

            LogLocation location = LogLocation.FileAndConsole;
            LogLevel    level    = LogLevel.Info;

            if (ArgsManager.TaskTriggered)
            {
                location = LogLocation.File;
            }
            if (ArgsManager.DebugLog)
            {
                level = LogLevel.Debug;
            }

            try
            {
                Logger = new TelemetryLogger(FileLocationManager.WorkingDirectory, location, level);
            }
            catch (LoggingException logException)
            {
                Console.WriteLine("Error setting up logging:\n" + logException.Message);
                if (logException.InnerException != null)
                {
                    Console.WriteLine("\nInner exception:\n" + logException.InnerException.Message);
                }
                return(1);
            }
            Logger.Log("Arguments handled and logging initialized.", LogLevel.Info);

            Logger.Log("Current working directory: " + FileLocationManager.WorkingDirectory, LogLevel.Debug);

            // Get certificates and set up QRS Requester
            try
            {
                _qrsInstance = new QlikRepositoryRequester(CertificateConfigHelpers.Hostname, CertificateConfigHelpers.Certificate, ArgsManager.RepositoryTimeout);
            }
            catch (UnauthorizedAccessException)
            {
                Logger.Log("Failed to get certificates and host.cfg file. This is probably because the executable is not being run either as an administrator or in an administrator command prompt.", LogLevel.Error);
                return(1);
            }

            // Main

            if (ArgsManager.NoArgs)
            {
                Console.WriteLine(ArgumentManager.HELP_STRING);
                return(0);
            }
            else if (ArgsManager.TestRun)
            {
                Logger.Log("Test Mode:", LogLevel.Info);
                Logger.Log("Checking to see if repository is running.", LogLevel.Info);
                Tuple <bool, HttpStatusCode> responseIsRunning = _qrsInstance.IsRepositoryRunning();
                if (responseIsRunning.Item1)
                {
                    Logger.Log(responseIsRunning.Item2.ToString() + " returned. Validation successful.", LogLevel.Debug);
                    return(0);
                }
                else
                {
                    Logger.Log(responseIsRunning.Item2.ToString() + " returned. Failed to get valid response from Qlik Sense Repository. Either the service is not running or the Telemetry Dashboard cannot connect.", LogLevel.Error);
                    return(1);
                }
            }
            else if (ArgsManager.InitializeRun)
            {
                Tuple <bool, HttpStatusCode> responseIsRunning = _qrsInstance.IsRepositoryRunning();
                if (!responseIsRunning.Item1)
                {
                    Logger.Log("Failed to connect to Qlik Sense Repository Service. Either it is not running, or the telemetry dashboard cannot reach it.", LogLevel.Error);
                    return(1);
                }

                Logger.Log("Preparing to run initialize mode, this will create two tasks, import an application and create two data connections in your environment, press 'q' to quit or any other key to proceed:", LogLevel.Info);

                ConsoleKeyInfo keyPressed = Console.ReadKey();
                Logger.Log("Please enter the 'DOMAIN\\user' for the service account running Qlik Sense Enterprise (without quotes, example: QLIK\\jparis): ", LogLevel.Info);

                string serviceAccount = Console.ReadLine();
                if (serviceAccount.StartsWith("'"))
                {
                    serviceAccount = serviceAccount.Substring(1);
                }
                if (serviceAccount.EndsWith("'"))
                {
                    serviceAccount = serviceAccount.Substring(0, serviceAccount.Length - 1);
                }
                if (serviceAccount.StartsWith(".\\"))
                {
                    serviceAccount = Environment.MachineName + "\\" + serviceAccount.Substring(2);
                }
                Logger.Log("The user '" + serviceAccount + "' was entered.", LogLevel.Info);


                if (keyPressed.Key != ConsoleKey.Q)
                {
                    Logger.Log("Initialize Mode:", LogLevel.Info);

                    return(InitializeEnvironment.Run(serviceAccount, ArgsManager.SkipCopy));
                }
                return(0);
            }
            else if (ArgsManager.FetchMetadataRun)
            {
                Tuple <bool, HttpStatusCode> responseIsRunning = _qrsInstance.IsRepositoryRunning();
                if (!responseIsRunning.Item1)
                {
                    Logger.Log("Failed to connect to Qlik Sense Repository Service. Either it is not running, or the telemetry dashboard cannot reach it.", LogLevel.Error);
                    return(1);
                }

                Logger.Log("Fetch Metadata Mode:", LogLevel.Info);

                if (ArgsManager.TaskTriggered)
                {
                    Logger.Log("Running Fetch Metadata from external program task.", LogLevel.Debug);
                }
                else
                {
                    Logger.Log("Running Fetch Metadata from command line.", LogLevel.Debug);
                }

                // fetch metadata and wriet to csv
                int returnVal = MetadataFetchRunner.Run(ArgsManager.EngineTimeout);

                DateTime endTime   = DateTime.UtcNow;
                TimeSpan totalTime = endTime - startTime;
                Logger.Log("Fetch metadata took: " + totalTime.ToString(@"hh\:mm\:ss"), LogLevel.Info);

                return(returnVal);
            }
            else
            {
                Logger.Log("Unhandled argument.", LogLevel.Error);
                return(1);
            }
        }
Exemplo n.º 19
0
 /// <summary>
 /// Creates a new instance of the <see cref="LoggerSharp"> class and forwards all the specified information to the parent <see cref="Logger">, <see cref="LoggerBase">, and <see cref="LogFile"> classes.
 /// </summary>
 /// <param name="sender">The sender or name to display in the console and <see cref="LogFile"></param>
 /// <param name="location">The <see cref="LogLocation"> and system path to the log file, or a directory to store default-named <see cref="LogFile">.</param>
 /// <param name="debug">Allow use of the debug status in the console and the <see cref="LogFile"></param>
 public LoggerSharp(object sender, LogLocation location, bool debug)
 {
     logger = new Logger(sender.GetType().Name, location.location, debug);
 }
Exemplo n.º 20
0
 /// <summary>
 /// Creates a new instance of the <see cref="LoggerSharp"> class and forwards all the specified information to the parent <see cref="Logger">, <see cref="LoggerBase">, and <see cref="LogFile"> classes.
 /// </summary>
 /// <param name="sender">The sender or name to display in the console and <see cref="LogFile"></param>
 /// <param name="location">The <see cref="LogLocation"> and system path to the log file, or a directory to store default-named <see cref="LogFile">.</param>
 /// <param name="debug">Allow use of the debug status in the console and the <see cref="LogFile"></param>
 public LoggerSharp(string sender, LogLocation location, bool debug)
 {
     logger = new Logger(sender, location.location, debug);
 }
Exemplo n.º 21
0
        protected AuditProvider(AuditPolicy auditPolicy, string sourceName, LogLocation location)
        {
            if (auditPolicy == null)
            {
                throw new ArgumentNullException(nameof(auditPolicy));
            }

            if (sourceName == null)
            {
                throw new ArgumentNullException(nameof(sourceName));
            }

            if (!SourceNameValidator.IsSourceNameValid(sourceName))
            {
                throw new ArgumentException("Invalid event source name", nameof(sourceName));
            }

            if (location != LogLocation.ApplicationLog &&
                location != LogLocation.SecurityLog)
            {
                throw new ArgumentOutOfRangeException(nameof(location), "Invalid enum");
            }

            this.auditPolicy = auditPolicy;

            if (location == LogLocation.SecurityLog)
            {
                Privilege privilege = new Privilege(Privilege.Audit);

                try
                {
                    privilege.Enable();

                    if (false == Win32Native.AuthzRegisterSecurityEventSource(0, sourceName, ref this.securityLogHandle))
                    {
                        int error = Marshal.GetLastWin32Error();

                        if (error == Win32Native.ERROR_NOT_ENOUGH_MEMORY)
                        {
                            throw new OutOfMemoryException();
                        }
                        else if (error == Win32Native.ERROR_INVALID_PARAMETER)
                        {
                            // Marshaling failed!
                            throw new Win32Exception(error);
                        }
                        else if (error == Win32Native.ERROR_ACCESS_DENIED)
                        {
                            throw new UnauthorizedAccessException();
                        }
                        else if (error == Win32Native.ERROR_PRIVILEGE_NOT_HELD)
                        {
                            // Privilege should be enabled by now!
                            throw new PrivilegeNotHeldException(Privilege.Audit);
                        }
                        else
                        {
                            throw new Win32Exception(error);
                        }
                    }
                }
                catch (EntryPointNotFoundException)
                {
                    throw new NotSupportedException("Platform not supported");
                }
                finally
                {
                    privilege.Revert();
                }
            }
            else // application log
            {
                this.applicationLogHandle = Win32Native.RegisterEventSource(null, sourceName);

                if (this.applicationLogHandle.Equals(IntPtr.Zero))
                {
                    int error = Marshal.GetLastWin32Error();

                    if (error == Win32Native.ERROR_NOT_ENOUGH_MEMORY)
                    {
                        throw new OutOfMemoryException();
                    }
                    else if (error == Win32Native.ERROR_INVALID_PARAMETER)
                    {
                        // Marshaling failed!
                        throw new Win32Exception(error);
                    }
                    else if (error == Win32Native.ERROR_ACCESS_DENIED)
                    {
                        throw new UnauthorizedAccessException();
                    }
                    else
                    {
                        throw new Win32Exception(error);
                    }
                }
            }
        }
Exemplo n.º 22
0
        static void Main(string[] args)
        {
            var logWriterFactory = new LogWriterFactory();
            var logger           = logWriterFactory.Create();

            Log.Information("Application started.");

            var now = DateTime.UtcNow;

            // Log message through LogBridge
            Time("LogBridge simple message: {0}", () => Log.Warning("Message"));

            // Log formatted message through LogBridge
            Time("LogBridge formatted message: {0}", () => Log.Warning("Message {0} {1} {2} {3}", 42, "87", now, 87.42));

            // Log message with location through LogBridge
            Time("LogBridge simple message with location: {0}", () => Log.Warning(LogLocation.Here(typeof(Program)), "Message"));

            // Log formatted message with location through LogBridge
            Time("LogBridge formatted message with location: {0}", () => Log.Warning(LogLocation.Here(typeof(Program)), "Message {0} {1} {2} {3}", 42, "87", now, 87.42));

            var logData = new LogData(
                now,
                Guid.NewGuid(),
                Option.None <Guid>(),
                Level.Warning,
                "Message",
                "Username",
                "Machinename",
                42,
                "ProcessName",
                "AppDomainName",
                null,
                new LogLocation(),
                new Dictionary <string, object>());

            // Log formatted message directly through Enterprise Library
            Time("Enterprise Library formatted message: {0}",
                 () =>
            {
                var logEntry = new LogEntry()
                {
                    ActivityId         = logData.EventId,
                    AppDomainName      = logData.AppDomainName,
                    ExtendedProperties = logData.Properties,
                    Message            = logData.Message,
                    Severity           = TraceEventType.Warning,
                    TimeStamp          = logData.TimeStamp,
                    Title       = logData.Message.Substring(0, Math.Min(32, logData.Message.Length)),
                    MachineName = logData.MachineName,
                    ProcessId   = logData.ProcessIdString,
                    ProcessName = logData.ProcessName,
                    Priority    = 0
                };

                if (logger.ShouldLog(logEntry))
                {
                    logger.Write(logEntry);
                }
            });

            Console.WriteLine("Press ENTER to exit.");
            //Console.ReadLine();
        }