@@ -3,7 +3,6 @@ package main
3
3
import (
4
4
"bufio"
5
5
"encoding/json"
6
- "encoding/xml"
7
6
"errors"
8
7
"flag"
9
8
"fmt"
@@ -888,7 +887,7 @@ func (app *App) selectService(g *gocui.Gui, v *gocui.View) error {
888
887
}
889
888
// Загружаем журналы выбранной службы, обрезая пробелы в названии
890
889
app .loadJournalLogs (strings .TrimSpace (line ), true , g )
891
- // Включаем загрузку журнала только при ручном выборе для Windows
890
+ // Включаем загрузку журнала ( только при ручном выборе для Windows)
892
891
app .updateFile = true
893
892
// Фиксируем для ручного или автоматического обновления вывода журнала
894
893
app .lastWindow = "services"
@@ -910,10 +909,10 @@ func (app *App) loadJournalLogs(serviceName string, newUpdate bool, g *gocui.Gui
910
909
switch {
911
910
// Читаем журналы Windows
912
911
case app .getOS == "windows" :
913
- // Отключаем чтение в горутине
914
912
if ! app .updateFile {
915
913
return
916
914
}
915
+ // Отключаем чтение в горутине
917
916
app .updateFile = false
918
917
// Извлекаем полное имя события
919
918
var eventName string
@@ -1019,82 +1018,57 @@ func (app *App) loadJournalLogs(serviceName string, newUpdate bool, g *gocui.Gui
1019
1018
// return []byte(fullMessage)
1020
1019
// }
1021
1020
1021
+ // Функция для чтения и парсинга содержимого события Windows через wevtutil
1022
1022
func (app * App ) loadWinEventLog (eventName string ) (output []byte ) {
1023
- cmd := exec .Command ("powershell" , "-Command" ,
1024
- "chcp 65001 > $null;" +
1025
- "wevtutil qe " + eventName + " /f:RenderedXml /c:5000 -l:en" )
1026
- xmlData , _ := cmd .Output ()
1027
- decoder := xml .NewDecoder (strings .NewReader (string (xmlData )))
1028
- var eventMessages []string
1029
- var inEvent , inRenderingInfo , inMessage , inLevel , inEventID bool
1030
- var systemTime , level , eventID , message string
1031
- for {
1032
- token , _ := decoder .Token ()
1033
- switch elem := token .(type ) {
1034
- case xml.StartElement :
1035
- switch elem .Name .Local {
1036
- case "Event" :
1037
- inEvent = true
1038
- systemTime , level , eventID , message = "" , "" , "" , ""
1039
- case "TimeCreated" :
1040
- if inEvent {
1041
- for _ , attr := range elem .Attr {
1042
- if attr .Name .Local == "SystemTime" {
1043
- systemTime = attr .Value
1044
- }
1045
- }
1046
- }
1047
- case "EventID" :
1048
- if inEvent {
1049
- inEventID = true
1050
- }
1051
- case "Level" :
1052
- if inEvent {
1053
- inLevel = true
1054
- }
1055
- case "RenderingInfo" :
1056
- if inEvent {
1057
- inRenderingInfo = true
1058
- }
1059
- case "Message" :
1060
- if inRenderingInfo {
1061
- inMessage = true
1023
+ cmd := exec .Command ("cmd" , "/C" ,
1024
+ "chcp 65001 &&" +
1025
+ "wevtutil qe " + eventName + " /f:text -l:en" )
1026
+ eventData , _ := cmd .Output ()
1027
+ // Декодирование вывода из Windows-1251 в UTF-8
1028
+ decoder := charmap .Windows1251 .NewDecoder ()
1029
+ decodeEventData , decodeErr := decoder .Bytes (eventData )
1030
+ if decodeErr == nil {
1031
+ eventData = decodeEventData
1032
+ }
1033
+ // Разбиваем вывод на массив
1034
+ eventStrings := strings .Split (string (eventData ), "Event[" )
1035
+ var eventMessage []string
1036
+ for _ , eventString := range eventStrings {
1037
+ var dateTime , eventID , level , description string
1038
+ // Разбиваем элемент массива на строки
1039
+ lines := strings .Split (eventString , "\n " )
1040
+ // Флаг для обработки последней строки Description с содержимым Message
1041
+ isDescription := false
1042
+ for _ , line := range lines {
1043
+ // Удаляем проблемы во всех строках
1044
+ trimmedLine := strings .TrimSpace (line )
1045
+ switch {
1046
+ // Обновляем формат даты
1047
+ case strings .HasPrefix (trimmedLine , "Date:" ):
1048
+ dateTime = strings .ReplaceAll (trimmedLine , "Date: " , "" )
1049
+ dateTimeParse := strings .Split (dateTime , "T" )
1050
+ dateParse := strings .Split (dateTimeParse [0 ], "-" )
1051
+ timeParse := strings .Split (dateTimeParse [1 ], "." )
1052
+ dateTime = fmt .Sprintf ("%s.%s.%s %s" , dateParse [2 ], dateParse [1 ], dateParse [0 ], timeParse [0 ])
1053
+ case strings .HasPrefix (trimmedLine , "Event ID:" ):
1054
+ eventID = strings .ReplaceAll (trimmedLine , "Event ID: " , "" )
1055
+ case strings .HasPrefix (trimmedLine , "Level:" ):
1056
+ level = strings .ReplaceAll (trimmedLine , "Level: " , "" )
1057
+ case strings .HasPrefix (trimmedLine , "Description:" ):
1058
+ // Фиксируем и пропускаем Description
1059
+ isDescription = true
1060
+ case isDescription :
1061
+ // Добавляем до конца текущего массива все не пустые строки
1062
+ if trimmedLine != "" {
1063
+ description += "\n " + trimmedLine
1062
1064
}
1063
1065
}
1064
- case xml.CharData :
1065
- text := string (elem )
1066
- if inEventID {
1067
- eventID = text
1068
- }
1069
- if inLevel {
1070
- level = text
1071
- }
1072
- if inMessage {
1073
- message = text
1074
- }
1075
- case xml.EndElement :
1076
- switch elem .Name .Local {
1077
- case "Event" :
1078
- inEvent = false
1079
- parsedTime , _ := time .Parse (time .RFC3339Nano , systemTime )
1080
- formattedTime := parsedTime .Format ("02.01.2006 15:04:05" )
1081
- formattedMessage := fmt .Sprintf (
1082
- "%s %s (%s): %s" ,
1083
- formattedTime , level , eventID , strings .TrimSpace (message ),
1084
- )
1085
- eventMessages = append (eventMessages , formattedMessage )
1086
- case "RenderingInfo" :
1087
- inRenderingInfo = false
1088
- case "Message" :
1089
- inMessage = false
1090
- case "Level" :
1091
- inLevel = false
1092
- case "EventID" :
1093
- inEventID = false
1094
- }
1066
+ }
1067
+ if dateTime != "" && eventID != "" && level != "" && description != "" {
1068
+ eventMessage = append (eventMessage , fmt .Sprintf ("%s %s (%s): %s" , dateTime , level , eventID , strings .TrimSpace (description )))
1095
1069
}
1096
1070
}
1097
- fullMessage := strings .Join (eventMessages , "\n " )
1071
+ fullMessage := strings .Join (eventMessage , "\n " )
1098
1072
return []byte (fullMessage )
1099
1073
}
1100
1074
0 commit comments