ringbuffer and statistics

This commit is contained in:
meelstorm
2025-07-18 10:13:46 +02:00
parent d3cb790bd9
commit 40d74d6da6
41 changed files with 1188 additions and 180 deletions

View File

@@ -0,0 +1,15 @@
using Ninject.Extensions.ChildKernel;
using VisionBuilder.UI.Common;
using VisionBuilder.UI.Console;
namespace VisionBuilder.UI.Statistics;
public static class ModuleExtensions
{
public static IChildKernel UseConsole(this IChildKernel self)
{
self.Bind<VisionBuilderConsoleSettings, ISettings>().ToConstant(new VisionBuilderConsoleSettings());
self.RegisterModule<VisionBuilderConsole>();
return self;
}
}

View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VisionBuilder.UI.Common\VisionBuilder.UI.Common.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,36 @@
using Ninject;
using Serilog;
using VisionBuilder.UI.Common;
namespace VisionBuilder.UI.Console
{
public class VisionBuilderConsole: IVisionBuilderModule
{
private readonly VisionBuilderConsoleSettings _settings;
public VisionBuilderConsole(VisionBuilderConsoleSettings settings)
{
_settings = settings;
}
public void InitializeModule()
{
if (_settings.CreateConsoleWindow)
{
WinConsole.Initialize();
}
// configure Serilog to use console
if (_settings.UseConsole)
{
Serilog.Log.Logger = new Serilog.LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.CreateLogger();
Log.Information("Console initialized");
}
}
}
}

View File

@@ -0,0 +1,18 @@
using Inspectron.Settings;
using Inspectron.Settings.Attributes;
using Serilog;
using VisionBuilder.UI.Common;
namespace VisionBuilder.UI.Console;
public class VisionBuilderConsoleSettings:ISettings
{
public bool UseConsole { get; set; } = false;
[SettingDescription("Create a console window for non-console application")]
public bool CreateConsoleWindow { get; set; }
public void RegisterSettings(InspectronSettings settings)
{
settings.RegisterSimple(this, () => this.UseConsole, "Console", nameof(UseConsole));
settings.RegisterSimple(this, () => this.CreateConsoleWindow, "Console", nameof(CreateConsoleWindow));
}
}

View File

@@ -0,0 +1,118 @@
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
namespace VisionBuilder.UI.Console
{
public static class WinConsole
{
public static void Initialize(bool alwaysCreateNewConsole = true, bool minimizeWindow = false)
{
bool consoleAttached = true;
if (alwaysCreateNewConsole
|| (AttachConsole(ATTACH_PARRENT) == 0
&& Marshal.GetLastWin32Error() != ERROR_ACCESS_DENIED))
{
consoleAttached = AllocConsole() != 0;
}
if (consoleAttached)
{
InitializeOutStream();
InitializeInStream();
}
if (minimizeWindow)
{
const int SW_MINIMIZE = 6;
var handle = GetConsoleWindow();
ShowWindow(handle, SW_MINIMIZE);
}
}
public static void MinimizeWindow()
{
const int SW_MINIMIZE = 6;
var handle = GetConsoleWindow();
ShowWindow(handle, SW_MINIMIZE);
}
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("kernel32.dll")]
private static extern IntPtr GetConsoleWindow();
private static void InitializeOutStream()
{
var fs = CreateFileStream("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE, FileAccess.Write);
if (fs != null)
{
var writer = new StreamWriter(fs) { AutoFlush = true };
System.Console.SetOut(writer);
System.Console.SetError(writer);
}
}
private static void InitializeInStream()
{
var fs = CreateFileStream("CONIN$", GENERIC_READ, FILE_SHARE_READ, FileAccess.Read);
if (fs != null)
{
System.Console.SetIn(new StreamReader(fs));
}
}
private static FileStream CreateFileStream(string name, uint win32DesiredAccess, uint win32ShareMode,
FileAccess dotNetFileAccess)
{
var file = new SafeFileHandle(CreateFileW(name, win32DesiredAccess, win32ShareMode, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero), true);
if (!file.IsInvalid)
{
var fs = new FileStream(file, dotNetFileAccess);
return fs;
}
return null;
}
#region Win API Functions and Constants
[DllImport("kernel32.dll",
EntryPoint = "AllocConsole",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int AllocConsole();
[DllImport("kernel32.dll",
EntryPoint = "AttachConsole",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern UInt32 AttachConsole(UInt32 dwProcessId);
[DllImport("kernel32.dll",
EntryPoint = "CreateFileW",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr CreateFileW(
string lpFileName,
UInt32 dwDesiredAccess,
UInt32 dwShareMode,
IntPtr lpSecurityAttributes,
UInt32 dwCreationDisposition,
UInt32 dwFlagsAndAttributes,
IntPtr hTemplateFile
);
private const UInt32 GENERIC_WRITE = 0x40000000;
private const UInt32 GENERIC_READ = 0x80000000;
private const UInt32 FILE_SHARE_READ = 0x00000001;
private const UInt32 FILE_SHARE_WRITE = 0x00000002;
private const UInt32 OPEN_EXISTING = 0x00000003;
private const UInt32 FILE_ATTRIBUTE_NORMAL = 0x80;
private const UInt32 ERROR_ACCESS_DENIED = 5;
private const UInt32 ATTACH_PARRENT = 0xFFFFFFFF;
#endregion
}
}