Public/Show-LogAnalyzerUI.ps1
function Show-LogAnalyzerUI { if (-not $IsWindows) { throw "❌ The Smart Log Analyzer UI is only supported on Windows." } try { Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing } catch { throw "❌ Failed to load Windows Forms. This feature requires .NET and Windows." } # Form $form = New-Object Windows.Forms.Form $form.Text = "Smart Log Analyzer" $form.Size = New-Object Drawing.Size(1000, 700) $form.StartPosition = "CenterScreen" # File Select Button $btnSelect = New-Object Windows.Forms.Button $btnSelect.Text = "Select Log Files" $btnSelect.Location = New-Object Drawing.Point(10, 10) $btnSelect.Size = New-Object Drawing.Size(150, 30) # Export Buttons $btnExportCSV = New-Object Windows.Forms.Button $btnExportCSV.Text = "Export to CSV" $btnExportCSV.Location = New-Object Drawing.Point(170, 10) $btnExportCSV.Size = New-Object Drawing.Size(120, 30) $btnExportJSON = New-Object Windows.Forms.Button $btnExportJSON.Text = "Export to JSON" $btnExportJSON.Location = New-Object Drawing.Point(300, 10) $btnExportJSON.Size = New-Object Drawing.Size(120, 30) # Data Grid $grid = New-Object Windows.Forms.DataGridView $grid.Location = New-Object Drawing.Point(10, 50) $grid.Size = New-Object Drawing.Size(960, 540) $grid.AutoSizeColumnsMode = 'Fill' $grid.ReadOnly = $true $grid.AutoGenerateColumns = $false # Summary Label $lblSummary = New-Object Windows.Forms.Label $lblSummary.Location = New-Object Drawing.Point(10, 600) $lblSummary.Size = New-Object Drawing.Size(960, 60) $lblSummary.Text = "Summary will appear here..." # Add controls to form $form.Controls.AddRange(@($btnSelect, $btnExportCSV, $btnExportJSON, $grid, $lblSummary)) # Global variable for current log data $logData = @() # File Select Action $btnSelect.Add_Click({ $dialog = New-Object System.Windows.Forms.OpenFileDialog $dialog.Multiselect = $true $dialog.Filter = "Log Files (*.etl;*.log;*.txt)|*.etl;*.log;*.txt|All Files (*.*)|*.*" if ($dialog.ShowDialog() -eq "OK") { $entries = @() foreach ($file in $dialog.FileNames) { try { $entries += Get-LogEntries -Path $file } catch { [System.Windows.Forms.MessageBox]::Show("Failed to read $file`n$($_.Exception.Message)", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error) } } $logData = $entries | ForEach-Object { if ($_ -match '^(?<Time>[\d\-:\s]+) \[(?<Level>[^\]]+)\] (?<Provider>[^:]+): (?<Message>.+)$') { [pscustomobject]@{ Timestamp = $matches.Time Level = $matches.Level Provider = $matches.Provider Message = $matches.Message } } else { [pscustomobject]@{ RawEntry = $_ } } } $grid.Columns.Clear() if ($logData.Count -gt 0) { foreach ($col in $logData[0].PSObject.Properties.Name) { $colObj = New-Object Windows.Forms.DataGridViewTextBoxColumn $colObj.Name = $col $colObj.DataPropertyName = $col $colObj.HeaderText = $col $grid.Columns.Add($colObj) } } $grid.DataSource = $logData try { $summary = Get-LogSummary -LogLines $entries $lblSummary.Text = "Total: $($summary.TotalLines) | Errors: $($summary.ErrorCount) | Warnings: $($summary.WarningCount) | Info: $($summary.InfoCount)`nFrom: $($summary.FirstTimestamp) To: $($summary.LastTimestamp)" } catch { $lblSummary.Text = "Could not generate summary." } } }) # Export to CSV $btnExportCSV.Add_Click({ if (-not $logData) { return } $save = New-Object System.Windows.Forms.SaveFileDialog $save.Filter = "CSV Files (*.csv)|*.csv" $save.FileName = "LogExport.csv" if ($save.ShowDialog() -eq "OK") { $logData | Export-Csv -Path $save.FileName -NoTypeInformation [System.Windows.Forms.MessageBox]::Show("Exported to CSV.", "Export", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information) } }) # Export to JSON $btnExportJSON.Add_Click({ if (-not $logData) { return } $save = New-Object System.Windows.Forms.SaveFileDialog $save.Filter = "JSON Files (*.json)|*.json" $save.FileName = "LogExport.json" if ($save.ShowDialog() -eq "OK") { $logData | ConvertTo-Json -Depth 5 | Set-Content -Path $save.FileName [System.Windows.Forms.MessageBox]::Show("Exported to JSON.", "Export", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information) } }) # Show form $form.Topmost = $true $form.Add_Shown({ $form.Activate() }) [void]$form.ShowDialog() } # SIG # Begin signature block # MIIFsAYJKoZIhvcNAQcCoIIFoTCCBZ0CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAI7BrdnHx6nF/N # xim/J2+h8C08sYDvuo9AlAlYaHTh5KCCAxwwggMYMIICAKADAgECAhAVMtqhUrdy # mkjK9MI220b3MA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGVNtYXJ0TG9nQW5h # bHl6ZXIgRGV2IENlcnQwHhcNMjUwNjE4MjIxMTA3WhcNMjYwNjE4MjIzMTA3WjAk # MSIwIAYDVQQDDBlTbWFydExvZ0FuYWx5emVyIERldiBDZXJ0MIIBIjANBgkqhkiG # 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzLQdDt7qLciu6u2CtXOuwfSDoMKY73xMjh7l # AcWWteWEvv9zLo6zQ02uHX5Xgz+dLyNhYs0kqQor4s8DkSRRQXzr90IENyL5LG5B # sMyFhhmmUjA4QFQxgn5exm4DI56hNw/VrDKTkGUvHE2SAai7spZBSkU6hXe2+aEj # Ld9vdbJc5gS0iGQ+XIF6oJUB3owuQE+30WFZaGpqtHfS8jtxkwUsfwxM1Y2AK+Zj # Mv1P+njfhVDbfIsXS051dtXbeE5ClEu5XINZP7zVXy4XEsGo/br/cA3OubbEzEJW # SnPVuuZGsw4SoM3RJx0MVPZG4vd2YLZDKiJYqv3uJBgQi4LYhQIDAQABo0YwRDAO # BgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHQYDVR0OBBYEFEOg # ZC7C7IdkMQsB+4Eti+0plKQ1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ+i2wjjPtCzjF # hrZw0IfpPcOOy/1fQXAryX52thXIA/Wcb+6qi5WmEpHZtZTxnZ3qyIkRpGa0NsuH # BlYu0HlTN9Y6JA25gdiOQ9idDpUbpOz+gfD/t9vs0+cQC664l7mnFqHGXRrSsC4N # zLYnde5ROU3NWfUkZyEsftBk0IghIi4qvJXAW3ic6dDQdq4rEpuUrI+pa2R2h1nE # sjkv2ru5yL58u8zS7enQ4XGMJRfcow4yyS55a3tQYtnZzCyWS7AeYkbTTjzE4Oxg # p31zzX01eYEundHvZAxoLg7QENvbqWiFwkbx7ssc/6ehiwOapNUhJTOB1glNAqX/ # rGRwMRitMYIB6jCCAeYCAQEwODAkMSIwIAYDVQQDDBlTbWFydExvZ0FuYWx5emVy # IERldiBDZXJ0AhAVMtqhUrdymkjK9MI220b3MA0GCWCGSAFlAwQCAQUAoIGEMBgG # CisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcC # AQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIE # IOLk02e/9RNopm1Dndj4NR9fsuy6Wrxj+MFiq/2gjryqMA0GCSqGSIb3DQEBAQUA # BIIBAHvIEUAukYfPUH32xeo9GtOTrz8/B1dkZAGh4KaxHE64U6XNWSGYMKvtRsmo # 8vVVOT9pKsCbbidyVsWT/5CMbKpSL7yQJ59Ds9+s5gUMmvOiqK0CE/B8sLRsLfim # KyjbCe7BcXzKPZOB/J1D35Y7lTzSPmDIeTXt2Nga8t+n1+rCUYP156aY9WEA7NZc # d2wIJWGIy8Zpq+RF+1c7YWTm10HmbDsoJCGzZ0+BUFWzl2KyUrT4xvNj61qJw/xP # R/On/nwbFzUVLxeGF49x/ITRKrNbAsc3lU7XB1DdEBmGZNGIHo7wrNfdxQKmmyAA # lMj9sroTn61l/mxpSckf3pB2KYc= # SIG # End signature block |