source

이벤트 소스 등록 없이 Windows 응용 프로그램 이벤트 로그에 쓰기

factcode 2023. 4. 9. 22:27
반응형

이벤트 소스 등록 없이 Windows 응용 프로그램 이벤트 로그에 쓰기

이 이벤트 로그에 쓰는 방법이 있습니까?

여기에 이미지 설명 입력

또는 이벤트 소스를 등록할 필요가 없는 다른 Windows 기본 로그도 있습니다.

네, 찾고 있는 이벤트 로그에 쓰는 방법이 있습니다.새로운 소스를 작성할 필요는 없습니다.기존 소스를 사용하면 됩니다.이러한 소스는 EventLog 이름과 이름이 같고 경우에 따라서는 EventLog Application과 같은 경우에도 관리자 권한 없이 액세스할 수 있습니다*.

* 직접 액세스할 수 없는 다른 경우로는 운영체제에서만 액세스할 수 있는 Security Event Log 등이 있습니다.

이 코드를 사용하여 이벤트 로그에 직접 기록했습니다.응용 프로그램:

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

보시는 바와 같이 EventLog 소스는 EventLog 이름과 동일합니다. 이유는 Event Sources @ Windows Dev Center에서 확인할 수 있습니다(소스 이름을 나타내는 부분은 굵은 글씨로 표시).

Eventlog 키의 각 로그에는 이벤트 소스라고 하는 서브 키가 포함됩니다.이벤트 소스는 이벤트를 기록하는 소프트웨어의 이름입니다.응용 프로그램의 이름이거나 응용 프로그램의 하위 구성 요소의 이름입니다(어플리케이션이 큰 경우입니다.레지스트리에 추가할 수 있는 이벤트소스는 최대 16,384개입니다

"How to: Write to the Application Event Log (Visual C#)"에서 설명한 바와 같이 Event Log 클래스를 사용할 수 있습니다.

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

단, 관리자 권한을 사용하여 이 소스 "MySource"를 구성해야 합니다.

이벤트 로그에 이벤트를 쓰려면 WriteEvent 및 WriteEntry를 사용합니다.이벤트를 쓸 이벤트 소스를 지정해야 합니다.소스로 첫 번째 엔트리를 쓰기 전에 이벤트 소스를 만들고 구성해야 합니다.

MSDN에 기재된 바와 같이(예:https://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog(v=vs.110).aspx )가 존재하지 않는 소스를 확인하고 소스를 작성하려면 관리자 권한이 필요합니다.

다만, 소스 「어플리케이션」을 사용하지 않고 사용할 수 있습니다.다만, Windows 2012 Server r2 의 테스트에서는, 「어플리케이션」소스를 사용하고, 다음의 로그 엔트리가 표시됩니다.

소스 응용 프로그램에서 이벤트 ID xxxx에 대한 설명을 찾을 수 없습니다.이 이벤트를 발생시키는 구성 요소가 로컬 컴퓨터에 설치되어 있지 않거나 설치가 손상되었습니다.로컬 시스템에 구성 요소를 설치하거나 복구할 수 있습니다.이벤트가 다른 컴퓨터에서 발생한 경우 디스플레이 정보를 이벤트와 함께 저장해야 합니다.다음 정보가 이벤트에 포함되었습니다. {my event entry message} 메시지 리소스가 있지만 문자열/메시지 테이블에서 메시지를 찾을 수 없습니다.

소스를 작성하기 위해 다음 방법을 정의했습니다.

    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으로 호출합니다.Current Domain(현재 도메인)친근한 이름

이 try/catch 대신 EventLogPermission 클래스를 사용할 수 있지만 이 catch를 피할 수 있을지는 확실하지 않습니다.

또한 소스를 외부에서 생성할 수도 있습니다. 예를 들어, 상승된 Powershell:

New-EventLog -LogName Application -Source MyApp

위의 방법으로 'MyApp'을 사용해도 예외가 생성되지 않고 해당 소스로 EventLog를 생성할 수 있습니다.

이것은 제가 사용하는 로거 클래스입니다. 로그에는 "" ( )" 가 있습니다.EventLog.WriteEntry()이치노이 모든 코드를 여기에 포함시키는 이유는 편리하기 때문입니다.이 클래스는 로깅과 더불어 메시지가 이벤트 로그에 기록하기에 너무 길지 않은지 확인합니다(메시지가 잘립니다).메시지가 너무 길면 예외입니다.발신자는 송신원을 지정할 수도 있습니다.발신자가 수신하지 않는 경우는, 이 클래스가 송신원을 취득합니다.도움이 됐으면 좋겠다.

【오브젝트 덤퍼】나는 여기에 그걸 다 올리고 싶지 않았어.내 건 여기서 가져왔어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;
        }
    }
}

해라

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

언급URL : https://stackoverflow.com/questions/25725151/write-to-windows-application-event-log-without-event-source-registration

반응형