我有一个我在多个ClickOnce应用程序中使用的库。如果此库中出现错误,我想将错误写入窗口EventLog
。
我发现了一个KB article,但似乎这需要管理员权限来搜索来源。特别是在尝试搜索Security
事件日志时会发出窒息。
是否有解决方法并在ClickOnce应用程序中写入事件日志?我看到一个人trying to write to a known source,但他们似乎无法找到始终可用的来源。
修改
根据这里的答案,我创建了一个程序,该程序包含在我的应用程序中,我可以在第一次运行时运行以设置可以获得管理员权限的事件源。但是一旦创建了源代码,我似乎仍然无法写入它。
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
if (!EventLog.SourceExists("ATE"))
{
EventLog.CreateEventSource("ATE", "Application");
}
}
是否正确创建了一个源(相当于Yannick Blondeau提供的注册表编辑)。当我在非提升的应用程序中写入源时,我收到一个新的错误,但它仍然无法正常工作。新错误是:
Cannot open log for source 'ATE'. You may not have write access.
编辑2:
我现在一直试图通过CustomSD key上的注册表编辑来使其工作。我尝试添加(A ;; 0x7 ;;; AU)为经过身份验证的用户提供完全访问权限,但似乎没有任何效果。
答案 0 :(得分:8)
不幸的是,事件源需要创建管理权限。但是,您不需要管理员权限来写入事件日志或从中读取。
有两种解决方法。
以管理员身份安装应用程序时添加新事件源。
您创建了一个简单的应用程序,您作为管理员运行以配置您的应用程序。这甚至可以包含在安装程序中。
如果您没有或不想要安装程序,请将应用程序作为管理员加载到计算机上并运行一次程序。您的应用启动应该配置事件源,如果它还没有,对吧? (好的,这有三种方式。)
此代码段来自microsoft:http://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog.aspx,旨在以管理员用户身份运行。
using System;
using System.Diagnostics;
using System.Threading;
class MySample
{
public static void Main()
{
// Create the source, if it does not already exist.
if (!EventLog.SourceExists("MySource"))
{
//An event log source should not be created and immediately used.
//There is a latency time to enable the source, it should be created
//prior to executing the application that uses the source.
//Execute this sample a second time to use the new source.
EventLog.CreateEventSource("MySource", "MyNewLog");
Console.WriteLine("CreatedEventSource");
Console.WriteLine("Exiting, execute the application a second time to use the source.");
// The source is created. Exit the application to allow it to be registered.
return;
}
// Create an EventLog instance and assign its source.
EventLog myLog = new EventLog();
myLog.Source = "MySource";
// Write an informational entry to the event log.
myLog.WriteEntry("Writing to event log.");
}
}
我知道这可能不完全是你所追求的,但我认为这是唯一的方法。
编辑1:添加了更多代码
public class EventLogger
{
private const string logName = "Application";
private static string appName = "";
private static bool sourceExists = false;
public static string AppName
{
get { return appName; }
set { appName = value; }
}
public static void Init(string appName)
{
AppName = appName;
sourceExists = EventLog.SourceExists(AppName);
if (!sourceExists)
{
EventLog.CreateEventSource(AppName, logName);
sourceExists = true;
}
}
private static void Write(string entry, EventLogEntryType logType, int eventID)
{
if (sourceExists)
{
EventLog.WriteEntry(AppName, entry, logType, eventID);
}
}
public static void Warning(string entry) { Write(entry, EventLogEntryType.Warning, 200); }
public static void Warning(string entry, int eventID) { Write(entry, EventLogEntryType.Warning, eventID); }
public static void Error(string entry) { Write(entry, EventLogEntryType.Error, 300); }
public static void Error(string entry, int eventID) { Write(entry, EventLogEntryType.Error, eventID); }
public static void Info(string entry) { Write(entry, EventLogEntryType.Information, 100); }
public static void Info(string entry, int eventID) { Write(entry, EventLogEntryType.Information, eventID); }
}
这是我实现在生产应用程序中使用的EventLogger类的方式。
如果您可以发布您的代码,我们可以进行比较。
我遇到的一件事是,当我创建源代码时,我使用应用程序名称,但坚持使用应用程序日志文件。您是否还尝试创建新的日志文件。如果是,请检查它是否在事件查看器中创建。
编辑2:模拟用户令牌值为零的用户
这有点难过。
尝试使用此代码,围绕事件编写代码。
System.Security.Principal.WindowsImpersonationContext wic = System.Security.Principal.WindowsIdentity.Impersonate(IntPtr.Zero);
// your code to write to event log or any to do something which needs elevated permission--
wic.Undo();
我没有试过这个,只是因为我的代码正常运行,它来自这里:http://sharenotes.wordpress.com/2008/03/18/cannot-open-log-for-source-you-may-not-have-write-access/
答案 1 :(得分:2)
另一种方法是下载ClickOnce setup.exe文件,右键单击并以管理员身份运行。不太令人满意,但似乎有效。
答案 2 :(得分:0)
在ClickOnce documentation中,如果运行ClickOnce应用程序的用户不是管理员,则应用程序将无法写入事件日志。
完整报价:
在ClickOnce部署之后,应用程序将创建一个事件 如果应用程序尝试时尚未存在,则为source 将事件写入事件日志。如果用户不是管理员, 尝试失败,应用程序不会记录任何事件。在这 例如,您可以手动创建事件源。
要手动创建事件源,您必须在部署过程中在注册表中添加一个条目:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\YourApp]
"EventMessageFile"="%SystemRoot%\\Microsoft.NET\\Framework\\v2.0.50727\\EventLogMessages.dll"
此方法将限制部署阶段的高程需求。