我们目前编写了一个托管在 Windows 服务中的 MSMQ WCF 服务,该服务充当电子邮件队列服务。这个想法是,我们所有的客户端应用程序都可以被多个并发客户端访问,可以将电子邮件提交到一个集中的可靠队列系统。提交电子邮件后,该服务会处理队列中的作业(这是一个自定义电子邮件对象)并将其发送出去。
我们遇到的问题是,实际打开 ServiceHost 的代码部分似乎被沙箱化,并阻止我们的服务代码写入事件日志或写入自定义日志文件(由 NLog 管理)。这里的奇怪之处在于代码还具有将文件系统上的文件移动到另一个位置的功能 - 这可以正常工作 - 但如前所述,无法写入事件日志或日志文件。由于我们设置了 AppDomain.UnhandledException 处理程序,因此似乎也没有抛出异常。
我们曾尝试将 Windows 服务“运行方式”帐户从本地服务更改为域管理员,再更改为随机用户,但似乎没有任何效果。我们能够证明在实际的“ServiceHost.Open()”调用之前,我们可以成功地写入事件日志和自定义日志文件。只有在 ServiceHost 托管的实际类中才会出现问题。
我想认为它是权限,但如前所述,我们可以移动文件 - 所以至少可以说似乎是矛盾的。托管环境是 Windows Server 2003 R2 x64,我们使用的是 .NET 4.0。
** 作为说明,如果我们删除注册表/自定义日志记录代码,并且仅具有发送电子邮件功能(通过 .NET SMTP 客户端对象),则电子邮件将正确发送。
片段 1 - WCF 服务代码本身,只是尝试写入注册表,这不起作用并且显然不会引发异常:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, IncludeExceptionDetailInFaults = true)]
public class EmailQueueListener : IEmailQueuingService
{
[OperationBehavior(TransactionScopeRequired = false, TransactionAutoComplete = true)]
public void SendEmailToQueue(SerializableMailMessage emailMessage)
{
var eventLogSrc = "Email Service";
var eventLogLogType = "[APP NAME HERE]";
if (!EventLog.SourceExists(eventLogSrc))
EventLog.CreateEventSource(eventLogSrc, eventLogLogType);
EventLog.WriteEntry(eventLogSrc, "TESTING", EventLogEntryType.Information);
片段 2 - 启动服务主机的代码,从 Windows 服务的 OnStart 方法调用:
public static void Start(bool isConsole = false)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
ConsoleLog.Info("TEST");
var eventLogSrc = "Email Service";
var eventLogLogType = "[APP NAME HERE]";
if (!EventLog.SourceExists(eventLogSrc))
EventLog.CreateEventSource(eventLogSrc, eventLogLogType);
EventLog.WriteEntry(eventLogSrc, "Email Service Started", EventLogEntryType.Information);
m_EmailServiceHost = new ServiceHost(typeof(EmailQueueListener));
m_EmailServiceHost.Open();
}