2008-09-22 9 views
25

की स्थापना के दौरान कस्टम इवेंट लॉग और इवेंट स्रोत बनाने का सबसे विश्वसनीय तरीका क्या है। मुझे अपने .Net Windows सेवा की स्थापना के दौरान ईवेंट स्रोतों को विश्वसनीय रूप से बनाने/निकालने में कठिनाई हो रही है।.NET सेवा

यहाँ मेरी 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 }); 

मुखौटा तरीकों सिर्फ लॉग सेवा के नाम पर लिए सूत्र संदर्भित, आदि

इस कोड को समय के सबसे अधिक काम करता है , लेकिन हाल ही में स्थापित करने के बाद मैंने कस्टम लॉग की बजाय एप्लिकेशन लॉग में अपनी लॉग प्रविष्टियां दिखाना शुरू कर दिया। और निम्न त्रुटियां लॉग में भी हैं:

स्रोत (ऑटोकेकआउट) में इवेंट आईडी (0) के लिए विवरण नहीं मिल सकता है। स्थानीय कंप्यूटर में रिमोट कंप्यूटर से संदेश प्रदर्शित करने के लिए आवश्यक रजिस्ट्री जानकारी या संदेश DLL फ़ाइलें नहीं हो सकती हैं। आप इस विवरण को पुनः प्राप्त करने के लिए/AUXSOURCE = ध्वज का उपयोग करने में सक्षम हो सकते हैं; विवरण के लिए सहायता और सहायता देखें।

किसी कारण से यह अनइंस्टॉल के दौरान स्रोत को ठीक तरह से हटा नहीं रहा है या यह इंस्टॉल के दौरान इसे नहीं बना रहा है।

यहां सर्वोत्तम प्रथाओं के साथ कोई मदद की सराहना की जाती है।

धन्यवाद!

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

stephbu के जवाब के बारे में::

इसके अलावा, यहां मैं कैसे लॉग के लिए अपवाद लिख रहा हूँ का एक नमूना है सिफारिश पथ एक इंस्टॉलर स्क्रिप्ट और InstallUtil, या एक Windows सेटअप दिनचर्या है।

मैं एक सेटअप प्रोजेक्ट का उपयोग कर रहा हूं, जो सेवा की स्थापना करता है और लॉग सेट करता है। चाहे मैं installutil.exe या विंडोज सेटअप प्रोजेक्ट का उपयोग करता हूं, मेरा मानना ​​है कि वे दोनों ऊपर दिखाए गए प्रोजेक्ट इंस्टालर क्लास को कॉल करते हैं।

मैं देखता हूं कि अगर मेरी रीबूटिंग तक लॉग वास्तव में हटाया नहीं जाता है तो मेरी टेस्ट मशीन की स्थिति त्रुटि कैसे उत्पन्न कर सकती है। मैं यह देखने के लिए और अधिक प्रयोग करूंगा कि क्या यह समस्या हल करती है।

संपादित करें: मुझे सेवा की स्थापना के दौरान स्रोत और लॉग नाम पंजीकृत करने के लिए एक निश्चित अग्नि मार्ग में रूचि है। इसलिए यदि सेवा पहले स्थापित की गई थी, तो यह स्रोत को हटा देगी, या बाद के इंस्टॉलेशन के दौरान स्रोत का पुन: उपयोग करेगी।

मुझे अभी तक उस मार्ग को आजमाने के लिए WiX सीखने का अवसर नहीं मिला है। चीजों की

+0

FYI: मैं अभी भी इस समस्या के लिए एक विश्वसनीय समाधान की तलाश में हूं। –

+0

जेसन, इवेंटलॉग स्रोत को हटाने के बजाय यदि यह मौजूद है तो क्यों न केवल इंस्टॉलेशन निष्पादित करता है यदि लॉग स्रोत और लॉग मौजूद नहीं है? मैंने अभी तक यह कोशिश नहीं की है क्योंकि मुझे अपनी खोज के जवाब में आपका प्रश्न मिला है। मेरे पास एक सरल सेवा है जो मैं एक अलग सेवा स्थापित परियोजना के साथ स्थापित कर रहा हूं। बेस्ट, जेसन – Tinidian

उत्तर

5

सबसे अच्छा अनुशंसा विजुअल स्टूडियो में सेटअप प्रोजेक्ट का उपयोग नहीं करना होगा। इसमें बहुत गंभीर सीमाएं हैं। मेरे पास WiX

+0

धन्यवाद अल्बर्ट मैं इसे अभी डाउनलोड कर रहा हूं और कल इसे आज़मा दूंगा! –

7

युगल यहाँ

मक्खी पर इवेंट लॉग और सूत्रों का कहना है बनाना बहुत पर सिकोड़ी है। मुख्य रूप से कार्रवाई करने के लिए आवश्यक अधिकारों के कारण - आप वास्तव में उस शक्ति के साथ अपने अनुप्रयोगों को आशीर्वाद नहीं देना चाहते हैं।

इसके अलावा अगर आप एक ईवेंट लॉग हटा सकते हैं या प्रवेश स्रोत केवल वास्तव नष्ट कर दिया है जब सर्वर रिबूट, आप अजीब राज्यों में प्राप्त कर सकते हैं, इसलिए यदि आप हटा सकते हैं और बॉक्स उछल बिना प्रविष्टियों से तैयार करें।रजिस्ट्री में मेटाडेटा संग्रहीत करने के तरीके के कारण विवादों के नामकरण के बारे में अनचाहे नियमों का भी एक समूह है।

अनुशंसित पथ एक इंस्टॉलर स्क्रिप्ट और installutil, या एक विंडोज सेटअप दिनचर्या है।

+0

रीबूटिंग ने समस्या का समाधान नहीं किया है और मैंने इंस्टाल्यूट और विंडोज सेटअप इंस्टॉलर दोनों का उपयोग किया है, न तो कोई भी लॉग स्रोत बनाता है ... –

+1

इसके अलावा ईवेंट स्रोत फ्लाई पर नहीं बनाया गया है, वे हैं स्थापना के दौरान बनाया जा रहा है, जिसे एक व्यवस्थापक के रूप में निष्पादित किया जाता है। –

+1

यह मक्खी पर नहीं है - यह एक इंस्टॉलर का हिस्सा है, और इंस्टॉलर को व्यवस्थापक के रूप में चलाने के लिए माना जाता है। हालांकि, हटाने के बारे में सहमत नहीं हैं। –

2

के साथ बहुत अच्छे परिणाम हुए हैं, मुझे "अजीब राज्यों" के बारे में stephbu से सहमत होना है कि ईवेंट लॉग इन हो जाता है, मैंने पहले इसमें भाग लिया है। अगर मुझे लगता है, तो आपकी कुछ कठिनाइयों में झूठ बोल रही है।

हालांकि, एप्लिकेशन में ईवेंट लॉगिंग करने का सबसे अच्छा तरीका वास्तव में ट्रेस लिस्टनर के साथ है। आप सेवा के app.config के माध्यम से उन्हें कॉन्फ़िगर कर सकते हैं:

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

वहाँ उस पृष्ठ का वर्णन करता है कि कैसे इवेंटलॉग आप को लिखना चाहते हैं निर्दिष्ट करने के लिए इवेंटलॉग संपत्ति का उपयोग करने के बीच के पास एक खंड है।

आशा है कि मदद करता है।

+2

EventLogTraceListener को अभी भी EventLogSource की आवश्यकता होगी, अगर नहीं, तो यह इसे बनाने का प्रयास करेगा और इसके लिए व्यवस्थापक निजीकरण की आवश्यकता होगी। मेरी सेवा व्यवस्थापक के रूप में नहीं चली जाएगी, उपयोगकर्ता सेवा स्थापित करेगा; यही कारण है कि मैं सेटअप के दौरान EventLog और EventLogSource बनाते हैं। –

0

मुझे कुछ समान अजीब व्यवहार का अनुभव हुआ क्योंकि मैंने एक सेवा स्रोत को उसी सेवा के साथ पंजीकृत करने का प्रयास किया था, जिस सेवा को मैं शुरू कर रहा था।

मुझे पता है कि आपके पास DisplayName भी आपके ईवेंट स्रोत के समान नाम पर सेट है।

सेवा शुरू करने पर, हमने पाया कि विंडोज़ ने अनुप्रयोग लॉग में "सेवा सफलतापूर्वक प्रारंभ की" प्रविष्टि को लॉग इन किया है, जिसे प्रदर्शन नाम के रूप में स्रोत के साथ किया गया है। ऐसा लगता है कि आवेदन लॉग के साथ आवेदन का नाम पंजीकृत करने का प्रभाव पड़ा।

मेरे इवेंट लॉगर क्लास में मैंने बाद में पंजीकरण नाम को एक अलग इवेंट लॉग के साथ स्रोत के रूप में पंजीकृत करने का प्रयास किया, लेकिन जब यह नई इवेंट लॉग प्रविष्टियों को जोड़ने के लिए आया तो वे हमेशा एप्लिकेशन लॉग में जोड़े गए।

मुझे "स्रोत में इवेंट आईडी (0) के लिए विवरण" संदेश कई बार मिला।

आसपास के काम के रूप में मैंने बस डिस्प्लेनाम में थोड़ा अलग नाम के साथ संदेश स्रोत पंजीकृत किया, और यह तब से काम करता है। यदि आप पहले से नहीं हैं तो यह कोशिश करने लायक होगा।

+0

हाँ, मेरे पास वास्तव में दो अलग-अलग नाम हैं, ताकि एप्लिकेशन लॉग में स्टार्ट/स्टॉप लॉग हो, जबकि ऐप ईवेंट सभी कस्टम लॉग में लॉग इन हों। यह एक मुद्दा है जो केवल मेरी विकास मशीन पर उभरा। शायद पंजीकरण/पंजीकरण रद्द करने की वजह से बहुत अधिक ... –

0

मुझे एक ही समस्या है। मेरे मामले में ऐसा लगता है कि विंडोज इंस्टालर इवेंट स्रोत जोड़ रहा है जो कि मेरी सेवा के समान नाम का नाम है और ऐसा लगता है कि यह समस्याएं पैदा करता है। क्या आप विंडोज सेवा और लॉग स्रोत के लिए एक ही नाम का उपयोग कर रहे हैं? इसे बदलने का प्रयास करें ताकि आपके इवेंट लॉग स्रोत को अलग-अलग सेवा के नाम से बुलाया जा सके।

0

समस्या स्थापना से आता है जो डिफ़ॉल्ट रूप से "एप्लिकेशन" EventLog में आपकी सेवाओं के नाम के साथ एक ईवेंट स्रोत पंजीकृत करता है। मैं अभी भी इस बकवास करने से रोकने के लिए एक रास्ता तलाश रहा हूँ। यह वास्तव में अच्छा होगा अगर कोई installutil के व्यवहार को प्रभावित कर सकता है :(

25

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 
}); 
+0

इससे मुझे मदद मिली लेकिन एक बदलाव के साथ .. मुझे केवल इंस्टॉलर को लॉग इनस्टालर संलग्न करना पड़ा अन्यथा मुझे एक त्रुटि मिली है कि सेवा पहले से मौजूद है .. 'यह। इंस्टॉलर। AddRange (नया इंस्टॉलर [] { logInstaller }); ' –

+0

लाइन 'logInstaller.Log =" MyLog "पंक्ति के अलावा;' जिसे मैं निश्चित नहीं था, यह बहुत अच्छा काम करता था! मुझे कोड को 'ProjectInstaller.Designer.cs' में' InitializeComponent() 'में भी रखना था क्योंकि समान कोड पहले से मौजूद था। – SharpC

0

helb के सुझाव मेरे लिए समस्या का समाधान करें:

इस कोड का प्रयास करें। डिफ़ॉल्ट घटना लॉग इंस्टॉलर को मारकर, उसके उदाहरण में इंगित बिंदु पर, इंस्टॉलर को एप्लिकेशन इवेंट लॉग के तहत स्वचालित रूप से मेरी विंडोज सेवा पंजीकृत करने से रोका।

इस निराशाजनक क्विर्क को हल करने का प्रयास करने में बहुत अधिक समय गुम हो गया था। बहुत - बहुत धन्यवाद!

एफडब्ल्यूआईडब्ल्यू, मैं अपने डिजाइनर द्वारा जेनरेट किए गए प्रोजेक्ट इंस्टालर क्लास के भीतर कोड को संशोधित नहीं कर सका, वीएस को मोड के बारे में बताए बिना। मैंने डिजाइनर से उत्पन्न कोड को तोड़ दिया और मैन्युअल रूप से कक्षा में प्रवेश किया।

2

मैंने हेल के सुझाव का भी पालन किया, सिवाय इसके कि मैंने मूल रूप से मानक डिजाइनर जेनरेटेड क्लास (डिफ़ॉल्ट ऑब्जेक्ट्स "सर्विसप्रोसेस इंस्टालर 1" और "सर्विस इंस्टालर 1") का उपयोग किया था। मैंने इसे पोस्ट करने का फैसला किया क्योंकि यह थोड़ा सा सरल संस्करण है; और यह भी क्योंकि मैं वीबी में काम कर रहा हूं और कभी-कभी लोग वीबी-मार्ग देखना पसंद करते हैं।

रूप tartheode कहा, तुम ProjectInstaller.Designer.vb फ़ाइल में डिजाइनर उत्पन्न ProjectInstaller वर्ग संशोधित नहीं करना चाहिए, लेकिन आप ProjectInstaller.vb फ़ाइल में कोड को संशोधित कर सकते हैं। एक सामान्य प्रोजेक्ट इंस्टालर बनाने के बाद (मानक 'एड इंस्टॉलर' तंत्र का उपयोग करके), मैंने जो परिवर्तन किया है वह 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 class description में) कहा गया है: अगर स्रोत संपत्ति एक स्रोत का नाम उस कंप्यूटर पर एक अलग ईवेंट लॉग के लिए पंजीकृत किया गया है से मेल खाता है

स्थापित विधि एक अपवाद फेंकता है। समारोह झूठी रिटर्न

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 

हैं, सेवा स्टार्टअप कोड बस सेवा बंद हो जाता है:

इसलिए, मैं भी मेरी सेवा है, जो जब सेवा शुरू होता है कहा जाता है में इस समारोह की है। यह फ़ंक्शन बहुत अधिक सुनिश्चित करता है कि आपको अंततः सही इवेंट लॉग फ़ाइल से संबंधित सही इवेंट स्रोत नाम मिल जाएगा। आपको मशीन को एक बार रीबूट करना पड़ सकता है; और आपको सेवा को एक से अधिक बार शुरू करने का प्रयास करना पड़ सकता है।

1

मैंने अभी एमएसडीएन मंचों पर इस पर एक समाधान पोस्ट किया है, जिसके लिए मैं एक मानक सेटअप एमएसआई प्रोजेक्ट का उपयोग करके इस पर पहुंचने में कामयाब रहा।

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); 
    } 
} 

कोड केवल करने के लिए आगे थोड़ा संशोधित किया जा सकता है घटना स्रोतों कि नहीं था निकालें: क्या मैंने किया था Preinstall और प्रतिबद्ध घटनाओं जिसका मतलब था मैं सब कुछ बिल्कुल रख सकता है के रूप में यह था करने के लिए कोड जोड़ने के लिए था पहले से मौजूद है या उन्हें बनाते हैं (हालांकि लॉगनाम को इंस्टॉलर के खिलाफ कहीं भी संग्रहीत करने की आवश्यकता होगी) लेकिन चूंकि मेरा एप्लिकेशन कोड वास्तव में ईवेंट स्रोत बनाता है क्योंकि यह चलता है तो मेरे लिए कोई बात नहीं है। यदि पहले से ही घटनाएं हैं तो पहले से ही एक ईवेंट स्रोत होना चाहिए। यह सुनिश्चित करने के लिए कि वे बनाए गए हैं, आप बस सेवा शुरू कर सकते हैं।

0

HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ eventlog \ Application \ MY_CUSTOM_SOURCE_NAME_HERE को खाली रजिस्ट्री कुंजी जोड़ना ठीक काम करता प्रतीत होता है।

0

डिफ़ॉल्ट व्यवहार को बदलने का एक आसान तरीका (यानी, कि प्रोजेक्ट इंस्टॉलर एप्लिकेशन लॉग में आपकी सेवा के नाम के साथ एक ईवेंट लॉग स्रोत बनाता है) को निम्न प्रकार के प्रोजेक्टर इंस्टॉलर के कन्स्ट्रक्टर को आसानी से संशोधित करना है:

[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; 
     } 
    } 
} 
संबंधित मुद्दे