Windowsアプリケーションイベントログに書き込む


164

このイベントログに書き込む方法はありますか。

ここに画像の説明を入力してください

または、少なくとも、イベントソースを登録する必要がない他のいくつかのWindowsデフォルトログ?




1
"ソースを使用して最初のエントリを書き込む前に、イベントソースを作成して構成する必要があります。"
Jerther 2014

できないようです。では、アプリケーションがWindowsログに書き込めないことを警告する適切なフォールバック方法はありますか?フラットファイルは良いようですが、どこですか?アプリケーションフォルダには、依然としていくつかの権限が必要です。私のアプリケーションはWindowsサービスです。
Jerther 14

3
アプリケーションがWindowsサービスの場合、イベントソースが自動的に作成されます。からアクセスできますServiceBase.EventLog。ソースのデフォルト名はServiceNameです。
Mike Zboray 2014

回答:


236

はい、探しているイベントログに書き込む方法があります。新しいソースを作成する必要はありません。単に、既存のソースを使用するだけです。これは、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 2014

3
技術的には、レジストリキーを作成する行為をされたイベントソースを登録します。アプリケーション名の後にキーに名前を付けることは、競合を回避するための規則です。あなたの答えは基本的にこの答えと同じです。
Raymond Chen

7
お時間をいただきありがとうございます。レイモンドチェン、私たちは他の人を助けるかもしれない何かを解決または提案するためにここにいます。この場合、「このイベントログに書き込む方法はありますか。少なくとも、他のWindowsのデフォルトログで、イベントソースを登録する必要がない場合」というトピックの質問に答えたと思います。->私は答えました:はい、それはあなたと共有しました。あなたが言ったようにそれが対立を引き起こすかもしれないという事実にもかかわらず、それは方法が存在します。
cloud120 2014

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 14

1
ありがとうございました。この他のSOの質問にこのリード私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

これは私が使用するロガークラスです。プライベートLog()メソッドにはEventLog.WriteEntry()、実際にイベントログに書き込む方法があります。このコードはすべて便利なので、ここにすべて含めます。ロギングに加えて、このクラスはメッセージがイベントログに書き込むには長すぎないことも確認します(メッセージを切り捨てます)。メッセージが長すぎると、例外が発生します。呼び出し元はソースを指定することもできます。呼び出し元がそうしない場合、このクラスはソースを取得します。それが役に立てば幸い。

ちなみに、ObjectDumperはWebから取得できます。ここにすべてを投稿したくありませんでした。私はここから私の物を得ました: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などに役立ってくれませんか?
ボブ・ホーン

5
イベントソースを作成せずにイベントログに書き込むことはできないため、このコードではそれを示していません。
CodeCaster 2014

2
イベントソースを作成する必要がありますが、質問のタイトルが更新される前にanwserを投稿しました。それでも、長さ制限については知りませんでした。
Jerther 14

-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 2014

この質問の主なアイデアは、「アプリケーション」イベントソースを使用することです。
rcarrillopadron 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.