什么是创建一个安装服务的.Net的过程中自定义事件日志和事件源的最可靠的方法(What is the

2019-07-30 12:14发布

我有困难可靠创建/安装我的.Net Windows服务的过程中删除事件源。

下面是我的ProjectInstaller类的代码:

// Create Process Installer
ServiceProcessInstaller spi = new ServiceProcessInstaller();
spi.Account = ServiceAccount.LocalSystem;

// Create Service
ServiceInstaller si = new ServiceInstaller();
si.ServiceName = Facade.GetServiceName();
si.Description = "Processes ...";
si.DisplayName = "Auto Checkout";
si.StartType = ServiceStartMode.Automatic;

// Remove Event Source if already there
if (EventLog.SourceExists("AutoCheckout"))
    EventLog.DeleteEventSource("AutoCheckout");

// Create Event Source and Event Log     
EventLogInstaller log = new EventLogInstaller();
log.Source = "AutoCheckout";
log.Log = "AutoCheckoutLog";

Installers.AddRange(new Installer[] { spi, si, log });

门面引用的方法只返回字符串的日志,服务等的名称

此代码工作的大部分时间,但最近安装后,我开始让我的日志条目显示在应用程序日志,而不是自定义日志了。 而下面的错误日志中还有:

在源(AutoCheckout)的事件ID(0)的描述不能被发现。 本地计算机可能没有必要的注册信息或消息DLL文件来从远程计算机显示消息。 您可以使用/ AUXSOURCE =标识来检索词描述; 详情请参阅帮助和支持。

出于某种原因,要么没有正确卸载过程中删除源,或者在安装过程中也没有创造它。

在这里的最佳实践任何帮助表示赞赏。

谢谢!

此外,这里是我如何写例外日志的一个示例:

// Write to Log
EventLog.WriteEntry(Facade.GetEventLogSource(), errorDetails, EventLogEntryType.Error, 99);

关于stephbu的回答是:推荐路径是安装脚本和installutil,或Windows安装程序例程。

我使用的是安装项目,该项目执行服务的安装和设置日志。 无论我用installutil.exe或Windows安装项目,我相信他们都呼吁同ProjectInstaller类我上面显示。

我怎么看,如果日志没有真正重启之前删除我的测试机的状态可能会导致错误。 我将更多的实验,看看是否能解决这个问题。

编辑:我感兴趣的肯定火的方式注册安装在服务期间源和日志的名称。 因此,如果以前曾安装服务时,它会删除源,或者重复使用以后的安装源。

我尚未有机会了解WiX的尝试这条路线。

Answer 1:

最好的建议是不要使用Visual Studio中的安装项目。 它有非常严格的限制。 我有很好的效果与维克斯



Answer 2:

ServiceInstaller类自动创建一个EventLogInstaller并把它自己的安装程序集合中。

试试这个代码:

ServiceProcessInstaller serviceProcessInstaller = new ServiceProcessInstaller();
serviceProcessInstaller.Password = null;
serviceProcessInstaller.Username = null;
serviceProcessInstaller.Account = ServiceAccount.LocalSystem;

// serviceInstaller
ServiceInstaller serviceInstaller = new ServiceInstaller();
serviceInstaller.ServiceName = "MyService";
serviceInstaller.DisplayName = "My Service";
serviceInstaller.StartType = ServiceStartMode.Automatic;
serviceInstaller.Description = "My Service Description";
// kill the default event log installer
serviceInstaller.Installers.Clear(); 

// Create Event Source and Event Log     
EventLogInstaller logInstaller = new EventLogInstaller();
logInstaller.Source = "MyService"; // use same as ServiceName
logInstaller.Log = "MyLog";

// Add all installers
this.Installers.AddRange(new Installer[] {
   serviceProcessInstaller, serviceInstaller, logInstaller
});


Answer 3:

事情夫妇在这里

在飞行中创建事件日志和资源时是相当皱起眉头。 主要是因为要执行的操作所需的权利 - 你真的不希望与力量祝福你的应用程序。

此外,如果你删除事件日志或源进入服务器重新启动时只忠实地删除了,这样你就可以进入状态怪异,如果你删除并重新创建条目没有弹跳框。 另外还有约命名冲突,由于元数据存储在注册表的方式一堆不成文的规则。

建议的路径是安装脚本和installutil,或Windows安装程序例程。



Answer 4:

我有一个关于“怪异国家”的事件日志进入stephbu同意,我以前碰到这一点。 如果我猜,你的一些困难,躺在那里。

不过,据我所知,做事件记录在应用程序的最佳途径实际上是一个TraceListener的。 您可以通过服务的app.config配置它们:

http://msdn.microsoft.com/en-us/library/system.diagnostics.eventlogtracelistener.aspx

还有就是介绍如何使用事件日志属性来指定要写入事件日志该页面中间附近的一个部分。

希望帮助。



Answer 5:

我也跟着HELB的建议,但我基本上使用的标准设计器生成的类(默认对象“ServiceProcessInstaller1”和“ServiceInstaller1”)。 我决定发布此,因为它是一个稍微简单的版本; 也因为我在VB中工作,有时人们喜欢看到VB-方式。

作为tartheode说,你不应该修改在ProjectInstaller.Designer.vb文件中的设计器生成的ProjectInstaller类,但你可以修改ProjectInstaller.vb文件中的代码。 创建一个正常的ProjectInstaller(使用标准的“添加安装程序”机制)之后,我做出的唯一改变是在ProjectInstaller类的新的()。 经过正常“的InitializeComponent()”打电话,我插入的代码:

  ' remove the default event log installer 
  Me.ServiceInstaller1.Installers.Clear()

  ' Create an EventLogInstaller, and set the Event Source and Event Log      
  Dim logInstaller As New EventLogInstaller
  logInstaller.Source = "MyServiceName"
  logInstaller.Log = "MyCustomEventLogName"

  ' Add the event log installer
  Me.ServiceInstaller1.Installers.Add(logInstaller)

这种预期一样,则在安装程序没有在应用程序日志中创建事件源,但在新的自定义日志文件而创建的。

不过,我已经够左右拧,我有一个有点乱的一台服务器上。 与自定义日志的问题是,如果事件源名存在关联到错误日志文件(例如,“应用程序”日志,而不是新的自定义日志),那么源名称必须先删除; 然后机器重新启动; 那么源可以与关联正确的日志中创建。 微软帮助明确指出(在EventLogInstaller类说明 ):

如果源属性相匹配是一个注册为计算机上的不同的事件日志源名称的安装方法抛出异常。

因此,我也有我的服务,这就是所谓此功能在服务启动时:

   Private Function EventLogSourceNameExists() As Boolean
      'ensures that the EventSource name exists, and that it is associated to the correct Log 

      Dim EventLog_SourceName As String = Utility.RetrieveAppSetting("EventLog_SourceName")
      Dim EventLog_LogName As String = Utility.RetrieveAppSetting("EventLog_LogName")

      Dim SourceExists As Boolean = EventLog.SourceExists(EventLog_SourceName)
      If Not SourceExists Then
         ' Create the source, if it does not already exist.
         ' An event log source should not be created and immediately used.
         ' There is a latency time to enable the source, it should be created
         ' prior to executing the application that uses the source.
         'So pass back a False to cause the service to terminate.  User will have 
         'to re-start the application to make it work.  This ought to happen only once on the 
         'machine on which the service is newly installed

         EventLog.CreateEventSource(EventLog_SourceName, EventLog_LogName)  'create as a source for the SMRT event log
      Else
         'make sure the source is associated with the log file that we want
         Dim el As New EventLog
         el.Source = EventLog_SourceName
         If el.Log <> EventLog_LogName Then
            el.WriteEntry(String.Format("About to delete this source '{0}' from this log '{1}'.  You may have to kill the service using Task Manageer.  Then please reboot the computer; then restart the service two times more to ensure that this event source is created in the log {2}.", _
            EventLog_SourceName, el.Log, EventLog_LogName))

            EventLog.DeleteEventSource(EventLog_SourceName)
            SourceExists = False  'force a close of service
         End If
      End If
      Return SourceExists
   End Function

如果函数返回False,该服务启动代码简单地停止服务。 该功能几乎可确保您最终会得到相关的正确的事件日志文件正确的事件源名称。 您可能需要一次重新启动机器; 你可能必须尝试启动服务不止一次。



Answer 6:

我有同样的问题。 在我而言似乎是Windows安装程序添加事件源自动同名作为我的服务,这似乎会导致问题。 您是否使用相同的名称为Windows服务和日志源? 试着改变它,这样你的事件日志源称为不同那么服务的名称。



Answer 7:

我刚刚张贴在MSDN论坛这是我管理使用标准安装MSI项目来解决这个问题的解决方案,以这种过度。 我所做的就是将代码添加到这意味着我能保持一切,正是因为它是预安装,并承诺事项:

SortedList<string, string> eventSources = new SortedList<string, string>();
private void serviceProcessInstaller_BeforeInstall(object sender, InstallEventArgs e)
{
  RemoveServiceEventLogs();
}

private void RemoveServiceEventLogs()
{
  foreach (Installer installer in this.Installers)
    if (installer is ServiceInstaller)
    {
      ServiceInstaller serviceInstaller = installer as ServiceInstaller;
      if (EventLog.SourceExists(serviceInstaller.ServiceName))
      {
        eventSources.Add(serviceInstaller.ServiceName, EventLog.LogNameFromSourceName(serviceInstaller.ServiceName, Environment.MachineName));
        EventLog.DeleteEventSource(serviceInstaller.ServiceName);
      }
    }
}

private void serviceProcessInstaller_Committed(object sender, InstallEventArgs e)
{
  RemoveServiceEventLogs();
  foreach (KeyValuePair<string, string> eventSource in eventSources)
  {
    if (EventLog.SourceExists(eventSource.Key))
      EventLog.DeleteEventSource(eventSource.Key);

    EventLog.CreateEventSource(eventSource.Key, eventSource.Value);
  }
}

该代码可以被进一步修改了一下,只除去未存在或创建它们(虽然LOGNAME将需要对安装程序存储的地方),但因为我的应用程序代码实际创建事件源,因为它运行的事件源那么就没有一点对我来说。 如果已经有事件,则应该已经有一个事件源。 为了确保创建它们,你可以自动启动该服务。



Answer 8:

我经历了一些类似的怪异的行为,因为我想注册为服务,我开始一个同名的事件源。

我注意到,你也有显示名称设置为同一名称的事件源。

在启动服务时,我们发现,登录Windows“服务成功启动”应用程序日志条目,与源作为显示名称。 这似乎与应用程序日志登记申请名称的效果。

在我的事件记录器类后来我试图注册申请名称为具有不同的事件日志源,但是当它来增加新的事件日志条目,他们总是得到添加到应用程序日志。

我也得到了消息多次“为源事件ID(0)的说明”。

由于周围的工作,我只是注册的消息源有一个稍微不同的名称,显示名称,并且因为它没有计算过。 这将是值得尝试这个,如果你还没有准备好。



Answer 9:

问题来自installutil它默认登记在“应用程序”事件日志与您的服务名称的事件源。 我仍然在寻找一种方式来阻止它这样做的废话。 这将是非常好的,如果能影响installutil行为:(



Answer 10:

HELB的建议解决了这个问题对我来说。 杀死默认的事件日志安装程序,在他的榜样指示的点,从应用程序事件日志下自动登记在我的Windows服务阻止安装程序。

太多时间失去了试图解决这个令人沮丧的怪癖。 太感谢了!

FWIW,我不能改变我的设计器生成的ProjectInstaller类中的代码,而不会造成VS鲤鱼约MODS的。 我报废设计器生成的代码和手动输入的类。



Answer 11:

添加\ CURRENTCONTROLSET \服务一个空的注册表项以HKEY_LOCAL_MACHINE \ SYSTEM \事件日志\应用程序\ MY_CUSTOM_SOURCE_NAME_HERE似乎很好地工作。



Answer 12:

一个简单的方法来改变默认的行为(即该项目的安装程序创建与应用程序日志服务的名称的事件日志源)可以轻松地修改该项目的安装程序的构造函数如下:

[RunInstaller( true )]
public partial class ProjectInstaller : System.Configuration.Install.Installer
{
    public ProjectInstaller()
    {
        InitializeComponent();

        //Skip through all ServiceInstallers.
        foreach( ServiceInstaller ThisInstaller in Installers.OfType<ServiceInstaller>() )
        {
            //Find the first default EventLogInstaller.
            EventLogInstaller ThisLogInstaller = ThisInstaller.Installers.OfType<EventLogInstaller>().FirstOrDefault();
            if( ThisLogInstaller == null )
                continue;

            //Modify the used log from "Application" to the same name as the source name. This creates a source in the "Applications and Services log" which separates your service logs from the default application log.
            ThisLogInstaller.Log = ThisLogInstaller.Source;
        }
    }
}


文章来源: What is the most reliable way to create a custom event log and event source during the installation of a .Net Service