问题:是否可以在不以“以管理员身份运行”的流程中导出事件日志?
我正在关注https://msdn.microsoft.com/en-us/library/bb671203(v=vs.90).aspx
的示例代码using (var els = new EventLogSession())
{
els.ExportLogAndMessages("Security", PathType.LogName, "*", @"c:\temp\security.evtx");
}
当我使用“以管理员身份运行”运行流程时,此代码成功运行,但在“不以管理员身份运行且异常
时失败”System.UnauthorizedAccessException的: “试图执行未经授权的操作。”
使用类似的代码访问我的应用程序的事件日志
using (var els = new EventLogSession())
{
els.ExportLogAndMessages("MyAppLog", PathType.LogName, "*", @"c:\temp\myapplog.evtx");
}
除了异常不同之外,我得到了类似的结果:
System.Diagnostics.Eventing.Reader.EventLogException:“目录名无效”
我做错了什么,或者是否有不同的方法可以让我将事件日志导出到.evtx文件而不需要管理员权限?
备注:
EvtArchiveExportedLog
中调用(和失败)
https://msdn.microsoft.com/en-us/library/windows/desktop/aa385232(v=vs.85).aspx 答案 0 :(得分:1)
使用pinvoke.net上显示的方法,对我的自定义应用程序日志(即上例中的MyAppLog
)没有管理员权限。这不适用于上面显示的Security
日志示例(但我认为这是预期的):
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern IntPtr OpenEventLog(string UNCServerName, string sourceName);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern bool BackupEventLog(IntPtr hEventLog, string backupFile);
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool CloseEventLog(IntPtr hEventLog);
void SaveLog(string eventLogName, string destinationDirectory)
{
string exportedEventLogFileName = Path.Combine(destinationDirectory, eventLogName + ".evtx");
IntPtr logHandle = OpenEventLog(Environment.MachineName, eventLogName);
if (IntPtr.Zero != logHandle)
{
bool retValue = BackupEventLog(logHandle, exportedEventLogFileName);
//If false, notify.
CloseEventLog(logHandle);
}
}
答案 1 :(得分:1)
问题:是否可以在不以"以管理员身份运行的流程中导出事件日志"?
是的,您可以,但前提是您有权访问要导出的事件日志。
然而,你的问题似乎更像是
为什么我无法使用
EventLogSession
导出应用程序的事件日志?弹出EventLogException
消息"目录名无效"。
查看EventLogSession
的源代码,您可以看到对ExportLogAndMessages
的调用将调用本机函数EvtExportLog
。如果此函数失败,则通过调用GetLastError
来检索错误代码。然后,此本机Windows错误代码为mapped to one of several exceptions。
如果发生以下任何错误,则会抛出您遇到的异常:
如果指定了错误的事件日志名称,则ERROR_EVT_CHANNEL_NOT_FOUND是您遇到的错误。我猜这是你的问题。
但是,您可以自己调用EvtExportLog
并检查本机错误代码,以便更好地理解调用失败的原因:
[DllImport("kernel32.dll")]
static extern uint GetLastError();
[DllImport("wevtapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EvtExportLog(IntPtr session, string channelPath, string query, string targetFilePath, int flags);
var success = EvtExportLog(IntPtr.Zero, "MyAppLog", "*", @"c:\temp\myapplog.evtx", 1);
if (!success)
{
var error = GetLastError();
Console.WriteLine(error);
}
本机错误代码应该能够清楚地表明底层问题是什么。
答案 2 :(得分:0)
这有点陈旧,但是在尝试解决相同的问题时,我又多次提到它。在不提供管理员凭据的情况下,我不知道使用EventLogSession
的任何方法。
但是,Windows命令wevtutil
将允许您导出到evtx
文件,而无需管理员权限。例如,在命令窗口中运行wevtutil epl Application Downloads\export-Application.evtx
将导出应用程序事件日志。
要从C#程序运行,可以使用以下方法:
/// <summary>
/// Run wevtutil with the given parameters.
/// </summary>
/// <param name="programPath">Path to wevtutil</param>
/// <param name="programParameters">wevutil parameters</param>
/// <returns></returns>
/// <remarks>https://stackoverflow.com/a/37138255/468523</remarks>
private static (string info, string err) RunWevtUtil(string programPath, string programParameters)
{
var process = new Process
{
StartInfo =
{
FileName = programPath,
Arguments = programParameters,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
}
};
process.Start();
var outputData = process.StandardOutput.ReadToEnd();
var errorData = process.StandardError.ReadToEnd();
process.WaitForExit();
return (outputData, errorData);
}
对于programPath
,请提供指向wevtutil
的完整路径,通常为@“ C:\ Windows \ System32 \ wevtutil.exe”。对于programParameters
,您可以使用@“ epl Application Downloads \ export-Application.evtx”。它返回给出标准和错误输出的字符串元组。
您可以使用Windows命令行来测试您的参数,然后在程序中使用它们。