MSN Messenger 日志侦听器






4.66/5 (18投票s)
2006 年 1 月 11 日
6分钟阅读

133192

1470
用于 Microsoft Enterprise Library 日志记录框架的自定义日志侦听器。
代码下载已更新为 Enterprise Library 的最终版本,包括对 EntLibConfig 应用程序的设计支持。
引言
一群比我聪明得多的程序员已经辛勤工作了一段时间,旨在创建实用程序库,以帮助像我这样的开发人员创建更好的应用程序。这项工作的成果是 Microsoft Patterns & Practices 团队的 Enterprise Library。Enterprise Library 涵盖了异常处理、日志记录、缓存、安全性、加密和数据库访问。最新版本的 Enterprise Library 适用于 .NET 2.0 框架,还包括一个 ObjectBuilder
,它允许通过依赖注入创建对象。如果我说我完全理解 ObjectBuilder
的作用,那我就是在撒谎。Brian Button 发布了我迄今为止找到的关于 ObjectBuilder
最完整的信息。由于 Enterprise Library 尚未正式发布,目前文档稀缺。本文中涉及的代码基于 .NET Framework 2.0 的新 Enterprise Library 的 12 月社区技术预览版。
本文的重点是 Enterprise Library 中的日志记录部分。有关日志记录框架的概述,请参阅此 MSDN 文档。日志记录框架的功能之一是将日志消息发送到一个或多个侦听器,例如平面文件、电子邮件、数据库或 Microsoft 消息队列。日志记录框架的构建方式允许像我这样的开发人员创建用于日志消息的自定义侦听器。如果您还没有猜到,我创建了一个自定义日志侦听器,它将日志消息发送到 MSN Messenger 帐户。
好东西
我使用 FormattedDatabaseTraceListener
作为创建侦听器的参考。自定义侦听器实际上由三个类组成
- 实际的侦听器类,负责将日志消息作为 MSN Messenger 消息发送。
- 一个数据配置类,负责从 CONFIG 文件(app.config/web.config)读取配置数据。
- 一个汇编程序类,负责根据配置类创建侦听器对象(我认为这是
ObjectBuilder
的魔力)。
我们的侦听器类是 FormattedMsnMessengerTraceListener
,我将对其进行深入介绍。FormattedMsnMessengerTraceListenerData
和 FormattedMsnMessengerTraceListenerAssembler
处理自定义侦听器的配置和组装。这两个类在很大程度上是自解释的,但如果您有任何问题,请提出,我将尽力回答。
FormattedMsnMessengerTraceListener
为了发送 MSN Messenger 消息,我在互联网上搜索了现有的解决方案,并找到了 XIH Solutions 创建的一个很棒的库,名为 DotMSN。DotMSN 提供了一个托管代码库,用于创建自定义 MSN Messenger 客户端。我的自定义日志侦听器充当一个精简的客户端,只发送消息。
构造函数
构造函数初始化侦听器使用的所有数据,并启动连接到 MSN Messenger 服务器的过程。侦听器的配置值如下所述
senderAccount |
用于发送日志消息的 MSN Messenger 帐户。 |
senderPassword |
上述帐户的密码。 |
receiverAccounts |
以分号 (;) 分隔的 MSN Messenger 帐户列表,将接收日志消息。 |
connectionRetryInterval |
(可选)连接尝试之间的间隔时间(分钟)。默认值 = 5 分钟。 |
invitationRetryInterval |
(可选)邀请尝试之间的间隔时间(分钟)。默认值 = 5 分钟。 |
maxMessageQueue |
(可选)要排队等待发送的最大消息数。如果超出此值,则在添加最新消息之前从队列中删除最旧的消息。默认值 = 5 条消息。 |
public override void Write( string sMessage )
每当开发人员希望记录信息时,日志记录框架都会调用 Write
方法。我们的实现首先将消息排队
if (String.Empty != sMessage)
{
if (_iMaxMessageQueue <= _messageQueue.Count)
{
_messageQueue.Dequeue();
}
_messageQueue.Enqueue(sMessage);
}
消息之所以排队,是因为连接到 MSN Messenger 需要时间(通常取决于连接速度,需要 3-4 秒)。如果所有消息接收者都离线,消息也会排队。因此,您不应将 MSN Messenger 日志侦听器作为主要日志侦听器。如果所有收件人都离线,则日志消息将丢失。代码下载中包含的示例控制台应用程序同时使用平面文件侦听器和 MSN Messenger 侦听器。
DotMSN 库使用多线程和委托来通知开发人员各种 Messenger 相关事件。我声称自己不是多线程开发人员,因此 DotMSN 库和我的自定义侦听器之间可能存在更好的事件同步方式。下一段代码同步 DotMSN 库抛出的任何异常,并将它们传播到 Enterprise Library 日志记录框架
if (null != _thrownException)
{
lock (_oExceptionLock)
{
if (null != _thrownException)
{
try
{
throw _thrownException;
}
finally
{
_thrownException = null;
}
}
}
}
在记录消息之前的最后一步是确保我们与 MSN Messenger 服务器建立了有效的连接,并且与至少一个收件人建立了有效的 MSN 对话。这两个条件通过后面介绍的两个辅助方法进行验证。如果一切正常,所有排队的消息都将发送给收件人
if (true == _EnsureConnection() && true == _EnsureConversation())
{
while (0 < _messageQueue.Count)
{
TextMessage message =
new TextMessage(_messageQueue.Dequeue());
_conversation.Switchboard.SendTextMessage(message);
}
}
bool _EnsureConnection()
我开发我的自定义侦听器时,考虑到利用 Enterprise Library 日志记录框架的应用程序可能 24/7 运行,但日志消息接收者可能不会 24/7 连接到 MSN Messenger 网络。考虑到这一点,_EnsureConnection()
方法检查它是否当前连接到 MSN Messenger 网络。如果是,则返回 true
if (true == _messenger.Connected &&
true == _messenger.Nameserver.IsSignedIn )
{
return true;
}
如果没有连接到网络,首先我们检查是否正在连接。如果我们没有连接,我们就会启动一个连接。最后的检查是为了应对网络中断或连接中断的可能性。如果我们正在连接,但自开始连接以来已经超过五分钟(默认情况下),那么重新开始连接过程
if (false == _bConnecting)
{
lock (_oConnectingLock)
{
if (false == _bConnecting)
{
_messenger.Disconnect();
_bConnecting = true;
_dtLastConnectionAttempt = DateTime.Now;
_messenger.Connect();
}
}
}
else if( _tsConnectionRetryInterval <=
(DateTime.Now - _dtLastConnectionAttempt) )
{
lock (_oConnectingLock)
{
_bConnecting = false;
}
}
bool _EnsureConversation()
此方法执行的操作与 _EnsureConnection()
大致相同,只不过我们检查的不是连接,而是与参与者的现有会话。如果不存在,我们将启动创建 Conversation
的过程
if (null != _conversation &&
0 < _conversation.Switchboard.Contacts.Count)
{
return true;
}
if (false == _bInviting)
{
lock (_oInvitingLock)
{
if (false == _bInviting)
{
_bInviting = true;
_dtLastInvitationAttempt = DateTime.Now;
foreach (string receiver in _sReceiverAccounts)
{
_conversation.Invite(receiver);
}
}
}
}
else if ( _tsInvitationRetryInterval <=
(DateTime.Now - _dtLastInvitationAttempt) )
{
lock (_oInvitingLock)
{
_bInviting = false;
}
}
DotMSN 事件
自定义侦听器的最后部分是 DotMSN 事件的处理程序,包括抛出的异常、成功登录 MSN Messenger 网络以及收件人加入会话的信号。
测试
测试侦听器有点棘手,因为您不能使用同一个帐户两次登录 MSN Messenger。我不得不让我妻子使用她的帐户登录 MSN Messenger,然后将侦听器配置为使用我的帐户作为发件人帐户。简而言之,您需要两个 MSN 帐户来测试侦听器。
EntLibConfig
我向代码中添加了一个新项目,以支持 Enterprise Library 附带的 EntLibConfig 应用程序。您现在可以使用图形配置编辑器向应用程序添加/修改 MSN Messenger 跟踪侦听器。要使用 EntLibConfig,您需要将 WCPierce.Practices.EnterpriseLibrary.Logging.MsnMessenger.Configuration.Design.dll、WCPierce.Practices.EnterpriseLibrary.Logging.MsnMessenger.dll 和 XihSolutions.DotMSN.dll 复制到与 EntLibConfig.exe 相同的目录中。然后您应该能够添加 MSN Messenger 跟踪侦听器。请参阅下图示例
结论
FormattedMsnMessengerTraceListener
是为 Enterprise Library 日志记录框架创建自定义日志侦听器的一次有趣的练习。正如我上面所说,请不要将此侦听器用于任何关键任务。它与异常处理框架结合使用时最有用,可即时通知应用程序中出现的任何严重错误(这从未发生过,对吧?)。我鼓励您下载代码并查看侦听器,我很乐意听到任何认为它有用并将其用于其应用程序的人的意见。