"Anda harus membuat dan mengonfigurasi sumber acara sebelum menulis entri pertama dengan sumbernya."
Jerther
Sepertinya saya tidak bisa. Jadi, apakah ada metode fallback yang baik untuk memperingatkan bahwa aplikasi tidak dapat menulis ke log windows? File flat sepertinya bagus tapi, di mana? Folder aplikasi masih memerlukan beberapa izin. Aplikasi saya adalah layanan windows.
Jerther
3
Jika aplikasi Anda adalah Layanan Windows, maka sumber acara dibuat untuk Anda secara otomatis. Anda dapat mengaksesnya melalui ServiceBase.EventLog. Nama default Sumber adalah Nama Layanan.
Mike Zboray
Jawaban:
236
Ya, ada cara untuk menulis ke log peristiwa yang Anda cari. Anda tidak perlu membuat sumber baru, cukup gunakan sumber yang ada, yang sering memiliki nama yang sama dengan nama EventLog dan juga, dalam beberapa kasus seperti Aplikasi log peristiwa, dapat diakses tanpa hak administratif *.
* Kasus lain, di mana Anda tidak dapat mengaksesnya secara langsung, adalah Security EventLog, misalnya, yang hanya diakses oleh sistem operasi.
Saya menggunakan kode ini untuk menulis langsung ke Aplikasi log peristiwa:
using (EventLog eventLog =newEventLog("Application")){
eventLog.Source="Application";
eventLog.WriteEntry("Log message example",EventLogEntryType.Information,101,1);}
Seperti yang Anda lihat, sumber EventLog sama dengan nama EventLog. Alasannya dapat ditemukan di Event Sources @ Windows Dev Center (Saya membuat tebal bagian yang merujuk pada nama sumber):
Setiap log di kunci Eventlog berisi subkunci yang disebut sumber acara. Sumber acara adalah nama perangkat lunak yang mencatat acara tersebut. Sering nama aplikasi atau nama subkomponen aplikasi jika aplikasi tersebut besar. Anda dapat menambahkan maksimal 16.384 sumber acara ke dalam registri.
Tetapi teks yang Anda kutip mengatakan bahwa Anda harus mendaftarkan sumber acara di bawah kunci log peristiwa.
Raymond Chen
1
Yang saya maksudkan adalah nama Event Log sering kali sama dengan nama aplikasi, jadi itu sebabnya Anda bisa mendaftarkan entri eventlog langsung ke EventLog tanpa membuat sumber baru. Saya cetak tebal teks yang sudah di-quout untuk dibaca lebih lanjut.
cloud120
3
Secara teknis tindakan menciptakan kunci registri yang mendaftar sumber acara. Penamaan kunci setelah nama aplikasi adalah konvensi untuk menghindari konflik. Jawaban Anda pada dasarnya sama dengan jawaban ini .
Raymond Chen
7
Terima kasih atas waktu Anda, Raymond Chen, kami di sini untuk mencoba memecahkan atau menyarankan sesuatu yang dapat membantu orang lain. Dalam hal ini saya yakin saya menjawab pertanyaan topik: "Apakah ada cara untuk menulis ke log peristiwa ini: Atau setidaknya, beberapa log default Windows lainnya, di mana saya tidak harus mendaftarkan sumber acara?". -> Saya menjawab: Ya, dan saya membaginya dengan Anda. Terlepas dari kenyataan bahwa itu dapat menyebabkan konflik seperti yang Anda katakan, itu ada cara.
cloud120
7
Anda menjawab pertanyaan "Apakah ada cara untuk melakukannya tanpa mendaftarkan sumber acara?" dan jawaban Anda mengatakan "Buat kunci registri ini untuk mendaftarkan sumber acara." Ini juga identik dengan jawaban yang ada.
var appLog =newEventLog("Application");
appLog.Source="MySource";
appLog.WriteEntry("Test log message");
Namun, Anda harus mengonfigurasi sumber ini "MySource" menggunakan hak administratif:
Gunakan WriteEvent dan WriteEntry untuk menulis acara ke log peristiwa. Anda harus menentukan sumber acara untuk menulis acara; Anda harus membuat dan mengkonfigurasi sumber acara sebelum menulis entri pertama dengan sumbernya.
Ini adalah masalah yang saya miliki: Saya tidak dapat membuat sumber karena saya tidak memiliki hak istimewa itu, tetapi saya masih perlu mencatat masalah itu di suatu tempat
Namun dimungkinkan untuk menggunakan sumber "Aplikasi" tanpa. Dalam pengujian saya di bawah Windows 2012 Server r2, saya mendapatkan entri log berikut menggunakan sumber "Aplikasi":
Deskripsi untuk ID Peristiwa xxxx dari sumber Aplikasi tidak dapat ditemukan. Entah komponen yang menimbulkan peristiwa ini tidak diinstal di komputer lokal Anda atau instalasi rusak. Anda dapat menginstal atau memperbaiki komponen di komputer lokal. Jika acara tersebut berasal dari komputer lain, informasi tampilan harus disimpan dengan acara tersebut. Informasi berikut disertakan dengan acara: {pesan entri acara saya} sumber daya pesan hadir tetapi pesan tidak ditemukan dalam string / tabel pesan
Saya mendefinisikan metode berikut untuk membuat sumber:
privatestringCreateEventSource(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 privilegeEventLog.CreateEventSource(eventSource,"Application");}}catch(SecurityException){
eventSource ="Application";}return eventSource;}
Saya menyebutnya dengan currentAppName = AppDomain.CurrentDomain.FriendlyName
Dimungkinkan untuk menggunakan kelas EventLogPermission alih-alih mencoba / menangkap ini tetapi tidak yakin kita dapat menghindari tangkapan.
Dimungkinkan juga untuk membuat sumber secara eksternal, misalnya dalam Powershell yang ditinggikan:
New-EventLog-LogNameApplication-SourceMyApp
Kemudian, menggunakan 'MyApp' dalam metode di atas TIDAK akan menghasilkan pengecualian dan EventLog dapat dibuat dengan sumber itu.
Ini adalah kelas logger yang saya gunakan. Metode Private Log () ada EventLog.WriteEntry()di dalamnya, yaitu bagaimana Anda benar-benar menulis ke log peristiwa. Saya menyertakan semua kode ini di sini karena berguna. Selain mencatat, kelas ini juga akan memastikan pesan tidak terlalu panjang untuk ditulis ke log peristiwa (ini akan memotong pesan). Jika pesannya terlalu panjang, Anda akan mendapatkan pengecualian. Penelepon juga dapat menentukan sumbernya. Jika penelepon tidak, kelas ini akan mendapatkan sumbernya. Semoga ini bisa membantu.
Omong-omong, Anda bisa mendapatkan ObjectDumper dari web. Saya tidak ingin memposting semua itu di sini. Saya mendapatkan milik saya dari sini: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>publicstaticclassLogger{// 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.privateconstintMaxEventLogEntryLength=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>publicstaticstringSource{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>publicstaticvoidLogDebug(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>publicstaticvoidLogInformation(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>publicstaticvoidLogWarning(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>publicstaticvoidLogException(Exception ex,string source =""){if(ex ==null){thrownewArgumentNullException("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")]publicstaticvoidLogObjectDump(object theObject,string objectName,string source =""){constint 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);}privatestaticvoidLog(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);}}privatestaticstringGetSource(){// If the caller has explicitly set a source value, just use it.if(!string.IsNullOrWhiteSpace(Source)){returnSource;}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 =newStackTrace().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.privatestaticstringEnsureLogMessageLimit(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;}}}
Dan kode ini menunjukkan itu. Apa salahnya berbagi ini dengannya? Tidak bisakah itu membantu OP dan lainnya?
Bob Horn
5
Anda tidak dapat menulis ke log peristiwa tanpa membuat sumber acara , jadi kode ini tidak menunjukkan itu.
CodeCaster
2
Saya masih perlu membuat sumber acara tetapi Anda memposting anwser Anda sebelum judul pertanyaan diperbarui. Namun, saya tidak tahu tentang batas panjangnya, terima kasih.
Jerther
-4
mencoba
System.Diagnostics.EventLog appLog =newSystem.Diagnostics.EventLog();
appLog.Source="This Application's Name";
appLog.WriteEntry("An entry to the Application event log.");
ServiceBase.EventLog
. Nama default Sumber adalah Nama Layanan.Jawaban:
Ya, ada cara untuk menulis ke log peristiwa yang Anda cari. Anda tidak perlu membuat sumber baru, cukup gunakan sumber yang ada, yang sering memiliki nama yang sama dengan nama EventLog dan juga, dalam beberapa kasus seperti Aplikasi log peristiwa, dapat diakses tanpa hak administratif *.
* Kasus lain, di mana Anda tidak dapat mengaksesnya secara langsung, adalah Security EventLog, misalnya, yang hanya diakses oleh sistem operasi.
Saya menggunakan kode ini untuk menulis langsung ke Aplikasi log peristiwa:
Seperti yang Anda lihat, sumber EventLog sama dengan nama EventLog. Alasannya dapat ditemukan di Event Sources @ Windows Dev Center (Saya membuat tebal bagian yang merujuk pada nama sumber):
sumber
Anda bisa menggunakan kelas EventLog, seperti yang dijelaskan pada Cara: Menulis ke Log Kejadian Aplikasi (Visual C #) :
Namun, Anda harus mengonfigurasi sumber ini "MySource" menggunakan hak administratif:
sumber
Sebagaimana dinyatakan dalam MSDN (mis. Https://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog(v=vs.110).aspx ), memeriksa sumber yang tidak ada dan membuat sumber memerlukan admin hak istimewa.
Namun dimungkinkan untuk menggunakan sumber "Aplikasi" tanpa. Dalam pengujian saya di bawah Windows 2012 Server r2, saya mendapatkan entri log berikut menggunakan sumber "Aplikasi":
Saya mendefinisikan metode berikut untuk membuat sumber:
Saya menyebutnya dengan currentAppName = AppDomain.CurrentDomain.FriendlyName
Dimungkinkan untuk menggunakan kelas EventLogPermission alih-alih mencoba / menangkap ini tetapi tidak yakin kita dapat menghindari tangkapan.
Dimungkinkan juga untuk membuat sumber secara eksternal, misalnya dalam Powershell yang ditinggikan:
Kemudian, menggunakan 'MyApp' dalam metode di atas TIDAK akan menghasilkan pengecualian dan EventLog dapat dibuat dengan sumber itu.
sumber
Ini adalah kelas logger yang saya gunakan. Metode Private Log () ada
EventLog.WriteEntry()
di dalamnya, yaitu bagaimana Anda benar-benar menulis ke log peristiwa. Saya menyertakan semua kode ini di sini karena berguna. Selain mencatat, kelas ini juga akan memastikan pesan tidak terlalu panjang untuk ditulis ke log peristiwa (ini akan memotong pesan). Jika pesannya terlalu panjang, Anda akan mendapatkan pengecualian. Penelepon juga dapat menentukan sumbernya. Jika penelepon tidak, kelas ini akan mendapatkan sumbernya. Semoga ini bisa membantu.Omong-omong, Anda bisa mendapatkan ObjectDumper dari web. Saya tidak ingin memposting semua itu di sini. Saya mendapatkan milik saya dari sini:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Samples\1033\CSharpSamples.zip\LinqSamples\ObjectDumper
sumber
mencoba
sumber