Windows 응용 프로그램 이벤트 로그에 쓰기


166

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

여기에 이미지 설명을 입력하십시오

또는 적어도 이벤트 소스를 등록 할 필요가없는 다른 Windows 기본 로그 무엇입니까?




1
"소스로 첫 번째 항목을 작성하기 전에 이벤트 소스를 작성하고 구성해야합니다."
Jerther

할 수없는 것 같습니다. 따라서 응용 프로그램이 Windows 로그에 쓸 수 없음을 경고하는 좋은 대체 방법이 있습니까? 플랫 파일은 좋아 보이지만 어디입니까? 응용 프로그램 폴더에는 여전히 일부 권한이 필요합니다. 내 응용 프로그램은 Windows 서비스입니다.
Jerther

3
애플리케이션이 Windows 서비스 인 경우 자동으로 이벤트 소스가 작성됩니다. 를 통해 액세스 할 수 있습니다 ServiceBase.EventLog. 소스의 기본 이름은 ServiceName입니다.
Mike Zboray

답변:


237

예, 찾고있는 이벤트 로그에 쓸 수있는 방법이 있습니다. 새로운 소스를 만들 필요는 없으며, 종종 EventLog의 이름과 이름이 같은 기존 소스를 사용하기 만하면되고 이벤트 로그 응용 프로그램과 같은 일부 경우에는 관리자 권한없이 액세스 할 수 있습니다 *.

* 직접 액세스 할 수없는 다른 경우는 보안 이벤트 로그입니다 (예 : 운영 체제에서만 액세스).

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

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

보시다시피 EventLog 소스는 EventLog의 이름과 동일합니다. 그 이유는 Windows 개발자 센터의 이벤트 소스 에서 찾을 수 있습니다 (소스 이름을 나타내는 부분은 굵게 표시).

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


1
그러나 인용 한 텍스트는 이벤트 로그 키 아래에 이벤트 소스를 등록해야한다고 말합니다.
Raymond Chen

1
내가 의미하는 바는 이벤트 로그의 이름이 종종 응용 프로그램의 이름과 동일하므로 새 소스를 만들지 않고 이벤트 로그 항목을 EventLog에 직접 등록 할 수 있습니다. 나는 더 읽을 거리를 위해 쿼트 된 텍스트를 굵게 표시했다.
cloud120

3
기술적으로 레지스트리 키를 생성하는 행위가 되는 이벤트 소스를 등록. 응용 프로그램 이름 뒤에 키 이름을 지정하면 충돌을 피할 수 있습니다. 귀하의 답변은 기본적 으로이 답변 과 동일 합니다.
Raymond Chen

7
시간 내 주셔서 감사합니다. 레이몬드 첸, 우리는 다른 사람들을 도울 수있는 것을 해결하거나 제안하려고 노력합니다. 이 경우에는 "이 이벤트 로그에 쓸 수있는 방법이 있습니까? 아니면 적어도 이벤트 소스를 등록 할 필요가없는 다른 Windows 기본 로그"라는 질문에 대한 답변이라고 생각합니다. -> 나는 대답했다 : 그렇습니다 그리고 나는 당신과 그것을 공유했습니다. 말한대로 충돌을 일으킬 수 있다는 사실에도 불구하고 방법이 있습니다.
cloud120

7
"이벤트 소스를 등록하지 않고 할 수있는 방법이 있습니까?"라는 질문에 답하고 있습니다. 답은 "이벤트 소스를 등록하기 위해이 레지스트리 키를 작성하십시오."라고 말합니다. 기존 답변과 동일합니다.
Raymond Chen

14

방법 : 응용 프로그램 이벤트 로그에 쓰기 (Visual C #)에 설명 된대로 EventLog 클래스를 사용할 수 있습니다 .

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

그러나 관리 권한을 사용 하여이 소스 "MySource" 를 구성해야합니다 .

WriteEvent 및 WriteEntry를 사용하여 이벤트를 이벤트 로그에 기록하십시오. 이벤트를 작성하려면 이벤트 소스를 지정해야합니다. 소스로 첫 번째 항목을 작성하기 전에 이벤트 소스를 작성하고 구성해야합니다.


2
이것은 내가 가진 문제입니다. 그 권한이 없기 때문에 소스를 만들 수 없지만 여전히 그 문제를 어딘가에 기록해야합니다
Jerther

2
그런 다음 설치 프로그램 ( stackoverflow.com/questions/1484605/… )을 사용하거나 파일에 로그인하십시오.
CodeCaster

1
감사합니다. 이것은 나를 다른 질문으로 인도합니다 : stackoverflow.com/questions/3930529/…
Jerther

@CodeCaster-이 로그에 액세스 할 수있는 곳은 어디입니까? 보관 장소를 의미합니까?
Arvind Chourasiya

1
@Arvind 그 질문은 내 대답과 아무런 관련이 없으며 완전히 새로운 질문입니다.
CodeCaster

11

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.CurrentDomain.FriendlyName으로 호출합니다.

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

예를 들어 상위 Powershell과 같이 외부에서 소스를 생성 할 수도 있습니다.

New-EventLog -LogName Application -Source MyApp

그런 다음 위의 방법에서 'MyApp'을 사용하면 예외가 발생하지 않으며 해당 소스로 EventLog를 만들 수 있습니다.


10

이것은 내가 사용하는 로거 클래스입니다. private Log () 메소드에는 EventLog.WriteEntry()이벤트 로그에 실제로 쓰는 방법이 있습니다. 이 코드는 모두 여기에 포함되어있어 편리합니다. 로깅 외에도이 클래스는 메시지가 이벤트 로그에 기록하기에 너무 길지 않은지 확인합니다 (메시지 잘림). 메시지가 너무 길면 예외가 발생합니다. 발신자는 소스를 지정할 수도 있습니다. 호출자가 그렇지 않으면이 클래스는 소스를 가져옵니다. 도움이 되길 바랍니다.

그건 그렇고, 웹에서 ObjectDumper를 얻을 수 있습니다. 나는 여기에 모든 것을 게시하고 싶지 않았습니다. 나는 여기에서 내 것을 얻었다 :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
그리고이 코드는 그것을 보여줍니다. 이것을 공유하는 데 어떤 해가 있습니까? OP 및 다른 사람들에게 도움이되지 않습니까?
Bob Horn

5
이벤트 소스를 작성하지 않으면 이벤트 로그에 쓸 수 없으므로이 코드는이를 표시하지 않습니다.
CodeCaster

2
여전히 이벤트 소스를 만들어야하지만 질문 제목이 업데이트되기 전에 답변을 게시했습니다. 여전히 길이 제한 덕분에 몰랐습니다.
Jerther

-4

시험

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

3
이벤트 소스를 등록해야하므로 질문에 대답하지 않습니다. 죄송합니다.
Jerther

이 질문의 주요 아이디어는 "응용 프로그램"이벤트 소스를 사용하는 것입니다.
rcarrillopadron
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.