Windows Uygulama Olay Günlüğüne Yaz


166

Bu olay günlüğüne yazmanın bir yolu var mı:

resim açıklamasını buraya girin

Ya da en azından olay kaynağı kaydetmem gerekmeyen başka bir Windows varsayılan günlüğü mü?




1
"Kaynakla ilk girişi yazmadan önce olay kaynağını oluşturmanız ve yapılandırmanız gerekir."
Jerther

Yapamýyor gibiyim. Peki, uygulamanın windows günlüklerine yazamadığını uyarmak için iyi bir geri dönüş yöntemi var mı? Düz bir dosya iyi görünüyor ama nerede? Uygulama klasörü hala bazı izinlere ihtiyaç duyar. Uygulamam bir windows hizmetidir.
Jerther

3
Uygulamanız bir Windows Hizmeti ise, sizin için otomatik olarak bir olay kaynağı oluşturulur. Erişebilirsiniz ServiceBase.EventLog. Kaynağın varsayılan adı HizmetAdı'dır.
Mike Zboray

Yanıtlar:


237

Evet, aradığınız olay günlüğüne yazmanın bir yolu var. Yeni bir kaynak oluşturmanıza gerek yoktur, yalnızca EventLog adıyla aynı ada sahip olan varolan kaynağı kullanın ve ayrıca bazı durumlarda olay günlüğü Uygulaması gibi yönetimsel ayrıcalıklar olmadan erişilebilir.

* Doğrudan erişemediğiniz diğer durumlar, örneğin yalnızca işletim sistemi tarafından erişilen Güvenlik Olayı Log'udur.

Olay günlüğü uygulamasına doğrudan yazmak için bu kodu kullandım:

using (EventLog eventLog = new EventLog("Application")) 
{
    eventLog.Source = "Application"; 
    eventLog.WriteEntry("Log message example", EventLogEntryType.Information, 101, 1); 
}

Gördüğünüz gibi, EventLog kaynağı EventLog adıyla aynıdır. Bunun nedeni Event Sources @ Windows Dev Center'da bulunabilir (Kaynak adını ifade eden kısmı kalınlaştırdım):

Eventlog anahtarındaki her günlük, olay kaynakları adı verilen alt anahtarları içerir. Olay kaynağı, olayı günlüğe kaydeden yazılımın adıdır. Genellikle uygulamanın adı veya uygulama büyükse uygulamanın bir alt bileşeninin adıdır. Kayıt defterine en fazla 16.384 olay kaynağı ekleyebilirsiniz.


1
Ancak alıntı yaptığınız metin, olay kaynağını Olay günlüğü anahtarı altında kaydetmeniz gerektiğini belirtir.
Raymond Chen

1
Demek istediğim, Olay Günlüğü adı genellikle uygulamanın aynı adıdır, bu yüzden yeni bir kaynak oluşturmadan doğrudan bir Eventlog girişine EventLog kaydedebilirsiniz. Alıntılanan metni daha fazla okuma için cesaretlendirdim.
cloud120

3
Teknik olarak kayıt defteri anahtarı yaratma eylemi olduğu olay kaynağını kayıt. Uygulama adından sonra anahtarı adlandırmak, çakışmalardan kaçınmak için bir kuraldır. Cevabınız temel olarak bu cevapla aynı .
Raymond Chen

7
Zaman ayırdığınız için teşekkürler Raymond Chen, başkalarına yardımcı olabilecek bir şeyi çözmek veya önermek için buradayız. Bu durumda, şu soruyu yanıtladığımı düşünüyorum: "Bu olay günlüğüne yazmanın bir yolu var mı? -> Yanıtladım: Evet öyle ve sizinle paylaştım. Söylediğiniz gibi çatışmalara neden olabilmesine rağmen, bir yolu var.
cloud120

7
"Bir olay kaynağını kaydetmeden bunu yapmanın bir yolu var mı?" ve cevabınız "Bir olay kaynağını kaydetmek için bu kayıt defteri anahtarını oluşturun" diyor. Aynı zamanda mevcut bir cevapla aynıdır.
Raymond Chen

14

Üzerinde açıklandığı gibi, EventLog sınıfını kullanarak yapabilirsiniz Nasıl yapılır: uygulama olay günlüğüne (Visual C #) için Write :

var appLog = new EventLog("Application");
appLog.Source = "MySource";
appLog.WriteEntry("Test log message");

Ancak, yönetici ayrıcalıklarını kullanarak bu kaynağı "MySource" olarak yapılandırmanız gerekir :

Olay günlüğüne olay yazmak için WriteEvent ve WriteEntry kullanın. Olay yazmak için bir olay kaynağı belirtmelisiniz; kaynakla ilk girişi yazmadan önce olay kaynağını oluşturmanız ve yapılandırmanız gerekir.


2
Sahip olduğum sorun bu: Kaynağı oluşturamıyorum çünkü bu ayrıcalıklara sahip değilim, ama yine de bir yerde bu sorunu
kaydetmem

2
Ardından bir yükleyici ( stackoverflow.com/questions/1484605/… ) kullanın veya dosyaya oturum açın.
CodeCaster

1
Teşekkür ederim. Bu beni diğer SO sorusuna
götürüyor

@CodeCaster - Bu günlüklere nereden erişebiliriz? Yani depolandığı yer?
Arvind Chourasiya

1
@Arvind bu sorunun cevabımla bir ilgisi yok ve tamamen yeni bir soru.
CodeCaster

11

MSDN'de belirtildiği gibi (örn. Https://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog(v=vs.110).aspx ), mevcut olmayan bir kaynağı kontrol etmek ve bir kaynak oluşturmak için yönetici gerekir ayrıcalık.

Ancak "Uygulama" kaynağını onsuz kullanmak mümkündür . Windows 2012 Server r2 altındaki testimde, ancak "Uygulama" kaynağını kullanarak aşağıdaki günlük girişini alıyorum:

Kaynak Uygulamadan olay kimliği xxxx için açıklama bulunamadı. Bu olayı başlatan bileşen yerel bilgisayarınıza yüklenmemiş veya yükleme bozulmuş. Bileşeni yerel bilgisayara yükleyebilir veya onarabilirsiniz. Olay başka bir bilgisayardan kaynaklandıysa, görüntüleme bilgilerinin olayla birlikte kaydedilmesi gerekir. Olayla birlikte şu bilgiler eklenmiştir: {olay girdi iletim} ileti kaynağı var, ancak ileti dizede / ileti tablosunda bulunamadı

Kaynağı oluşturmak için aşağıdaki yöntemi tanımladım:

    private string CreateEventSource(string currentAppName)
    {
        string eventSource = currentAppName;
        bool sourceExists;
        try
        {
            // searching the source throws a security exception ONLY if not exists!
            sourceExists = EventLog.SourceExists(eventSource);
            if (!sourceExists)
            {   // no exception until yet means the user as admin privilege
                EventLog.CreateEventSource(eventSource, "Application");
            }
        }
        catch (SecurityException)
        {
            eventSource = "Application";
        }

        return eventSource;
    }

CurrentAppName = AppDomain.CurrentDomain.FriendlyName ile çağırıyorum

Bu try / catch yerine EventLogPermission sınıfını kullanmak mümkün olabilir, ancak catch'i önleyebileceğimizden emin değiliz.

Kaynağı harici olarak, örneğin yükseltilmiş Powershell'de oluşturmak da mümkündür:

New-EventLog -LogName Application -Source MyApp

Daha sonra, yukarıdaki yöntemde 'Uygulamam' kullanılması istisna oluşturmaz ve EventLog bu kaynakla oluşturulabilir.


10

Bu kullandığım logger sınıfı. Özel Log () yönteminde, EventLog.WriteEntry()olay günlüğüne gerçekte böyle yazılır. Bu kodun hepsini buraya dahil ediyorum çünkü kullanışlı. Günlüğe ek olarak, bu sınıf ayrıca iletinin olay günlüğüne yazmak için çok uzun olmadığından da emin olur (iletiyi keser). Mesaj çok uzun olsaydı, bir istisna alırsınız. Arayan ayrıca kaynağı belirtebilir. Arayan bunu yapmazsa, bu sınıf kaynağı alır. Umarım yardımcı olur.

Bu arada, web'den bir ObjectDumper alabilirsiniz. Bunların hepsini buraya göndermek istemedim. Buradan benimkini aldım:C:\Program Files (x86)\Microsoft Visual Studio 10.0\Samples\1033\CSharpSamples.zip\LinqSamples\ObjectDumper

using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Reflection;
using Xanico.Core.Utilities;

namespace Xanico.Core
{
    /// <summary>
    /// Logging operations
    /// </summary>
    public static class Logger
    {
        // Note: The actual limit is higher than this, but different Microsoft operating systems actually have
        //       different limits. So just use 30,000 to be safe.
        private const int MaxEventLogEntryLength = 30000;

        /// <summary>
        /// Gets or sets the source/caller. When logging, this logger class will attempt to get the
        /// name of the executing/entry assembly and use that as the source when writing to a log.
        /// In some cases, this class can't get the name of the executing assembly. This only seems
        /// to happen though when the caller is in a separate domain created by its caller. So,
        /// unless you're in that situation, there is no reason to set this. However, if there is
        /// any reason that the source isn't being correctly logged, just set it here when your
        /// process starts.
        /// </summary>
        public static string Source { get; set; }

        /// <summary>
        /// Logs the message, but only if debug logging is true.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="debugLoggingEnabled">if set to <c>true</c> [debug logging enabled].</param>
        /// <param name="source">The name of the app/process calling the logging method. If not provided,
        /// an attempt will be made to get the name of the calling process.</param>
        public static void LogDebug(string message, bool debugLoggingEnabled, string source = "")
        {
            if (debugLoggingEnabled == false) { return; }

            Log(message, EventLogEntryType.Information, source);
        }

        /// <summary>
        /// Logs the information.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="source">The name of the app/process calling the logging method. If not provided,
        /// an attempt will be made to get the name of the calling process.</param>
        public static void LogInformation(string message, string source = "")
        {
            Log(message, EventLogEntryType.Information, source);
        }

        /// <summary>
        /// Logs the warning.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="source">The name of the app/process calling the logging method. If not provided,
        /// an attempt will be made to get the name of the calling process.</param>
        public static void LogWarning(string message, string source = "")
        {
            Log(message, EventLogEntryType.Warning, source);
        }

        /// <summary>
        /// Logs the exception.
        /// </summary>
        /// <param name="ex">The ex.</param>
        /// <param name="source">The name of the app/process calling the logging method. If not provided,
        /// an attempt will be made to get the name of the calling process.</param>
        public static void LogException(Exception ex, string source = "")
        {
            if (ex == null) { throw new ArgumentNullException("ex"); }

            if (Environment.UserInteractive)
            {
                Console.WriteLine(ex.ToString());
            }

            Log(ex.ToString(), EventLogEntryType.Error, source);
        }

        /// <summary>
        /// Recursively gets the properties and values of an object and dumps that to the log.
        /// </summary>
        /// <param name="theObject">The object to log</param>
        [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Xanico.Core.Logger.Log(System.String,System.Diagnostics.EventLogEntryType,System.String)")]
        [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "object")]
        public static void LogObjectDump(object theObject, string objectName, string source = "")
        {
            const int objectDepth = 5;
            string objectDump = ObjectDumper.GetObjectDump(theObject, objectDepth);

            string prefix = string.Format(CultureInfo.CurrentCulture,
                                          "{0} object dump:{1}",
                                          objectName,
                                          Environment.NewLine);

            Log(prefix + objectDump, EventLogEntryType.Warning, source);
        }

        private static void Log(string message, EventLogEntryType entryType, string source)
        {
            // Note: I got an error that the security log was inaccessible. To get around it, I ran the app as administrator
            //       just once, then I could run it from within VS.

            if (string.IsNullOrWhiteSpace(source))
            {
                source = GetSource();
            }

            string possiblyTruncatedMessage = EnsureLogMessageLimit(message);
            EventLog.WriteEntry(source, possiblyTruncatedMessage, entryType);

            // If we're running a console app, also write the message to the console window.
            if (Environment.UserInteractive)
            {
                Console.WriteLine(message);
            }
        }

        private static string GetSource()
        {
            // If the caller has explicitly set a source value, just use it.
            if (!string.IsNullOrWhiteSpace(Source)) { return Source; }

            try
            {
                var assembly = Assembly.GetEntryAssembly();

                // GetEntryAssembly() can return null when called in the context of a unit test project.
                // That can also happen when called from an app hosted in IIS, or even a windows service.

                if (assembly == null)
                {
                    assembly = Assembly.GetExecutingAssembly();
                }


                if (assembly == null)
                {
                    // From http://stackoverflow.com/a/14165787/279516:
                    assembly = new StackTrace().GetFrames().Last().GetMethod().Module.Assembly;
                }

                if (assembly == null) { return "Unknown"; }

                return assembly.GetName().Name;
            }
            catch
            {
                return "Unknown";
            }
        }

        // Ensures that the log message entry text length does not exceed the event log viewer maximum length of 32766 characters.
        private static string EnsureLogMessageLimit(string logMessage)
        {
            if (logMessage.Length > MaxEventLogEntryLength)
            {
                string truncateWarningText = string.Format(CultureInfo.CurrentCulture, "... | Log Message Truncated [ Limit: {0} ]", MaxEventLogEntryLength);

                // Set the message to the max minus enough room to add the truncate warning.
                logMessage = logMessage.Substring(0, MaxEventLogEntryLength - truncateWarningText.Length);

                logMessage = string.Format(CultureInfo.CurrentCulture, "{0}{1}", logMessage, truncateWarningText);
            }

            return logMessage;
        }
    }
}

3
Ve bu kod bunu gösteriyor. Bunu onunla paylaşmanın zararı nedir? OP ve diğerlerine yardımcı olamaz mı?
Bob Horn

5
Bir olay kaynağı oluşturmadan olay günlüğüne yazamazsınız , bu nedenle bu kod bunu göstermez.
CodeCaster

2
Yine de etkinlik kaynağını oluşturmam gerekiyordu, ancak soru başlığı güncellenmeden önce anwser'ınızı yayınladınız. Yine de uzunluk sınırını bilmiyordum teşekkürler.
Jerther

-4

Deneyin

   System.Diagnostics.EventLog appLog = new System.Diagnostics.EventLog();
   appLog.Source = "This Application's Name";
   appLog.WriteEntry("An entry to the Application event log.");

3
bunun bir Etkinlik Kaynağı kaydetmesi gerekir ve bu nedenle soruyu cevaplamaz. afedersiniz.
Jerther

Bu sorunun ana fikri "Uygulama" olay kaynağını kullanmaktır.
rcarrillopadron
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.