在安装 .Net 服务期间创建自定义事件日志和事件源的最可靠方法是什么
我在安装 .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 来尝试这条路线。
I am having difficulty reliably creating / removing event sources during the installation of my .Net Windows Service.
Here is the code from my ProjectInstaller class:
// 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 });
The facade methods referenced just return the strings for the name of the log, service, etc.
This code works most of the time, but recently after installing I started getting my log entries showing up in the Application Log instead of the custom log. And the following errors are in the log as well:
The description for Event ID ( 0 ) in Source ( AutoCheckout ) cannot be found. The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer. You may be able to use the /AUXSOURCE= flag to retrieve this description; see Help and Support for details.
For some reason it either isn't properly removing the source during the uninstall or it isn't creating it during the install.
Any help with best practices here is appreciated.
Thanks!
In addition, here is a sample of how I am writing exceptions to the log:
// Write to Log
EventLog.WriteEntry(Facade.GetEventLogSource(), errorDetails, EventLogEntryType.Error, 99);
Regarding stephbu's answer: The recommended path is an installer script and installutil, or a Windows Setup routine.
I am using a Setup Project, which performs the installation of the service and sets up the log. Whether I use the installutil.exe or the windows setup project I believe they both call the same ProjectInstaller class I show above.
I see how the state of my test machine could be causing the error if the log isn't truly removed until rebooting. I will experiment more to see if that solves the issue.
Edit:
I'm interested in a sure fire way to register the source and the log name during the installation of the service. So if the service had previously been installed, it would remove the source, or reuse the source during subsequent installations.
I haven't yet had an opportunity to learn WiX to try that route.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
这里有几件事
是非常不赞成动态创建事件日志和源的。 主要是因为执行该操作所需的权限 - 您并不真的希望为您的应用程序提供该权限。
此外,如果您删除事件日志或源,则只有在服务器重新启动时才会真正删除该条目,因此,如果您删除并重新创建条目而不弹跳框,您可能会进入奇怪的状态。 由于元数据在注册表中的存储方式,还有一些关于命名冲突的不成文规则。
推荐的路径是安装程序脚本和 installutil,或 Windows 安装例程。
Couple of things here
Creating Event Logs and Sources on the fly is pretty frowned upon. primarily because of the rights required to perform the action - you don't really want to bless your applications with that power.
Moreover if you delete an event log or source the entry is only truely deleted when the server reboots, so you can get into wierd states if you delete and recreate entries without bouncing the box. There are also a bunch of unwritten rules about naming conflicts due to the way the metadata is stored in the registry.
The recommended path is an installer script and installutil, or a Windows Setup routine.
我必须同意stephbu关于事件日志进入的“奇怪状态”的观点,我以前遇到过这种情况。 如果我猜的话,你的一些困难就在那里。
然而,据我所知,在应用程序中进行事件日志记录的最佳方法实际上是使用 TraceListener。 您可以通过服务的 app.config 来配置它们:
http:// /msdn.microsoft.com/en-us/library/system.diagnostics.eventlogtracelistener.aspx
该页面中间附近有一个部分,描述如何使用 EventLog 属性来指定您要写入的 EventLog到。
希望有帮助。
I have to agree with stephbu about the "weird states" that the event log gets into, I've run into that before. If I were to guess, some of your difficulties lie there.
However, the best way that I know of to do event logging in the application is actually with a TraceListener. You can configure them via the service's app.config:
http://msdn.microsoft.com/en-us/library/system.diagnostics.eventlogtracelistener.aspx
There is a section near the middle of that page that describes how to use the EventLog property to specify the EventLog you wish to write to.
Hope that helps.
最好的建议是不要使用 Visual Studio 中的安装项目。 它有非常严格的限制。
我使用 WiX 取得了非常好的结果
The best recommendation would be to not use the Setup Project in Visual Studio. It has very severe limitations.
I had very good results with WiX
我也遵循了 helb 的建议,只是我基本上使用了标准设计器生成的类(默认对象“ServiceProcessInstaller1”和“ServiceInstaller1”)。 我决定发布这个,因为它是一个稍微简单的版本; 也因为我在 VB 中工作,人们有时喜欢看到 VB 的方式。
正如 tartheode 所说,您不应该修改 ProjectInstaller.Designer.vb 文件中设计器生成的 ProjectInstaller 类,但您可以修改代码在 ProjectInstaller.vb 文件中。 创建普通的 ProjectInstaller(使用标准的“添加安装程序”机制)后,我所做的唯一更改是在 ProjectInstaller 类的 New() 中。 在正常的“InitializeComponent()”调用之后,我插入了以下代码:
这按预期工作,因为安装程序没有在应用程序日志中创建事件源,而是在新的自定义日志中创建文件。
然而,我已经搞砸了,以至于我在一台服务器上弄得有点乱。 自定义日志的问题是,如果存在与错误日志文件关联的事件源名称(例如“应用程序”日志而不是新的自定义日志),则必须首先删除源名称; 然后机器重新启动; 然后可以创建与正确日志关联的源。 Microsoft 帮助明确指出(在 EventLogInstaller 类说明):
因此,我的服务中也有这个函数,在服务启动时调用该函数:
如果该函数返回 False,则服务启动代码只是停止该服务。 此功能几乎可以确保您最终获得与正确事件日志文件关联的正确事件源名称。 您可能需要重新启动一次机器; 并且您可能需要多次尝试启动该服务。
I also followed helb's suggestion, except that I basically used the standard designer generated classes (the default objects "ServiceProcessInstaller1" and "ServiceInstaller1"). I decided to post this since it is a slightly simpler version; and also because I am working in VB and people sometimes like to see the VB-way.
As tartheode said, you should not modify the designer-generated ProjectInstaller class in the ProjectInstaller.Designer.vb file, but you can modify the code in the ProjectInstaller.vb file. After creating a normal ProjectInstaller (using the standard 'Add Installer' mechanism), the only change I made was in the New() of the ProjectInstaller class. After the normal "InitializeComponent()" call, I inserted this code:
This worked as expected, in that the installer did not create the Event Source in the Application log, but rather created in the new custom log file.
However, I had screwed around enough that I had a bit of a mess on one server. The problem with the custom logs is that if the event source name exists associated to the wrong log file (e.g. the 'Application' log instead of your new custom log), then the source name must first be deleted; then the machine rebooted; then the source can be created with association to the correct log. The Microsoft Help clearly states (in the EventLogInstaller class description):
Therefore, I also have this function in my service, which is called when the service starts:
If the function returns False, the service startup code simply stops the service. This function pretty much ensures that you will eventually get the correct Event Source name associated to the correct Event Log file. You may have to reboot the machine once; and you may have to try starting the service more than once.
我也有同样的问题。 就我而言,Windows 安装程序似乎自动添加与我的服务同名的事件源,这似乎会导致问题。 Windows 服务和日志源是否使用相同的名称? 尝试更改它,以便您的事件日志源的调用方式与服务名称不同。
I am having the same problems. In my case it seems that Windows installer is adding the event source which is of the same name as my service automatically and this seems to cause problems. Are you using the same name for the windows service and for the log source? Try changing it so that your event log source is called differently then the name of the service.
我刚刚在 MSDN 论坛上发布了一个解决方案,我设法使用标准设置 MSI 项目来解决这个问题。 我所做的是将代码添加到 PreInstall 和 Commied 事件中,这意味着我可以将其他所有内容保持原样:
可以进一步修改代码以仅删除尚不存在的事件源或创建它们(尽管日志名需要存储在安装程序的某个地方),但由于我的应用程序代码实际上在运行时创建了事件源,所以对我来说没有意义。 如果已经有事件,那么应该已经有事件源。 为了确保它们被创建,您可以自动启动该服务。
I just posted a solution to this over on MSDN forums which was to that I managed to get around this using a standard setup MSI project. What I did was to add code to the PreInstall and Committed events which meant I could keep everything else exactly as it was:
The code could be modified a bit further to only remove the event sources that didn't already exist or create them (though the logname would need to be stored somewhere against the installer) but since my application code actually creates the event sources as it runs then there's no point for me. If there are already events then there should already be an event source. To ensure that they are created, you can just automatically start the service.
我经历了一些类似的奇怪行为,因为我尝试注册与我正在启动的服务同名的事件源。
我注意到您还将 DisplayName 设置为与事件源相同的名称。
启动服务时,我们发现 Windows 在应用程序日志中记录了“服务已成功启动”条目,源为 DisplayName。 这似乎具有在应用程序日志中注册应用程序名称的效果。
在我的事件记录器类中,我后来尝试将应用程序名称注册为具有不同事件日志的源,但是当涉及添加新的事件日志条目时,它们总是被添加到应用程序日志中。
我还多次收到“源中事件 ID (0) 的描述”消息。
作为解决方法,我只是使用与 DisplayName 稍有不同的名称来注册消息源,从那时起它就一直有效。 如果您还没有尝试的话,那么值得尝试一下。
I experienced some similar weird behaviour because I tried to register an event source with the same name as the service I was starting.
I notice that you also have the DisplayName set to the same name as your event Source.
On starting the service up, we found that Windows logged a "Service started successfully" entry in the Application log, with source as the DisplayName. This seemed to have the effect of registering Application Name with the application log.
In my event logger class I later tried to register Application Name as the source with a different event log, but when it came to adding new event log entries they always got added to the Application log.
I also got the "The description for Event ID ( 0 ) in Source" message several times.
As a work around I simply registered the message source with a slightly different name to the DisplayName, and it's worked ever since. It would be worth trying this if you haven't already.
问题来自 installutil,它默认在“应用程序”事件日志中使用您的服务名称注册事件源。 我仍在寻找一种方法来阻止它做这种垃圾事。 如果能够影响 installutil 的行为那就太好了:(
The problem comes from installutil which by default registers an event source with your services name in the "Application" EventLog. I'm still looking for a way to stop it doing this crap. It would be really nice if one could influence the behaviour of installutil :(
按照 helb 的建议解决了我的问题。 在示例中所示的位置终止默认事件日志安装程序会阻止安装程序在应用程序事件日志下自动注册我的 Windows 服务。
为了解决这个令人沮丧的怪癖,我们浪费了太多的时间。 太感谢了!
FWIW,我无法修改设计器生成的 ProjectInstaller 类中的代码而不导致 VS 对 mods 吹毛求疵。 我放弃了设计者生成的代码并手动输入类。
Following helb's suggestion resolved the problem for me. Killing the default event log installer, at the point indicated in his example, prevented the installer from automatically registering my Windows Service under the Application Event log.
Far too much time was lost attempting to resolve this frustrating quirk. Thanks a million!
FWIW, I could not modify the code within my designer-generated ProjectInstaller class without causing VS to carp about the mods. I scrapped the designer-generated code and manually entered the class.
将空注册表项添加到 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\Application\MY_CUSTOM_SOURCE_NAME_HERE 似乎工作正常。
Adding an empty registry key to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\Application\MY_CUSTOM_SOURCE_NAME_HERE seems to work fine.
更改默认行为(即项目安装程序在应用程序日志中使用您的服务名称创建事件日志源)的一种简单方法是轻松修改项目安装程序的构造函数,如下所示:
An easy way to change the default behavior (that is, that the project installer creates an event log source with the name of your service in the application log) is to easily modify the constructor of the project installer as following:
ServiceInstaller
类自动创建一个EventLogInstaller
并将其放入自己的 Installers 集合中。试试这个代码:
The
ServiceInstaller
class automatically creates anEventLogInstaller
and puts it inside its own Installers collection.Try this code: