예제 #1
0
 /// <summary>
 /// Logs the end of the current scope.
 /// </summary>
 public void Dispose()
 {
     if (!isDisposed)
     {
         isDisposed = true;
         FL.LogScope(FieldLogScopeType.ThreadEnd, name);
         GC.SuppressFinalize(this);
     }
 }
예제 #2
0
 /// <summary>
 /// Logs the end of the current scope.
 /// </summary>
 public void Dispose()
 {
     if (!isDisposed)
     {
         isDisposed = true;
         FL.Leave(name);
         GC.SuppressFinalize(this);
     }
 }
예제 #3
0
        /// <inheritdoc/>
        public override void WriteLine(string message)
        {
            msgSb.Append(message);
            var final = msgSb.ToString();

            msgSb.Length = 0;
            if (!FL.IsShutdown)
            {
                FL.Trace(sourceName + ": " + final);
            }
        }
        private static void CreateForRectangle(Rectangle rect)
        {
            if (KeepTime <= TimeSpan.Zero || MaxTotalSize <= 0)
            {
                return;                   // Nothing to do
            }
            try
            {
                string fileName = GetFileNameWithoutExtension();
                if (fileName != null)
                {
                    // Source: http://stackoverflow.com/a/5049138/143684
                    // Source: http://stackoverflow.com/a/1163770/143684
                    using (Bitmap bitmap = new Bitmap(rect.Width, rect.Height))
                    {
                        using (Graphics graphics = Graphics.FromImage(bitmap))
                        {
                            graphics.CopyFromScreen(rect.X, rect.Y, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
                        }

                        // Save bitmap as PNG and JPEG
                        bitmap.Save(fileName + ".png", ImageFormat.Png);
                        SaveJpegImage(bitmap, fileName + ".jpg", 75);

                        // Evaluate both file sizes and decide which to keep
                        long pngSize = new FileInfo(fileName + ".png").Length;
                        long jpgSize = new FileInfo(fileName + ".jpg").Length;
                        if (pngSize > jpgSize * 2)
                        {
                            File.Delete(fileName + ".png");
                        }
                        else
                        {
                            File.Delete(fileName + ".jpg");
                        }
                    }

                    Purge();
                }
            }
            catch (Exception ex)
            {
                FL.Error(ex, "Creating screenshot");
            }
        }
        /// <summary>
        /// Creates a new log file reader and adds it to the priority's log file enumerator.
        /// </summary>
        /// <param name="prio">The priority of files to write.</param>
        /// <param name="fileName">The name of the log file.</param>
        /// <param name="fromFsw">Indicates whether the reader was created from a FileSystemWatcher event.</param>
        private void AddNewReader(FieldLogPriority prio, string fileName, bool fromFsw)
        {
            // Must be within a lock(readerLock)!
            FL.Trace("AddNewReader, prio=" + prio + ", fileName=" + Path.GetFileName(fileName) + ", fromFsw=" + fromFsw);

            // Reject the new file if it's already in the queue (delayed FSW event after active scan)
            if (readers.ContainsKey(prio) &&
                readers[prio] != null &&
                readers[prio].ContainsFile(fileName))
            {
                // This file is already current or queued
                FL.Checkpoint("This file is already current or queued");
                return;
            }

            var reader = new FieldLogFileReader(fileName, true);
            ManualResetEvent h;

            if (!prioReadSignals.TryGetValue(prio, out h))
            {
                h = new ManualResetEvent(false);
                prioReadSignals[prio] = h;
            }
            reader.ReadWaitHandle = h;

            if (!readers.ContainsKey(prio) || readers[prio] == null)
            {
                // This is the first file of this priority
                readers[prio]        = new FieldLogFileEnumerator(reader);
                readers[prio].Error += FieldLogFileEnumerator_Error;
                readTasks[(int)prio] = Task <bool> .Factory.StartNew(readers[prio].MoveNext);

                // Signal the blocking ReadLogItem method that there's a new reader now
                newFilePrioEvent.Set();
            }
            else
            {
                // Chain the new reader after the last reader in the queue
                readers[prio].Append(reader, fromFsw);

                // TODO,DEBUG: What for?
                //newFilePrioEvent.Set();
            }
        }
예제 #6
0
 private void StartSubmitTool()
 {
     if (sendCheckBox.Checked)
     {
         string exeFile = Application.ExecutablePath;
         if (!string.IsNullOrEmpty(exeFile))
         {
             exeFile = Path.GetDirectoryName(exeFile);
             exeFile = Path.Combine(exeFile, "LogSubmit.exe");
             if (File.Exists(exeFile))
             {
                 // Found the log submit tool, now start it
                 try
                 {
                     Process.Start(exeFile, "/errordlg /logpath \"" + FL.LogFileBasePath + "\"");
                 }
                 catch (Exception ex)
                 {
                     // Start failed, show an error message
                     FL.Critical(ex, "Starting log submit tool");
                     MessageBox.Show(
                         "The log submit tool could not be started." + " " + ex.Message,
                         "Error",
                         MessageBoxButtons.OK,
                         MessageBoxIcon.Error);
                 }
                 return;
             }
         }
         // Log submit tool not found but logs should be sent, show an error message
         FL.Error("Could not start log submit tool, path or file not found");
         MessageBox.Show(
             "The log submit tool could not be started. The path or file was not found. Please start the tool manually from the application installation directory.",
             "Error",
             MessageBoxButtons.OK,
             MessageBoxIcon.Error);
     }
 }
        /// <summary>
        /// Advances the enumerator to the next log item of the currently read log file. If there
        /// are no more items in this file and there is a NextReader set, the first log item of the
        /// next file reader is selected. If there are no more items in this file and WaitMode is
        /// set, the method will block until another log item is appended to the current file or
        /// the wait operation is cancelled by a close event.
        /// </summary>
        /// <returns>true if the enumerator was successfully advanced to the next log item;
        /// false if the enumerator has passed the end of the collection.</returns>
        public bool MoveNext()
        {
            FieldLogFileReader nextReader = null;

            do
            {
                if (nextReader != null)
                {
                    FL.Trace(reader.ItemCount + " items read from " + Path.GetFileName(reader.FileName));
                    reader = nextReader;
                    FL.Trace("Switching to next reader " + Path.GetFileName(reader.FileName));
                }

                try
                {
                    item = reader.ReadLogItem();
                }
                catch (Exception ex)
                {
                    FL.Error(ex, "Reading item from log file");
                    OnError(ex);
                    // Skip the rest of the current file and continue with the next one if
                    // available. If this is the last file and WaitMode is set, this priority will
                    // not be monitored anymore.
                    item = null;
                }

                if (item == null && reader.IsClosing)
                {
                    // Close event must have been set
                    Dispose();
                    return(false);
                }
                nextReader = reader.NextReader;
            }while (item == null && nextReader != null);
            return(item != null);
        }
        /// <summary>
        /// Appends a new FieldLogFileReader at the end of this enumerator.
        /// </summary>
        /// <param name="newReader">The new reader to append.</param>
        /// <param name="fromFsw">Indicates whether the reader was created from a FileSystemWatcher event.</param>
        public void Append(FieldLogFileReader newReader, bool fromFsw)
        {
            FieldLogFileReader currentLastReader = LastReader;

            currentLastReader.NextReader = newReader;
            // Unset wait mode for this reader, now that we know where to continue after this file
            if (fromFsw)
            {
                // The file is newly created. Take some time to actually start reading the previous
                // file before switching to this one. Once the first item has been read from the
                // file, more items will likely exist in the file, and the file is read until the
                // end. Then it will still sit there waiting for more items until the rest of this
                // delay has elapsed (which is not a big problem, if we get any items from that
                // file at all).
#if NET20
                new Thread(() =>
                {
                    Thread.Sleep(1000);
                    currentLastReader.WaitMode = false;
                }).Start();
#else
                Task.Factory.StartNew(() =>
                {
                    Thread.Sleep(1000);
                    currentLastReader.WaitMode = false;
                });
#endif
            }
            else
            {
                currentLastReader.WaitMode = false;
            }
            FL.Trace(
                "Appending next reader",
                "this=" + Path.GetFileName(currentLastReader.FileName) + "\nNext=" + Path.GetFileName(newReader.FileName) +
                "\nItems read from this=" + currentLastReader.ItemCount);
        }
예제 #9
0
        private static void ThreadProc()
        {
#if NET20
            localOffset = (int)TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.UtcNow).TotalMinutes;
#else
            localOffset = (int)TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow).TotalMinutes;
#endif
            // Only check for offset changes every new minute (plus 1 second safety margin) to save
            // resources for clearing the TimeZoneInfo cache
            nextOffsetCheck = DateTime.UtcNow.Ticks / 600000000 * 600000000 + 610000000;

            do
            {
                try
                {
                    Thread.Sleep(CheckInterval);
                }
                catch (ThreadInterruptedException)
                {
                    // That's fine.
                }

                // Check for UTC time changes
                TimeSpan offset = DateTime.UtcNow - FL.UtcNow;
                if (Math.Abs(offset.TotalMilliseconds) >= FL.CheckTimeThreshold)
                {
                    FL.RebaseTime();

                    string msg  = "System time changed by " + offset.TotalMilliseconds.ToString("0.0", CultureInfo.InvariantCulture) + " ms";
                    var    item = new FieldLogTextItem(FieldLogPriority.Notice, msg, "Changes less than " + FL.CheckTimeThreshold + " ms are not reported.");
                    // Discard this log item if there was no other item logged within the last
                    // 10 seconds because it wouldn't be interesting anyway. If no other log items
                    // may have discontinuous timestamps, the time recalibration can occur silently.
                    FL.LogInternal(item, TimeSpan.FromSeconds(10));
                    Debug.WriteLine(msg);
                    prevLoggedOffset = 0;
                }
                else if (FL.LogTimeThreshold >= 0 &&
                         Math.Abs(offset.TotalMilliseconds - prevLoggedOffset) > FL.LogTimeThreshold)
                {
                    FL.TraceData("System time offset", offset.TotalMilliseconds);
                    prevLoggedOffset = offset.TotalMilliseconds;
                }

                // Check for local time zone changes
                if (DateTime.UtcNow.Ticks >= nextOffsetCheck)
                {
                    // Clear the cache to get the real current setting
#if NET20
                    int newLocalOffset = (int)TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.UtcNow).TotalMinutes;
#else
                    TimeZoneInfo.ClearCachedData();
                    int newLocalOffset = (int)TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow).TotalMinutes;
#endif
                    if (newLocalOffset != localOffset)
                    {
                        int hours = localOffset / 60;
                        int mins  = Math.Abs(localOffset) % 60;

                        int newHours = newLocalOffset / 60;
                        int newMins  = Math.Abs(newLocalOffset) % 60;

                        localOffset = newLocalOffset;

                        string msg = "Local time UTC offset changed from " +
                                     hours.ToString("+00;-00;+00") + ":" + mins.ToString("00") + " to " +
                                     newHours.ToString("+00;-00;+00") + ":" + newMins.ToString("00");
                        string details = "\u0001UtcOffset=" + newLocalOffset;
                        FL.Notice(msg, details);
                        Debug.WriteLine(msg);
                    }
                    nextOffsetCheck = DateTime.UtcNow.Ticks / 600000000 * 600000000 + 610000000;
                }
            }while (!cancelPending);
        }
예제 #10
0
        /// <summary>
        /// Shows the application error dialog. This is the only method that is called to show or
        /// update an error dialog. If a dialog is already open, the error is added to it.
        /// </summary>
        /// <param name="canContinue">Indicates whether the application can continue.</param>
        /// <param name="errorMsg">The error message to display.</param>
        /// <param name="ex">The <see cref="Exception"/> instance to display as details object.</param>
        /// <param name="terminateTimerEnabled">Indicates whether the termination safety timer has been started.</param>
        public static void ShowError(bool canContinue, string errorMsg, object ex, bool terminateTimerEnabled)
        {
            lock (syncLock)
            {
                try
                {
                    if (currentInstance == null)
                    {
                        currentInstance = new AppErrorDialog();
                        currentInstance.SetCanContinue(canContinue);
                        currentInstance.errorLabel.Text      = errorMsg;
                        currentInstance.grid.SelectedObject  = ex;
                        currentInstance.detailsLabel.Enabled = ex != null;
                        if (terminateTimerEnabled)
                        {
                            currentInstance.EnableTerminateTimer();
                        }

                        // Source: http://stackoverflow.com/a/3992635/143684
                        uiThread      = new Thread(UiThreadStart);
                        uiThread.Name = "FieldLog.AppErrorDialogUIThread";
                        uiThread.SetApartmentState(ApartmentState.STA);
                        uiThread.Start();
                    }
                    else
                    {
                        // Add next error to existing dialog
                        // Wait until the window handle is created
                        int count = 0;
                        while (!currentInstance.IsHandleCreated)
                        {
                            if (count++ > 500)
                            {
                                throw new TimeoutException("Application error dialog was not created in reasonable time.");
                            }
                            Thread.Sleep(10);
                        }
                        currentInstance.Invoke(new AddErrorDelegate(currentInstance.AddError), canContinue, errorMsg, ex, terminateTimerEnabled);
                    }
                }
                catch (Exception ex2)
                {
                    FL.Critical(ex2, "FieldLog.Showing AppErrorDialog", false);
                    FL.Flush();
                    MessageBox.Show(
                        "Error showing the application error dialog. Details should be logged.",
                        "Error",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                }
            }

            // Make sure we won't continue in this thread if it's not possible
            while (!canContinue)
            {
                Thread.Sleep(1000000);
            }

            // Slow down or halt the application as long as there are many pending errors.
            // The error dialog runs in its own thread so it will still respond to user input. :-)
            // (Unless, of course, should an error occur in the error dialog…)
            if (currentInstance != null && currentInstance.GetNextErrorsCount() >= 20)
            {
                Thread.Sleep(1000);
            }
            while (currentInstance != null && currentInstance.GetNextErrorsCount() >= 40)
            {
                Thread.Sleep(1000);
            }
        }
예제 #11
0
        private AppErrorDialog()
        {
            if (!appErrorInitialized)
            {
                Application.EnableVisualStyles();
                appErrorInitialized = true;
            }

            string title   = FL.AppErrorDialogTitle;
            string appName = FL.AppName;

            if (!string.IsNullOrEmpty(appName))
            {
                title = appName + " – " + title;
            }

            this.BackColor       = SystemColors.Window;
            this.ControlBox      = false;
            this.MinimizeBox     = false;
            this.MaximizeBox     = false;
            this.Font            = SystemFonts.MessageBoxFont;
            this.FormBorderStyle = FormBorderStyle.FixedDialog;
            this.ShowInTaskbar   = false;
            this.Size            = new Size(550, 300);
            this.StartPosition   = FormStartPosition.CenterScreen;
            this.Text            = title;
            this.TopMost         = true;

            tablePanel          = new TableLayoutPanel();
            tablePanel.Dock     = DockStyle.Fill;
            tablePanel.RowCount = 6;
            tablePanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
            tablePanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
            tablePanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
            tablePanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
            tablePanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 0));
            tablePanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
            tablePanel.ColumnCount = 1;
            tablePanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
            this.Controls.Add(tablePanel);

            introLabel           = new Label();
            introLabel.BackColor = Color.FromArgb(221, 74, 59);
            introLabel.ForeColor = Color.White;
            introLabel.Dock      = DockStyle.Fill;
            introLabel.AutoSize  = true;
            introLabel.Font      = new Font(
                SystemFonts.MessageBoxFont.FontFamily,
                SystemFonts.MessageBoxFont.SizeInPoints * 1.3f,
                SystemFonts.MessageBoxFont.Style);
            introLabel.MaximumSize = new Size(this.ClientSize.Width, 0);
            introLabel.Padding     = new Padding(6, 4, 7, 6);
            introLabel.Margin      = new Padding();
            introLabel.UseCompatibleTextRendering = false;
            introLabel.UseMnemonic = false;
            tablePanel.Controls.Add(introLabel);
            tablePanel.SetRow(introLabel, 0);
            tablePanel.SetColumn(introLabel, 0);

            errorPanel            = new Panel();
            errorPanel.AutoScroll = true;
            errorPanel.Dock       = DockStyle.Fill;
            errorPanel.Margin     = new Padding(7, 8, 10, 6);
            errorPanel.Padding    = new Padding();
            tablePanel.Controls.Add(errorPanel);
            tablePanel.SetRow(errorPanel, 1);
            tablePanel.SetColumn(errorPanel, 0);

            errorLabel             = new Label();
            errorLabel.AutoSize    = true;
            errorLabel.MaximumSize = new Size(this.ClientSize.Width - 20, 0);
            errorLabel.Padding     = new Padding();
            errorLabel.Margin      = new Padding();
            errorLabel.UseCompatibleTextRendering = false;
            errorLabel.UseMnemonic = false;
            errorPanel.Controls.Add(errorLabel);

            logLabel             = new LinkLabel();
            logLabel.AutoSize    = true;
            logLabel.MaximumSize = new Size(this.ClientSize.Width - 20, 0);
            logLabel.Margin      = new Padding(8, 6, 10, 0);
            logLabel.Padding     = new Padding();
            if (FL.LogFileBasePath != null)
            {
                logLabel.Text = string.Format(FL.AppErrorDialogLogPath, FL.LogFileBasePath.Replace("\\", "\\\u200B") + "*.fl");
                string dir = Path.GetDirectoryName(FL.LogFileBasePath).Replace("\\", "\\\u200B");
                logLabel.LinkArea     = new LinkArea(FL.AppErrorDialogLogPath.IndexOf("{0}", StringComparison.Ordinal), dir.Length);
                logLabel.LinkClicked += (s, e) =>
                {
                    Process.Start(Path.GetDirectoryName(FL.LogFileBasePath));
                };
            }
            else
            {
                logLabel.Text     = FL.AppErrorDialogNoLog;
                logLabel.LinkArea = new LinkArea(0, 0);
            }
            logLabel.UseCompatibleTextRendering = false;
            logLabel.UseMnemonic = false;
            tablePanel.Controls.Add(logLabel);
            tablePanel.SetRow(logLabel, 2);
            tablePanel.SetColumn(logLabel, 0);

            detailsLabel          = new LinkLabel();
            detailsLabel.AutoSize = true;
            detailsLabel.Margin   = new Padding(7, 6, 10, 10);
            detailsLabel.Padding  = new Padding();
            detailsLabel.TabIndex = 11;
            detailsLabel.Text     = FL.AppErrorDialogDetails;
            detailsLabel.UseCompatibleTextRendering = false;
            detailsLabel.Visible = CanShowDetails;
            tablePanel.Controls.Add(detailsLabel);
            tablePanel.SetRow(detailsLabel, 3);
            tablePanel.SetColumn(detailsLabel, 0);

            var attr = new TypeConverterAttribute(typeof(ExpandableObjectConverter));

            TypeDescriptor.AddAttributes(typeof(Exception), attr);
            grid                            = new PropertyGrid();
            grid.Dock                       = DockStyle.Fill;
            grid.Margin                     = new Padding(10, 10, 10, 10);
            grid.ToolbarVisible             = false;
            grid.HelpVisible                = false;
            grid.PropertySort               = PropertySort.Alphabetical;
            grid.UseCompatibleTextRendering = false;
            grid.Visible                    = false;
            tablePanel.Controls.Add(grid);
            tablePanel.SetRow(grid, 4);
            tablePanel.SetColumn(grid, 0);

            bool isGridColumnResized = false;

            grid.Resize += (s, e) =>
            {
                if (!isGridColumnResized)
                {
                    isGridColumnResized = true;
                    // Source: http://stackoverflow.com/a/14475276/143684
                    FieldInfo fi = grid.GetType().GetField("gridView", BindingFlags.Instance | BindingFlags.NonPublic);
                    if (fi != null)
                    {
                        Control view = fi.GetValue(grid) as Control;
                        if (view != null)
                        {
                            MethodInfo mi = view.GetType().GetMethod("MoveSplitterTo", BindingFlags.Instance | BindingFlags.NonPublic);
                            if (mi != null)
                            {
                                mi.Invoke(view, new object[] { 170 });
                            }
                            mi = view.GetType().GetMethod("set_GrayTextColor", BindingFlags.Instance | BindingFlags.NonPublic);
                            if (mi != null)
                            {
                                mi.Invoke(view, new object[] { Color.Black });
                            }
                        }
                    }
                }
            };

            detailsLabel.LinkClicked += (s, e) =>
            {
                detailsLabel.Hide();
                this.Height += 300;
                this.Top    -= Math.Min(this.Top - 4, 150);
                tablePanel.RowStyles[4].Height = 350;
                grid.Visible = true;
            };

            buttonsPanel              = new TableLayoutPanel();
            buttonsPanel.AutoSize     = true;
            buttonsPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            buttonsPanel.BackColor    = SystemColors.Control;
            buttonsPanel.Dock         = DockStyle.Fill;
            buttonsPanel.Margin       = new Padding();
            buttonsPanel.Padding      = new Padding(10, 10, 10, 10);
            buttonsPanel.ColumnCount  = 4;
            buttonsPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
            buttonsPanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
            buttonsPanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
            buttonsPanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
            tablePanel.Controls.Add(buttonsPanel);
            tablePanel.SetRow(buttonsPanel, 5);
            tablePanel.SetColumn(buttonsPanel, 0);

            sendCheckBox          = new CheckBox();
            sendCheckBox.Anchor   = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Bottom;
            sendCheckBox.AutoSize = true;
            sendCheckBox.Enabled  = FL.CanSubmitLog;
            if (sendCheckBox.Enabled)
            {
                sendCheckBox.Checked = true;
            }
            sendCheckBox.FlatStyle = FlatStyle.System;
            sendCheckBox.Margin    = new Padding();
            sendCheckBox.Padding   = new Padding();
            sendCheckBox.Text      = FL.AppErrorDialogSendLogs;
            sendCheckBox.UseCompatibleTextRendering = false;
            buttonsPanel.Controls.Add(sendCheckBox);
            buttonsPanel.SetRow(sendCheckBox, 0);
            buttonsPanel.SetColumn(sendCheckBox, 0);

            nextButton              = new Button();
            nextButton.AutoSize     = true;
            nextButton.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            nextButton.FlatStyle    = FlatStyle.System;
            nextButton.Margin       = new Padding(6, 0, 0, 0);
            nextButton.Padding      = new Padding(2, 1, 2, 1);
            nextButton.Text         = FL.AppErrorDialogNext;
            nextButton.UseCompatibleTextRendering = false;
            nextButton.UseVisualStyleBackColor    = true;
            nextButton.Visible = false;
            nextButton.Click  += (s, e) =>
            {
                ShowNextError();
            };
            buttonsPanel.Controls.Add(nextButton);
            buttonsPanel.SetRow(nextButton, 0);
            buttonsPanel.SetColumn(nextButton, 1);

            terminateButton              = new Button();
            terminateButton.AutoSize     = true;
            terminateButton.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            terminateButton.FlatStyle    = FlatStyle.System;
            terminateButton.Margin       = new Padding(6, 0, 0, 0);
            terminateButton.Padding      = new Padding(2, 1, 2, 1);
            terminateButton.Text         = FL.AppErrorDialogTerminate;
            terminateButton.UseCompatibleTextRendering = false;
            terminateButton.UseVisualStyleBackColor    = true;
            terminateButton.Click += (s, e) =>
            {
                StartSubmitTool();
                Close();
                FL.Shutdown();
                Environment.Exit(1);
            };
            buttonsPanel.Controls.Add(terminateButton);
            buttonsPanel.SetRow(terminateButton, 0);
            buttonsPanel.SetColumn(terminateButton, 2);

            continueButton              = new Button();
            continueButton.AutoSize     = true;
            continueButton.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            continueButton.FlatStyle    = FlatStyle.System;
            continueButton.Margin       = new Padding(6, 0, 0, 0);
            continueButton.Padding      = new Padding(2, 1, 2, 1);
            continueButton.Text         = FL.AppErrorDialogContinue;
            continueButton.UseCompatibleTextRendering = false;
            continueButton.UseVisualStyleBackColor    = true;
            continueButton.Click += (s, e) =>
            {
                StartSubmitTool();
                Close();
            };
            buttonsPanel.Controls.Add(continueButton);
            buttonsPanel.SetRow(continueButton, 0);
            buttonsPanel.SetColumn(continueButton, 3);
        }
예제 #12
0
        private void WriteToFieldLog(string source, TraceEventType eventType, int id, string msg)
        {
            string shortMsg = null;

            // Name comparisons roughly in a descending order of frequency, to optimise performance
            if (source == PresentationTraceSources.DataBindingSource.Name)
            {
                HandleDataBindingMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.RoutedEventSource.Name)
            {
                if (id == 3)
                {
                    if (eventType == TraceEventType.Start)
                    {
                        eventType = TraceEventType.Verbose;                           // Don't indent for this
                    }
                    else if (eventType == TraceEventType.Stop)
                    {
                        return;                           // Don't log this
                    }
                }
                //if (id == 4)
                //{
                //    return;   // Don't log this
                //}
                HandleRoutedEventMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.ResourceDictionarySource.Name)
            {
                HandleResourceDictionaryMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.MarkupSource.Name)
            {
                HandleMarkupMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.AnimationSource.Name)
            {
                HandleAnimationMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.DependencyPropertySource.Name)
            {
                HandleDependencyPropertyMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.FreezableSource.Name)
            {
                if (id == 1)
                {
                    return;                       // Don't log this, it appears everywhere and comes from bugs in WPF
                }
                HandleFreezableMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.HwndHostSource.Name)
            {
                HandleHwndHostMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.NameScopeSource.Name)
            {
                HandleNameScopeMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.ShellSource.Name)
            {
                HandleShellMessage(id, ref msg, ref shortMsg);
            }
            // DocumentsSource does not have any information and is not augmented here

            // Fallback short message if unknown event ID
            if (shortMsg == null)
            {
                shortMsg = "ID " + id;
            }

            // Select appropriate FieldLog priority or otherwise highlight event type
            FieldLogPriority prio = FieldLogPriority.Trace;

            switch (eventType)
            {
            case TraceEventType.Critical:
            case TraceEventType.Error:
                prio = FieldLogPriority.Error;
                break;

            case TraceEventType.Warning:
                prio = FieldLogPriority.Warning;
                break;

            case TraceEventType.Information:
                prio = FieldLogPriority.Info;
                break;

            case TraceEventType.Start:
                //shortMsg += " [Start]";
                break;

            case TraceEventType.Stop:
                shortMsg += " [Stop]";
                break;

            case TraceEventType.Suspend:
                shortMsg += " [Suspend]";
                break;

            case TraceEventType.Resume:
                shortMsg += " [Resume]";
                break;

            case TraceEventType.Transfer:
                shortMsg += " [Transfer]";
                break;
            }

            // Write message to the log if it's still there
            if (!FL.IsShutdown)
            {
                if (eventType == TraceEventType.Stop)
                {
                    indentLevel--;
                }

                string indentPrefix = null;
                if (indentLevel < 0)
                {
                    indentPrefix = "«";
                    indentLevel  = 0;
                }
                else if (indentLevel > 0)
                {
                    // Use a cached pre-generated indent prefix for better performance
                    while (indentStrings.Count <= indentLevel)
                    {
                        int    newLevel = indentStrings.Count;
                        string prefix   = "";
                        for (int i = 1; i <= newLevel; i++)
                        {
                            prefix += "-  ";
                        }
                        indentStrings.Add(prefix);
                    }
                    indentPrefix = indentStrings[indentLevel];
                }

                FL.Text(
                    prio,
                    indentPrefix + shortName + ": " + shortMsg,
                    (!string.IsNullOrEmpty(msg) ? msg + "\n\n" : "") +
                    "Event ID: " + id + "\nEvent type: " + eventType + "\nSource: " + sourceName);

                if (eventType == TraceEventType.Start)
                {
                    indentLevel++;
                }
            }
        }
예제 #13
0
        /// <summary>
        /// Handles a custom time measurement timer for saving the time data.
        /// </summary>
        /// <param name="state">Unused.</param>
        private void OnCustomTimer(object state)
        {
            if (key == FL.EnsureJitTimerKey)
            {
                return;
            }

            long ticks, ticksPc, ticksTt, localCounter;

            lock (syncLock)
            {
                // Do nothing if the stopwatch was just started again or current data has already
                // been written
                if (stopwatch.IsRunning || !writePending)
                {
                    return;
                }
                // Clear the flag while we're in the lock region
                writePending = false;

                // Fetch the data in the lock region
                localCounter = counter;
                // Subtract 4 ticks per measurement, determined by tests
                // TODO: 0-tick intervals have been observed many times. Is the correction needed at all?
                long correction = localCounter * 0;
                ticks = stopwatch.Elapsed.Ticks - correction;
                if (ticks < 0)
                {
                    ticks = 0;
                }
                if (localCounter > 0)
                {
                    ticksPc = ticks / localCounter;
                }
                else
                {
                    ticksPc = 0;
                }

                long counterTt = localCounter - prevCounter;
                if (counterTt > 0)
                {
                    ticksTt = (ticks - prevTicks) / counterTt;
                }
                else
                {
                    ticksTt = 0;
                }

                prevTicks   = ticks;
                prevCounter = localCounter;
            }

            // Total time
            // (Add 5 ticks for simple microseconds rounding)
            long roundTicks = ticks + 5;
            int  seconds    = (int)(roundTicks / 10000000);
            int  ms         = (int)((roundTicks % 10000000) / 10000);
            int  us         = (int)((roundTicks % 10000) / 10);

            // Per call, this time (since last item)
            long roundTicksTt = ticksTt + 5;
            int  secondsTt    = (int)(roundTicksTt / 10000000);
            int  msTt         = (int)((roundTicksTt % 10000000) / 10000);
            int  usTt         = (int)((roundTicksTt % 10000) / 10);

            // Per call time
            long roundTicksPc = ticksPc + 5;
            int  secondsPc    = (int)(roundTicksPc / 10000000);
            int  msPc         = (int)((roundTicksPc % 10000000) / 10000);
            int  usPc         = (int)((roundTicksPc % 10000) / 10);

            string text    = "Custom timer " + key + " at " + localCounter;
            string details =
                localCounter + " calls\n" +
                secondsPc.ToString() + "." +
                msPc.ToString("000") + "\u2009" +
                usPc.ToString("000") + " seconds per call (" + ticksPc + " ticks)\n" +
                secondsTt.ToString() + "." +
                msTt.ToString("000") + "\u2009" +
                usTt.ToString("000") + " seconds per call since last item (" + ticksTt + " ticks)\n" +
                seconds.ToString() + "." +
                ms.ToString("000") + "\u2009" +
                us.ToString("000") + " seconds total (" + ticks + " ticks)";

            FL.Trace(text, details);
        }
 /// <summary>
 /// Logs an exception raised in the task. Call this like the ContinueWith method with the
 /// <see cref="TaskContinuationOptions.OnlyOnFaulted"/> option.
 /// </summary>
 /// <typeparam name="TResult">The type of the result produced by this Task.</typeparam>
 /// <param name="task"></param>
 /// <param name="prio">The priority of the log item.</param>
 /// <param name="taskName">The name of the task, used for the exception log item context.</param>
 /// <returns>A new continuation <see cref="Task"/>.</returns>
 public static Task LogFaulted <TResult>(this Task <TResult> task, FieldLogPriority prio, string taskName)
 {
     return(task.ContinueWith(t => FL.Exception(prio, t.Exception, taskName + " Task"), TaskContinuationOptions.OnlyOnFaulted));
 }
예제 #15
0
 /// <summary>
 /// Initialises a new instance of the FieldLogThreadScope class and logs the thread scope
 /// beginning.
 /// </summary>
 /// <param name="name">The thread scope name.</param>
 public FieldLogThreadScope(string name)
 {
     this.name = name;
     FL.LogScope(FieldLogScopeType.ThreadStart, name);
 }
예제 #16
0
 /// <summary>
 /// Initialises a new instance of the CustomTimerScope class and calls the Start method of
 /// the CustomTimerInfo instance.
 /// </summary>
 /// <param name="key">The custom timer key for a dictionary lookup.</param>
 /// <param name="incrementCounter">Increment the counter value.</param>
 /// <param name="writeImmediately">true to write the timer value immediately when stopping, false for the normal delay.</param>
 public CustomTimerScope(string key, bool incrementCounter, bool writeImmediately)
 {
     this.key = key;
     this.writeImmediately = writeImmediately;
     cti = FL.StartTimer(key, incrementCounter);
 }
예제 #17
0
 /// <summary>
 /// Initialises a new instance of the FieldLogScope class and logs the scope beginning.
 /// </summary>
 /// <param name="name">The scope name.</param>
 public FieldLogScope(string name)
 {
     this.name = name;
     FL.Enter(name);
 }
예제 #18
0
        private AppErrorDialog()
        {
            if (!appErrorInitialized)
            {
                Application.EnableVisualStyles();
                appErrorInitialized = true;
            }

            string title   = FL.AppErrorDialogTitle;
            string appName = FL.AppName;

            if (!string.IsNullOrEmpty(appName))
            {
                title = appName + " – " + title;
            }

            AutoScaleDimensions = new SizeF(96, 96);
            AutoScaleMode       = AutoScaleMode.Dpi;
            scaleFactor         = CurrentAutoScaleDimensions.Width / 96;

            BackColor       = SystemColors.Window;
            ControlBox      = false;
            MinimizeBox     = false;
            MaximizeBox     = false;
            Font            = SystemFonts.MessageBoxFont;
            FormBorderStyle = FormBorderStyle.FixedDialog;
            ShowInTaskbar   = false;
            Size            = new Size(Scale(550), Scale(350));
            StartPosition   = FormStartPosition.CenterScreen;
            Text            = title;
            TopMost         = true;

            tablePanel          = new TableLayoutPanel();
            tablePanel.Dock     = DockStyle.Fill;
            tablePanel.RowCount = 6;
            tablePanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
            tablePanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
            tablePanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
            tablePanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
            tablePanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 0));
            tablePanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
            tablePanel.ColumnCount = 1;
            tablePanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
            Controls.Add(tablePanel);

            introLabel           = new Label();
            introLabel.BackColor = Color.FromArgb(221, 74, 59);
            introLabel.ForeColor = Color.White;
            introLabel.Dock      = DockStyle.Fill;
            introLabel.AutoSize  = true;
            introLabel.Font      = new Font(
                SystemFonts.MessageBoxFont.FontFamily,
                SystemFonts.MessageBoxFont.SizeInPoints * 1.3f,
                SystemFonts.MessageBoxFont.Style);
            introLabel.MaximumSize = new Size(ClientSize.Width, 0);
            introLabel.Padding     = Scale(new Padding(6, 4, 7, 6));
            introLabel.Margin      = new Padding();
            introLabel.UseCompatibleTextRendering = false;
            introLabel.UseMnemonic = false;
            tablePanel.Controls.Add(introLabel);
            tablePanel.SetRow(introLabel, 0);
            tablePanel.SetColumn(introLabel, 0);

            errorPanel            = new Panel();
            errorPanel.AutoScroll = true;
            errorPanel.Dock       = DockStyle.Fill;
            errorPanel.Margin     = Scale(new Padding(7, 8, 10, 6));
            errorPanel.Padding    = new Padding();
            tablePanel.Controls.Add(errorPanel);
            tablePanel.SetRow(errorPanel, 1);
            tablePanel.SetColumn(errorPanel, 0);

            errorLabel          = new Label();
            errorLabel.AutoSize = true;
            // Always keep the vertical scrollbar width free because the label wouldn't get smaller
            // when the vertical scrollbar appears and then the horizontal scrollbar kicks in as well.
            errorLabel.MaximumSize = new Size(errorPanel.ClientSize.Width - SystemInformation.VerticalScrollBarWidth - 2, 0);
            errorLabel.Padding     = new Padding();
            errorLabel.Margin      = new Padding();
            errorLabel.UseCompatibleTextRendering = false;
            errorLabel.UseMnemonic = false;
            errorPanel.Controls.Add(errorLabel);

            logLabel             = new LinkLabel();
            logLabel.AutoSize    = true;
            logLabel.MaximumSize = new Size(ClientSize.Width - Scale(20), 0);
            logLabel.Margin      = Scale(new Padding(8, 6, 10, 0));
            logLabel.Padding     = new Padding();
            if (FL.LogFileBasePath != null)
            {
                logLabel.Text = string.Format(FL.AppErrorDialogLogPath, FL.LogFileBasePath.Replace("\\", "\\\u200B") + "*.fl");
                string dir = Path.GetDirectoryName(FL.LogFileBasePath).Replace("\\", "\\\u200B");
                logLabel.LinkArea     = new LinkArea(FL.AppErrorDialogLogPath.IndexOf("{0}", StringComparison.Ordinal), dir.Length);
                logLabel.LinkClicked += (s, e) =>
                {
                    Process.Start(Path.GetDirectoryName(FL.LogFileBasePath));
                };
            }
            else
            {
                logLabel.Text     = FL.AppErrorDialogNoLog;
                logLabel.LinkArea = new LinkArea(0, 0);
            }
            logLabel.UseCompatibleTextRendering = false;
            logLabel.UseMnemonic = false;
            tablePanel.Controls.Add(logLabel);
            tablePanel.SetRow(logLabel, 2);
            tablePanel.SetColumn(logLabel, 0);

            detailsLabel          = new LinkLabel();
            detailsLabel.AutoSize = true;
            detailsLabel.Margin   = Scale(new Padding(7, 6, 10, 10));
            detailsLabel.Padding  = new Padding();
            detailsLabel.TabIndex = 11;
            detailsLabel.Text     = FL.AppErrorDialogDetails;
            detailsLabel.UseCompatibleTextRendering = false;
            detailsLabel.Visible = CanShowDetails;
            tablePanel.Controls.Add(detailsLabel);
            tablePanel.SetRow(detailsLabel, 3);
            tablePanel.SetColumn(detailsLabel, 0);

            var attr = new TypeConverterAttribute(typeof(ExpandableObjectConverter));

            TypeDescriptor.AddAttributes(typeof(Exception), attr);
            grid                            = new PropertyGrid();
            grid.Dock                       = DockStyle.Fill;
            grid.Margin                     = Scale(new Padding(10, 10, 10, 10));
            grid.ToolbarVisible             = false;
            grid.HelpVisible                = false;
            grid.PropertySort               = PropertySort.Alphabetical;
            grid.UseCompatibleTextRendering = false;
            grid.Visible                    = false;
            tablePanel.Controls.Add(grid);
            tablePanel.SetRow(grid, 4);
            tablePanel.SetColumn(grid, 0);

            bool isGridColumnResized = false;

            grid.Resize += (s, e) =>
            {
                if (!isGridColumnResized)
                {
                    isGridColumnResized = true;
                    // Source: http://stackoverflow.com/a/14475276/143684
                    FieldInfo fi = grid.GetType().GetField("gridView", BindingFlags.Instance | BindingFlags.NonPublic);
                    if (fi != null)
                    {
                        Control view = fi.GetValue(grid) as Control;
                        if (view != null)
                        {
                            MethodInfo mi = view.GetType().GetMethod("MoveSplitterTo", BindingFlags.Instance | BindingFlags.NonPublic);
                            if (mi != null)
                            {
                                mi.Invoke(view, new object[] { Scale(170) });
                            }
                            mi = view.GetType().GetMethod("set_GrayTextColor", BindingFlags.Instance | BindingFlags.NonPublic);
                            if (mi != null)
                            {
                                mi.Invoke(view, new object[] { Color.Black });
                            }
                        }
                    }
                }
            };

            detailsLabel.LinkClicked += (s, e) =>
            {
                detailsLabel.Hide();
                int maxHeight     = Screen.FromControl(this).Bounds.Height;
                int missingHeight = 0;
                int desiredHeight = Height + Scale(300);
                Height = desiredHeight;
                if (Height < desiredHeight)
                {
                    // A window is automatically constrained to the size of its screen, so we can
                    // compare the current size with what we had requested to know how much is
                    // missing for the layout.
                    missingHeight = desiredHeight - Height;
                }
                Top -= Scale(Math.Min(Top - 4, 150));
                if (Top < 0)
                {
                    Top = 0;
                }
                tablePanel.RowStyles[4].Height = Scale(350) - missingHeight;
                grid.Visible = true;
            };

            buttonsPanel              = new TableLayoutPanel();
            buttonsPanel.AutoSize     = true;
            buttonsPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            buttonsPanel.BackColor    = SystemColors.Control;
            buttonsPanel.Dock         = DockStyle.Fill;
            buttonsPanel.Margin       = new Padding();
            buttonsPanel.Padding      = Scale(new Padding(10, 10, 10, 10));
            buttonsPanel.ColumnCount  = 4;
            buttonsPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
            buttonsPanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
            buttonsPanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
            buttonsPanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
            tablePanel.Controls.Add(buttonsPanel);
            tablePanel.SetRow(buttonsPanel, 5);
            tablePanel.SetColumn(buttonsPanel, 0);

            sendCheckBox          = new CheckBox();
            sendCheckBox.Anchor   = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Bottom;
            sendCheckBox.AutoSize = true;
            sendCheckBox.Enabled  = FL.CanSubmitLog;
            if (sendCheckBox.Enabled)
            {
                sendCheckBox.Checked = true;
            }
            sendCheckBox.FlatStyle = FlatStyle.System;
            sendCheckBox.Margin    = new Padding();
            sendCheckBox.Padding   = new Padding();
            sendCheckBox.Text      = FL.AppErrorDialogSendLogs;
            sendCheckBox.UseCompatibleTextRendering = false;
            buttonsPanel.Controls.Add(sendCheckBox);
            buttonsPanel.SetRow(sendCheckBox, 0);
            buttonsPanel.SetColumn(sendCheckBox, 0);

            nextButton              = new Button();
            nextButton.AutoSize     = true;
            nextButton.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            nextButton.FlatStyle    = FlatStyle.System;
            nextButton.Margin       = Scale(new Padding(6, 0, 0, 0));
            nextButton.Padding      = Scale(new Padding(2, 1, 2, 1));
            nextButton.Text         = FL.AppErrorDialogNext;
            nextButton.UseCompatibleTextRendering = false;
            nextButton.UseVisualStyleBackColor    = true;
            nextButton.Visible = false;
            nextButton.Click  += (s, e) =>
            {
                ShowNextError();
            };
            buttonsPanel.Controls.Add(nextButton);
            buttonsPanel.SetRow(nextButton, 0);
            buttonsPanel.SetColumn(nextButton, 1);

            terminateButton              = new Button();
            terminateButton.AutoSize     = true;
            terminateButton.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            terminateButton.FlatStyle    = FlatStyle.System;
            terminateButton.Margin       = Scale(new Padding(6, 0, 0, 0));
            terminateButton.Padding      = Scale(new Padding(2, 1, 2, 1));
            terminateButton.Text         = FL.AppErrorDialogTerminate;
            terminateButton.UseCompatibleTextRendering = false;
            terminateButton.UseVisualStyleBackColor    = true;
            terminateButton.Click += (s, e) =>
            {
                StartSubmitTool();
                Close();
                FL.Shutdown();
                Environment.Exit(1);
            };
            buttonsPanel.Controls.Add(terminateButton);
            buttonsPanel.SetRow(terminateButton, 0);
            buttonsPanel.SetColumn(terminateButton, 2);

            continueButton              = new Button();
            continueButton.AutoSize     = true;
            continueButton.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            continueButton.FlatStyle    = FlatStyle.System;
            continueButton.Margin       = Scale(new Padding(6, 0, 0, 0));
            continueButton.Padding      = Scale(new Padding(2, 1, 2, 1));
            continueButton.Text         = FL.AppErrorDialogContinue;
            continueButton.UseCompatibleTextRendering = false;
            continueButton.UseVisualStyleBackColor    = true;
            continueButton.Click += (s, e) =>
            {
                StartSubmitTool();
                Close();
            };
            buttonsPanel.Controls.Add(continueButton);
            buttonsPanel.SetRow(continueButton, 0);
            buttonsPanel.SetColumn(continueButton, 3);
        }
        /// <summary>
        /// Purges screenshot files.
        /// </summary>
        public static void Purge()
        {
            try
            {
                string basePath = FL.LogFileBasePath;
                if (basePath == null)
                {
                    return;                       // Nothing to do
                }
                string logDir  = Path.GetDirectoryName(basePath);
                string logFile = Path.GetFileName(basePath);

                DateTime purgeTime = FL.UtcNow.Subtract(KeepTime);
                foreach (string fileName in Directory.GetFiles(logDir, logFile + "-scr-*.*"))
                {
                    FileInfo fi = new FileInfo(fileName);
                    if (fi.LastWriteTimeUtc < purgeTime)
                    {
                        // File is old enough to be deleted
                        try
                        {
                            File.Delete(fileName);
                        }
                        catch
                        {
                            // Retry next time (might be locked by a log viewer reading the file)
                        }
                    }
                }

                // Keep maximum data size
                string[]   fileNames     = Directory.GetFiles(logDir, logFile + "-scr-*.*");
                DateTime[] fileTimes     = new DateTime[fileNames.Length];
                long[]     fileSizes     = new long[fileNames.Length];
                long       totalUsedSize = 0;
                for (int i = 0; i < fileNames.Length; i++)
                {
                    FileInfo fi = new FileInfo(fileNames[i]);
                    fileTimes[i]   = fi.LastWriteTimeUtc;
                    fileSizes[i]   = fi.Length;
                    totalUsedSize += fileSizes[i];
                }
                while (totalUsedSize > MaxTotalSize)
                {
                    // Find oldest file
                    int      oldestIndex = -1;
                    DateTime oldestTime  = DateTime.MaxValue;
                    for (int i = 0; i < fileTimes.Length; i++)
                    {
                        if (fileTimes[i] < oldestTime)
                        {
                            oldestTime  = fileTimes[i];
                            oldestIndex = i;
                        }
                    }
                    if (oldestIndex == -1)
                    {
                        break;                                          // Nothing more to delete
                    }
                    // Delete the file and reduce the total size
                    try
                    {
                        File.Delete(fileNames[oldestIndex]);
                        totalUsedSize -= fileSizes[oldestIndex];
                    }
                    catch
                    {
                        // Try the next file
                    }
                    fileTimes[oldestIndex] = DateTime.MaxValue;                       // Don't consider this file again
                }
            }
            catch (Exception ex)
            {
                FL.Error(ex, "Purging screenshots");
            }
        }
예제 #20
0
 /// <summary>
 /// Initialises a new instance of the CustomTimerScope class and calls the Start method of
 /// the CustomTimerInfo instance.
 /// </summary>
 /// <param name="key">The custom timer key for a dictionary lookup.</param>
 public CustomTimerScope(string key)
 {
     this.key = key;
     cti      = FL.StartTimer(key);
 }
 /// <summary>
 /// Logs an exception raised in the task. Call this like the ContinueWith method with the
 /// <see cref="TaskContinuationOptions.OnlyOnFaulted"/> option.
 /// </summary>
 /// <typeparam name="TResult">The type of the result produced by this Task.</typeparam>
 /// <param name="task"></param>
 /// <param name="taskName">The name of the task, used for the exception log item context.</param>
 /// <returns>A new continuation <see cref="Task"/>.</returns>
 public static Task LogFaulted <TResult>(this Task <TResult> task, string taskName)
 {
     return(task.ContinueWith(t => FL.Error(t.Exception, taskName + " Task"), TaskContinuationOptions.OnlyOnFaulted));
 }