このイベントログに書き込む方法はありますか。
または、少なくとも、他のWindowsのデフォルトログで、イベントソースを登録する必要はありません。
はい、探しているイベントログに書き込む方法があります。新しいソースを作成する必要はありません。単にEventLogの名前と同じ名前を持つ既存のものを使用するだけで、場合によってはイベントログアプリケーションのように、管理者特権*なしでアクセスできる場合もあります。
あなたが直接それにアクセスできない*他のケースは、例えば、オペレーティングシステムによってのみアクセスされるSecurity EventLogです。
このコードを使用して、イベントログに直接書き込みます。
using (EventLog eventLog = new EventLog("Application"))
{
eventLog.Source = "Application";
eventLog.WriteEntry("Log message example", EventLogEntryType.Information, 101, 1);
}
ご覧のとおり、EventLogのソースはEventLogの名前と同じです。この理由は、 イベントソース@ Windows Dev Center にあります(ソース名を参照する部分は太字にしています)。
Eventlogキーの各ログには、イベントソースと呼ばれるサブキーが含まれています。イベントソースは、イベントを記録するソフトウェアの名前です。 アプリケーションの名前またはアプリケーションが大きい場合はアプリケーションのサブコンポーネントの名前です。最大16,384のイベントソースをレジストリに追加できます。
EventLogクラスを使用することができます。 How to:アプリケーションイベントログに書き込む(Visual C#) :
var appLog = new EventLog("Application");
appLog.Source = "MySource";
appLog.WriteEntry("Test log message");
ただし、管理者権限を使用して、このソース "MySource"を設定する必要があります。
イベントをイベントログに書き込むには、WriteEventとWriteEntryを使用します。イベントを書き込むには、イベントソースを指定する必要があります。最初のエントリをソースに書き込む前に、イベントソースを作成して設定する必要があります。
これが私が使うロガークラスです。 private Log()メソッドにはEventLog.WriteEntry()
が含まれています。これが実際にイベントログに書き込む方法です。これは便利なので、ここにすべてのコードを含めます。ロギングに加えて、このクラスはメッセージがイベントログに書き込むには長すぎないことを確認します(メッセージを切り捨てます)。メッセージが長すぎると、例外が発生します。呼び出し元はソースを指定することもできます。呼び出し側がそうでなければ、このクラスはソースを取得します。それが役に立てば幸い。
ところで、Webから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;
}
}
}
MSDNに記載されているとおり(例: https://msdn.Microsoft.com/ja-jp/library/system.diagnostics.eventlog(v = vs.110).aspx )、存在しないソースをチェックしてソースを作成するには管理者権限が必要です。
ただし、ソース "Application"を使用せずに使用することは可能です。 Windows 2012 Server R2でのテストでは、 "Application"ソースを使用して次のログエントリを取得しました。
ソースアプリケーションのイベント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はそのソースで作成できます。
EventLogクラスWindowsのイベントログとのやり取りを提供します。この例は、EventViewerへの書き込み方法を示します。
public void WriteEventLog(string message)
{
EventLog eventLog = new EventLog() { Source = "application Name",
EnableRaisingEvents = true };
eventLog.WriteEntry( message);
}