C#中拼接Event Log提取变量后控制台输出空白问题求助
问题
编写C#脚本从Windows安全日志的4625(登录失败)事件中提取时间、IP地址、账户名与账户域,单独输出各变量时控制台显示正常,但拼接成字符串后,输出内容缺失时间与IP信息。尝试过对变量调用ToString()方法、使用字符串插值,均未解决问题。
相关代码
using System; using System.Diagnostics; using System.Linq; using System.Net; using System.Text.RegularExpressions; class Program { static void Main() { string GetIP(string input) { Regex regex = new Regex(@"Source Network Address:.*"); Match match = regex.Match(input); if (match.Success) { string ipAddress = Regex.Replace(match.Value, @"Source Network Address:\s*", ""); return ipAddress; } else { return "No match found."; } } string GetAcc(string input) { Regex regexAccountName = new Regex(@"Account Name:\s*(\S+)"); MatchCollection matches = regexAccountName.Matches(input); if (matches.Count >= 2) { string accountName = matches[1].Groups[1].Value; return accountName; } else { return "No match found."; } } string GetDomain(string input) { Regex regexAccountName = new Regex(@"Account Domain:\s*(\S+)"); MatchCollection matches = regexAccountName.Matches(input); if (matches.Count >= 2) { string accountName = matches[1].Groups[1].Value; return accountName; } else { return "No match found."; } } Console.WriteLine("Date/Time,IP Address,Account Name,Account Domain"); int targetEventId = 4625; string logName = "Security"; EventLog eventLog = new EventLog(logName); foreach (EventLogEntry entry in eventLog.Entries) { if (entry.InstanceId == targetEventId) { DateTime Time = Convert.ToDateTime(entry.TimeGenerated); Console.WriteLine(Time); string message = entry.Message; string ip = GetIP(message); Console.WriteLine(ip); string acc = GetAcc(message); Console.WriteLine(acc); string domain = GetDomain(message); Console.WriteLine(domain); string csvOutput = Time + "," + ip + "," + acc + "," + domain; Console.WriteLine(csvOutput); } } eventLog.Close(); Console.WriteLine("End of logs. Press any key to exit."); Console.ReadKey(); } }
场景说明
- 输入:Windows安全日志中ID为4625的登录失败事件详细内容
- 实际输出:拼接后的字符串缺失时间与IP信息
- 预期输出:完整CSV格式内容,例如:
9/26/2023 10:39:53 AM,192.168.1.198,abc@def.ghi,MicrosoftAccount
解决方案
问题根源是提取的IP字符串中包含隐藏的回车/换行控制字符,控制台单独输出时会自动换行,但拼接后这些控制字符会覆盖前面的时间内容(类似终端的\r光标回退)。同时优化正则逻辑,避免不必要的字符串处理:
修复步骤
- 清理提取字符串中的控制字符:对提取的IP、账户名、域字符串调用
Trim(),或显式移除\r、\n - 优化IP提取正则:直接捕获IP地址,减少字符串替换操作,避免引入控制字符
- 明确格式化DateTime:避免默认格式可能带来的问题
修改后的代码
using System; using System.Diagnostics; using System.Text.RegularExpressions; class Program { static void Main() { string GetIP(string input) { // 直接捕获IP地址,避免匹配整行带来的换行符 Regex regex = new Regex(@"Source Network Address:\s*(\S+)"); Match match = regex.Match(input); if (match.Success) { // 清理可能的控制字符 return match.Groups[1].Value.Trim().Replace("\r", "").Replace("\n", ""); } else { return "No match found."; } } string GetAcc(string input) { Regex regexAccountName = new Regex(@"Account Name:\s*(\S+)"); MatchCollection matches = regexAccountName.Matches(input); if (matches.Count >= 2) { return matches[1].Groups[1].Value.Trim().Replace("\r", "").Replace("\n", ""); } else { return "No match found."; } } string GetDomain(string input) { Regex regexAccountName = new Regex(@"Account Domain:\s*(\S+)"); MatchCollection matches = regexAccountName.Matches(input); if (matches.Count >= 2) { return matches[1].Groups[1].Value.Trim().Replace("\r", "").Replace("\n", ""); } else { return "No match found."; } } Console.WriteLine("Date/Time,IP Address,Account Name,Account Domain"); int targetEventId = 4625; string logName = "Security"; EventLog eventLog = new EventLog(logName); foreach (EventLogEntry entry in eventLog.Entries) { if (entry.InstanceId == targetEventId) { DateTime time = entry.TimeGenerated; // 无需Convert,TimeGenerated本身就是DateTime Console.WriteLine(time); string message = entry.Message; string ip = GetIP(message); Console.WriteLine(ip); string acc = GetAcc(message); Console.WriteLine(acc); string domain = GetDomain(message); Console.WriteLine(domain); // 使用字符串插值,并明确格式化时间 string csvOutput = $"{time:G},{ip},{acc},{domain}"; Console.WriteLine(csvOutput); } } eventLog.Close(); Console.WriteLine("End of logs. Press any key to exit."); Console.ReadKey(); } }
关键修改点
- IP提取正则改为捕获组
(\S+),直接获取IP,避免匹配整行引入换行符 - 所有提取的字符串都调用
Trim()并移除\r、\n,彻底清理控制字符 - 直接使用
entry.TimeGenerated,无需额外转换 - 字符串插值时明确指定时间格式
G(常规日期时间格式)
内容的提问来源于stack exchange,提问作者TWB503
相关产品推荐
相关产品推荐

