8

作为 C# 应用程序的作者,我发现如果我可以访问异常或调试日志,则对用户报告的问题进行故障排除会容易得多。

我已经包含了一个用户可以打开或关闭的本土日志记录机制。我希望用户能够通过互联网提交日志,以便我可以查看日志中的错误。

我曾想过使用SMTPClientWeb 服务来发送信息。SMTPClient 可能无法工作,因为防火墙可能会阻止传出 SMTP 访问。Web 服务是否会在发送大量数据(可能超过 1 MB)时出现问题?

作为让应用程序将错误报告直接发送给开发人员进行审查的最佳方式,您会推荐什么?

编辑:澄清:这是一个 Windows 应用程序,当发生错误时,我想弹出一个对话框,要求提交错误。我的问题是关于通过互联网将错误日志从应用程序传输给我(开发人员)的机制。

4

6 回答 6

3

某种方式让用户知道你的意思是这样做。向他们索要代理,向他们索要电子邮件服务器,诸如此类。

如果他们发现您正在打开一个套接字或类似的东西并在没有通知的情况下发送数据,那么具有安全意识的人会非常紧张。

没错。

于 2009-05-24T03:01:52.097 回答
3

我建议不要发送所有内容(对您的应用程序的整个审核)。
但如果用户想要它(“反馈”按钮)或者如果应用程序中存在显式异常、致命错误、问题状态。

我们同时使用了 Web 服务和电子邮件 (SMTPClient)。我对这些的看法

网络服务

  • 每个用户没有特殊配置
  • 大小限制,超过 5Mb-8MB 的电子邮件是可能的

坏的

  • 公开可见(黑客喜欢玩这些东西)
  • 附加开发以使用 db 后端创建 Web 服务
  • 稍后创建其他字段是不好的
  • Web 服务的更改并不好!

SMTP客户端

  • 每个用户没有特殊配置
  • 登录到公用文件夹使搜索/过滤变得容易(分组,...)
  • 可以发送的所有数据、屏幕截图、堆栈跟踪、用户设置、...
    --> HTML
  • 日志格式和信息的更改很容易,因为我们使用 HTML 电子邮件

坏的

  • 每个用户的特殊配置(smtp 服务器,电子邮件用户,...)
  • 电子邮件大小限制(5MB-8MB ??)
  • 登录到电子邮件数据库需要大量开发
于 2009-05-24T04:17:41.357 回答
2

您可以自己编写,也可以使用log4net之类的东西,它会为您处理异常日志记录...

于 2009-05-24T03:01:29.400 回答
2

我们在我工作的地方使用 3 种方法

  • SMTP 到专用邮箱。这需要大量配置,并与“大公司”IT 部门合作,以确定他们的邮件服务器是什么,以及如何对其进行身份验证并通过它发送。还有像 Norton Internet Security 这样的程序可以阻止客户端机器上的出站 SMTP 流量,这会在工作中抛出额外的扳手。
  • 提交到我们服务器上的 asmx。这是我们的首选方法,但有很多事情会妨碍您。它主要是代理,但诺顿也可以介入并击倒你。如果涉及代理,请逃跑:-)
  • HTTP POST 使用 HttpWebRequest 和多部分/表单编码的 mime 类型。它也有代理和防火墙问题,但有时可以在 asmx 提交失败的情况下工作。

祝你好运。你是对的,如果你有堆栈跟踪,甚至可能是可怜的老用户在做什么的屏幕截图,调试起来会容易得多。

于 2009-05-24T03:36:37.117 回答
0

我喜欢将此类内容作为电子邮件发送到专用邮箱。这样我就可以轻松地归档、搜索或忽略它。

在客户端/发送方方面,我认为发送日志的弹出窗口是个好主意。如果是 windows,您可以使用 MAPI 发送电子邮件。在 unix 系统上,“邮件”问题适用于大多数系统。

您可以在确认消息中提示用户输入电子邮件地址,并可能提供一些关于如何发送的选项(包括复制/粘贴到他们选择的邮件客户端)。

您不应该做的一件事是未经用户许可发送信息。

于 2009-05-24T03:13:05.070 回答
0

如果您不希望在一天内发送这么多报告……您可以创建一个 gmail 帐户并使用它来发送电子邮件,以避免强制用户配置 SMTP 服务器。不确定 gmail 的条款和条件是什么。

这是我写的一个类,它使用 gmail 帐户发送电子邮件......

显然这里存在一些安全问题,例如有人可能会访问您的 gmail 帐户。所以,考虑到这一点。

该类中有同步或异步发送电子邮件的方法。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Collections;
using System.Text;
using System.Net;
using System.Net.Mail;
using System.Net.Mime; 
//Mime is Not necerrary if you dont change the msgview and 
//if you dont add custom/extra headers 
using System.Threading;
using System.IO;
using System.Windows.Forms; // needed for MessageBox only.



namespace BR.Util
{
    public class Gmailer
    {

        SmtpClient client = new SmtpClient();
        static String mDefaultToAddress = "yourToAddress@yourdomain.com";
        static String mDefaultFromAddress = "anonymous@gmail.com";
        static String mDefaultFromDisplayName = "Anonymous";

        String mGmailLogin = "someaccount@gmail.com";
        String mGmailPassword = "yourpassword";


        public Gmailer()
        {
            client.Credentials = new System.Net.NetworkCredential(mGmailLogin, mGmailPassword);
            client.Port = 587;           
            client.Host = "smtp.gmail.com";
            client.EnableSsl = true;
            client.SendCompleted += new SendCompletedEventHandler(Gmailer_DefaultAsyncSendCompletedHandler);
        }

        public void setSendCompletedHandler(SendCompletedEventHandler pHandler)
        {
            client.SendCompleted -= Gmailer_DefaultAsyncSendCompletedHandler;
            client.SendCompleted += pHandler;
        }

        /// <summary>
        /// Static method which sends an email synchronously.
        /// It uses a hardcoded from email.
        /// </summary>
        /// <returns></returns>
        public static bool quickSend(String toEmailAddress, String subject, String body)
        {
            return Gmailer.quickSend(toEmailAddress, mDefaultFromAddress, mDefaultFromDisplayName, subject, body);
        }

        /// <summary>
        /// Static method which sends an email synchronously.
        /// It uses the hardcoded email address.
        /// </summary>
        /// <returns>true if successful, false if an error occurred.</returns>
        public static bool quickSend(String toEmailAddress, String fromEmailAddress,
                                     String fromDisplayName, String subject, String body)
        {
            try
            {
                Gmailer gmailer = new Gmailer();
                System.Net.Mail.MailMessage mailMsg = gmailer.createMailMessage(toEmailAddress, fromEmailAddress, fromDisplayName, subject, body);
                gmailer.send(mailMsg);
            }
            catch (Exception ex)
            {
                return false;
            }
            return true;
        }

        // <summary> creates a MailMessage object initialized with the default values.</summary>
        public System.Net.Mail.MailMessage createMailMessage()
        {
            return createMailMessage(mDefaultToAddress, mDefaultFromAddress, mDefaultFromDisplayName, mDefaultEmailSubject, mDefaultEmailBody);
        }

        public System.Net.Mail.MailMessage createMailMessage(String toEmailAddress, String fromEmailAddress, 
                                                             String fromDisplayName, String subject, String body)
        {
            //Build The MSG
            System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage();
            msg.To.Add(toEmailAddress);
            msg.From = new MailAddress(fromEmailAddress, fromDisplayName, System.Text.Encoding.UTF8);
            msg.Subject = subject;
            msg.SubjectEncoding = System.Text.Encoding.UTF8;
            msg.Body = body;
            msg.BodyEncoding = System.Text.Encoding.UTF8;
            msg.IsBodyHtml = false;
            msg.Priority = MailPriority.High;
            return msg;
        }

        public System.Net.Mail.MailMessage addAttachmentToMailMessage(System.Net.Mail.MailMessage msg, String attachmentPath)
        {
            msg.Attachments.Add(new Attachment(attachmentPath));
            return msg;
        }

        // <summary> method which blocks until the MailMessage has been sent.  Throws
        // System.Net.Mail.SmtpException if error occurs.</summary>
        public void send(System.Net.Mail.MailMessage pMailMessage)
        {
            //try {
                client.Send(pMailMessage);
            //}
            //catch (System.Net.Mail.SmtpException ex)
            //{
            //    MessageBox.Show(ex.Message, "Send Mail Error");
            //}
        }

        // 
        public void sendAsync(System.Net.Mail.MailMessage pMailMessage)
        {
            object userState = pMailMessage;
            try
            {
                MailSent = false;
                client.SendAsync(pMailMessage, userState);
            }
            catch (System.Net.Mail.SmtpException ex)
            {
                MessageBox.Show(ex.Message, "Send Mail Error");
            }
        }

        // <summary> 
        // Provides a default SendComplete handler which is activated when an AsyncCompletedEvent 
        // is triggered by the private client variable.  This is useful for debugging etc.
        // Use the method setSendCompletedHandler to define your own application specific handler.
        // That method also turns this handler off.
        // </summary>
        public void Gmailer_DefaultAsyncSendCompletedHandler(object sender, AsyncCompletedEventArgs e)
        {
            MailMessage mail = (MailMessage)e.UserState;
            string subject = mail.Subject;

            if (e.Cancelled)
            {
                string cancelled = string.Format("[{0}] Send canceled.", subject);
                MessageBox.Show(cancelled);                
            }
            if (e.Error != null)
            {
                string error = String.Format("[{0}] {1}", subject, e.Error.ToString());
                MessageBox.Show(error);                
            }
            else
            {
                MessageBox.Show("Message sent.");
            }
            MailSent = true;
        }


        private bool _MailSent = false;
        /// <summary>
        /// Set to false when an async send operation is started and is set to true when finished.
        /// </summary>
        public bool MailSent
        {
            set
            {
                _MailSent = value;
            }
            get
            {
                return _MailSent;
            }
        }
    }
}
于 2009-06-19T08:27:43.117 回答