Now also returning last boottime by doing bootup time and math from current time
239 lines
11 KiB
C#
239 lines
11 KiB
C#
#nullable disable
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Newtonsoft.Json.Linq;
|
|
using LD_SysInfo.Services;
|
|
|
|
namespace LD_SysInfo
|
|
{
|
|
// Extension method for safe dictionary access
|
|
public static class DictionaryExtensions
|
|
{
|
|
public static string GetValueOrDefault(this Dictionary<string, string> dict, string key)
|
|
{
|
|
return dict.ContainsKey(key) ? dict[key] : "";
|
|
}
|
|
}
|
|
public class InstalledApplication
|
|
{
|
|
[JsonProperty("name")] public string Name { get; set; }
|
|
[JsonProperty("version")] public string Version { get; set; }
|
|
[JsonProperty("publisher")] public string Publisher { get; set; }
|
|
}
|
|
|
|
public class WindowsUpdate
|
|
{
|
|
[JsonProperty("hotFixID")] public string HotFixID { get; set; }
|
|
[JsonProperty("description")] public string Description { get; set; }
|
|
[JsonProperty("installedOn")] public string InstalledOn { get; set; }
|
|
[JsonProperty("installedBy")] public string InstalledBy { get; set; } // 🔹 added back for compatibility
|
|
}
|
|
|
|
public class AppXPackage
|
|
{
|
|
[JsonProperty("name")] public string Name { get; set; }
|
|
[JsonProperty("version")] public string Version { get; set; }
|
|
[JsonProperty("publisher")] public string Publisher { get; set; }
|
|
[JsonProperty("packageFullName")] public string PackageFullName { get; set; }
|
|
}
|
|
|
|
public class DriveInfoSummary
|
|
{
|
|
[JsonProperty("name")] public string Name { get; set; }
|
|
[JsonProperty("totalSizeGB")] public double TotalSizeGB { get; set; }
|
|
[JsonProperty("freeSpaceGB")] public double FreeSpaceGB { get; set; }
|
|
[JsonProperty("driveType")] public string DriveType { get; set; }
|
|
}
|
|
|
|
public class NetworkInterfaceInfo
|
|
{
|
|
[JsonProperty("interfaceName")] public string InterfaceName { get; set; }
|
|
[JsonProperty("ipAddress")] public string IpAddress { get; set; }
|
|
[JsonProperty("macAddress")] public string MacAddress { get; set; }
|
|
}
|
|
|
|
public class SystemInfo
|
|
{
|
|
[JsonProperty("hostname")] public string Hostname { get; set; }
|
|
[JsonProperty("osName")] public string OSName { get; set; }
|
|
[JsonProperty("osVersion")] public string OSVersion { get; set; }
|
|
[JsonProperty("windowsVersion")] public string WindowsVersion { get; set; }
|
|
[JsonProperty("windowsBuild")] public string WindowsBuild { get; set; }
|
|
[JsonProperty("osArchitecture")] public string OSArchitecture { get; set; }
|
|
[JsonProperty("processorName")] public string ProcessorName { get; set; }
|
|
[JsonProperty("processorArchitecture")] public string ProcessorArchitecture { get; set; }
|
|
[JsonProperty("gpuNames")] public List<string> GpuNames { get; set; } = new();
|
|
[JsonProperty("totalMemory")] public string TotalMemory { get; set; }
|
|
[JsonProperty("ipAddresses")] public List<NetworkInterfaceInfo> IpAddresses { get; set; } = new();
|
|
[JsonProperty("lastBootTime")] public string LastBootTime { get; set; }
|
|
[JsonProperty("collectedAt")] public string CollectedAt { get; set; }
|
|
|
|
[JsonProperty("installedApplications")] public List<InstalledApplication> InstalledApplications { get; set; } = new();
|
|
[JsonProperty("userInstalledApplications")] public List<InstalledApplication> UserInstalledApplications { get; set; } = new();
|
|
[JsonProperty("windowsUpdates")] public List<WindowsUpdate> WindowsUpdates { get; set; } = new();
|
|
[JsonProperty("appXPackages")] public List<AppXPackage> AppXPackages { get; set; } = new();
|
|
[JsonProperty("drives")] public List<DriveInfoSummary> Drives { get; set; } = new();
|
|
|
|
public static SystemInfo GetSystemInfo()
|
|
{
|
|
var info = new SystemInfo { CollectedAt = DateTime.Now.ToString("MMM dd, yyyy h:mm tt") };
|
|
|
|
try
|
|
{
|
|
// ✅ Base system info - using correct osquery column names
|
|
var sys = OsqueryService.Query("SELECT * FROM system_info;").FirstOrDefault();
|
|
if (sys != null)
|
|
{
|
|
info.Hostname = sys.GetValueOrDefault("hostname");
|
|
// OSName removed - was redundant with hostname
|
|
|
|
// Windows version info from os_version table
|
|
var osVer = OsqueryService.Query("SELECT * FROM os_version;").FirstOrDefault();
|
|
if (osVer != null)
|
|
{
|
|
info.OSVersion = osVer.GetValueOrDefault("version");
|
|
info.WindowsVersion = osVer.GetValueOrDefault("name");
|
|
info.WindowsBuild = osVer.GetValueOrDefault("build");
|
|
|
|
// Get proper OS name from os_version
|
|
info.OSName = osVer.GetValueOrDefault("name"); // e.g., "Windows 10 Pro"
|
|
}
|
|
|
|
info.ProcessorName = sys.GetValueOrDefault("cpu_brand");
|
|
info.ProcessorArchitecture = sys.GetValueOrDefault("cpu_type");
|
|
|
|
// Fix OS Architecture - should be x64, x86, etc.
|
|
info.OSArchitecture = sys.GetValueOrDefault("cpu_subtype");
|
|
if (string.IsNullOrEmpty(info.OSArchitecture) || info.OSArchitecture == "-1")
|
|
{
|
|
// Fallback: determine from cpu_type or use platform info
|
|
var platform = sys.GetValueOrDefault("cpu_type");
|
|
info.OSArchitecture = platform.Contains("64") ? "x64" : "x86";
|
|
}
|
|
}
|
|
|
|
// ✅ Memory - query physical_memory table and sum up total
|
|
var memResults = OsqueryService.Query("SELECT SUM(size) as total_bytes FROM physical_memory;").FirstOrDefault();
|
|
if (memResults != null && memResults.ContainsKey("total_bytes"))
|
|
{
|
|
if (long.TryParse(memResults["total_bytes"], out long memBytes))
|
|
{
|
|
double memGB = Math.Round(memBytes / (1024.0 * 1024.0 * 1024.0), 2);
|
|
info.TotalMemory = $"{memGB} GB";
|
|
}
|
|
}
|
|
|
|
// Fallback: try WMI-based system_info table
|
|
if (string.IsNullOrEmpty(info.TotalMemory))
|
|
{
|
|
var sysInfo = OsqueryService.Query("SELECT physical_memory FROM system_info;").FirstOrDefault();
|
|
if (sysInfo != null && sysInfo.ContainsKey("physical_memory"))
|
|
{
|
|
if (long.TryParse(sysInfo["physical_memory"], out long memBytes))
|
|
{
|
|
double memGB = Math.Round(memBytes / (1024.0 * 1024.0 * 1024.0), 2);
|
|
info.TotalMemory = $"{memGB} GB";
|
|
}
|
|
}
|
|
}
|
|
|
|
// ✅ Drives
|
|
info.Drives = OsqueryService.Query("SELECT device_id, size, free_space, type FROM logical_drives;")
|
|
.Select(d => new DriveInfoSummary
|
|
{
|
|
Name = d.GetValueOrDefault("device_id"),
|
|
TotalSizeGB = d.ContainsKey("size") && double.TryParse(d["size"], out double size)
|
|
? Math.Round(size / (1024.0 * 1024.0 * 1024.0), 2) : 0,
|
|
FreeSpaceGB = d.ContainsKey("free_space") && double.TryParse(d["free_space"], out double free)
|
|
? Math.Round(free / (1024.0 * 1024.0 * 1024.0), 2) : 0,
|
|
DriveType = d.GetValueOrDefault("type")
|
|
}).ToList();
|
|
|
|
// ✅ GPU info - query registry for all GPUs
|
|
var gpuQuery = OsqueryService.Query(@"
|
|
SELECT data
|
|
FROM registry
|
|
WHERE path LIKE 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\%\DriverDesc';");
|
|
|
|
info.GpuNames = gpuQuery
|
|
.Select(g => g.GetValueOrDefault("data"))
|
|
.Where(s => !string.IsNullOrEmpty(s))
|
|
.Distinct() // Remove duplicates
|
|
.ToList();
|
|
|
|
// ✅ Network interfaces - IPv4 only, with better formatting
|
|
var ipResults = OsqueryService.Query(
|
|
"SELECT interface, address FROM interface_addresses WHERE address NOT LIKE '127.%' AND address NOT LIKE '%:%';");
|
|
|
|
info.IpAddresses = ipResults
|
|
.Select(i => new NetworkInterfaceInfo
|
|
{
|
|
InterfaceName = i.GetValueOrDefault("interface"),
|
|
IpAddress = i.GetValueOrDefault("address"),
|
|
MacAddress = ""
|
|
})
|
|
.Where(ni => !string.IsNullOrEmpty(ni.IpAddress))
|
|
.ToList();
|
|
|
|
// ✅ Last boot time - calculate from current time minus uptime
|
|
info.LastBootTime = OsqueryService.Query("SELECT datetime((SELECT CAST(unix_time AS INTEGER) FROM time) - total_seconds, 'unixepoch') as boot_time FROM uptime;")
|
|
.FirstOrDefault()?.GetValueOrDefault("boot_time");
|
|
|
|
// ✅ Installed apps (user + system)
|
|
info.InstalledApplications = OsqueryService.Query("SELECT name, version, publisher FROM programs;")
|
|
.Select(a => new InstalledApplication
|
|
{
|
|
Name = a["name"],
|
|
Version = a["version"],
|
|
Publisher = a["publisher"]
|
|
}).ToList();
|
|
|
|
info.UserInstalledApplications = info.InstalledApplications
|
|
.Where(a => !string.IsNullOrEmpty(a.Publisher))
|
|
.ToList();
|
|
|
|
// ✅ AppX packages (Windows Store)
|
|
info.AppXPackages = OsqueryService.Query("SELECT name, version, publisher, package_id FROM appx_packages;")
|
|
.Select(p => new AppXPackage
|
|
{
|
|
Name = p["name"],
|
|
Version = p["version"],
|
|
Publisher = p["publisher"],
|
|
PackageFullName = p["package_id"]
|
|
}).ToList();
|
|
|
|
// ✅ Windows Updates (patches)
|
|
info.WindowsUpdates = OsqueryService.Query("SELECT hotfix_id, description, installed_on FROM patches;")
|
|
.Select(p => new WindowsUpdate
|
|
{
|
|
HotFixID = p["hotfix_id"],
|
|
Description = p["description"],
|
|
InstalledOn = p["installed_on"],
|
|
InstalledBy = Environment.UserName
|
|
}).ToList();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
try
|
|
{
|
|
string logDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "PSG-Oversight");
|
|
Directory.CreateDirectory(logDir);
|
|
string logPath = Path.Combine(logDir, "osquery_error.log");
|
|
File.AppendAllText(logPath, $"[{DateTime.Now}] {ex}\n");
|
|
}
|
|
catch
|
|
{
|
|
// Silently fail if we can't write logs
|
|
}
|
|
}
|
|
|
|
return info;
|
|
}
|
|
|
|
}
|
|
}
|