A comprehensive multi-target .NET shared library platform providing essential building blocks for enterprise applications within the BAUER GROUP ecosystem. Supports .NET 10, .NET 8, and .NET Standard 2.0 for maximum compatibility.
The BAUER GROUP Shared Libraries form a modular, multi-project solution designed to accelerate development across the organization. It provides battle-tested implementations for common enterprise requirements including logging, data persistence, API integrations, cloud services, and desktop UI components.
- Multi-Target Support: .NET 10, .NET 8, and .NET Standard 2.0 for broad compatibility
- Modular Architecture: Pick only the packages you need
- Enterprise-Ready Logging: NLog-based logging with Sentry integration for error tracking
- Data Layer: Support for SQLite (persistent key-value storage), LiteDB, and in-memory databases
- API Integrations: Generic REST API client with RestSharp
- Cloud Services: Cloudinary media management, RemoveBG background removal, Fixer.io currency exchange
- Desktop Components: WPF/WinForms utilities with embedded Chromium browser support
- Cross-Platform UI: Avalonia components for Windows, Linux and macOS, including an embeddable live log viewer
- Reporting: Stimulsoft Reports integration for professional reporting
| Package | Target Frameworks | Description |
|---|---|---|
BAUERGROUP.Shared.Core |
net10.0, net8.0, netstandard2.0 | Core utilities, extensions, logging (NLog + Sentry), resilience patterns (Polly) |
BAUERGROUP.Shared.Data |
net10.0, net8.0, netstandard2.0 | Data persistence: SQLite key-value storage, LiteDB, in-memory database (NMemory) |
BAUERGROUP.Shared.API |
net10.0, net8.0, netstandard2.0 | Generic REST API client (RestSharp) with JSON serialization |
BAUERGROUP.Shared.Cloud |
net10.0, net8.0 | Cloud services: Cloudinary, RemoveBG, Fixer.io currency exchange |
BAUERGROUP.Shared.Avalonia |
net10.0, net8.0 | Cross-platform Avalonia UI components (Windows, Linux, macOS), including an embeddable live log viewer |
BAUERGROUP.Shared.Desktop |
net10.0-windows, net8.0-windows | WPF/WinForms utilities, behaviors, reactive extensions |
BAUERGROUP.Shared.Desktop.Browser |
net10.0-windows, net8.0-windows | Embedded Chromium browser (CefSharp) and WebView2 for WPF |
BAUERGROUP.Shared.Desktop.Reporting |
net10.0-windows, net8.0-windows | Stimulsoft Reports integration* |
*Requires separate Stimulsoft license
# Core package (required)
Install-Package BAUERGROUP.Shared.Core
# Optional packages
Install-Package BAUERGROUP.Shared.Data
Install-Package BAUERGROUP.Shared.API
Install-Package BAUERGROUP.Shared.Cloud
Install-Package BAUERGROUP.Shared.Avalonia
Install-Package BAUERGROUP.Shared.Desktop
Install-Package BAUERGROUP.Shared.Desktop.Browser
Install-Package BAUERGROUP.Shared.Desktop.Reportingdotnet add package BAUERGROUP.Shared.Core
# Cross-platform Avalonia UI components (optional)
dotnet add package BAUERGROUP.Shared.Avaloniausing BAUERGROUP.Shared.Core.Logging;
// Optional: override name and log folder before BGLogger is first used
// (defaults: executable name, see "Data, Log and Error-Report Folders")
BGLoggerConfiguration.ApplicationName = "MyApplication";
BGLoggerConfiguration.LogDirectory = @"C:\Logs";
// Enable Sentry error tracking (optional)
BGLogger.Configuration.SentryDsn = "https://your-sentry-dsn@sentry.io/project";
BGLogger.Configuration.SentryEnvironment = "production";
BGLogger.Configuration.ErrorTracking = true;
// Enable additional targets as needed
BGLogger.Configuration.Console = true;
BGLogger.Configuration.File = true; // Enabled by default
// Use the logger
BGLogger.Info("Application started");
BGLogger.Error(exception, "An error occurred");
// Enable automatic unhandled exception reporting
BGLogger.UnhandledExceptionReporting(true);BAUERGROUP.Shared.Avalonia shows the running process's own log events — no UDP socket, no log file to tail. The viewer registers an in-process live sink while it is visible and removes it again when it is hidden or closed, so a diagnostics pane costs nothing while it is closed.
F12 window — LogViewerWindow.Toggle opens a log window owned by the given window, or closes the one it already owns:
using Avalonia.Controls;
using Avalonia.Input;
using BAUERGROUP.Shared.Avalonia.Logging;
public class MainWindow : Window
{
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.Key == Key.F12)
{
e.Handled = true;
LogViewerWindow.Toggle(this, "Diagnostics");
return;
}
base.OnKeyDown(e);
}
}Embedded pane — drop the control anywhere in your XAML:
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:logging="clr-namespace:BAUERGROUP.Shared.Avalonia.Logging;assembly=BAUERGROUP.Shared.Avalonia">
<!-- Captures only while visible: binding IsVisible to a "show log" toggle removes the sink again. -->
<logging:LogViewer MaxLines="10000" ShowToolbar="True" AutoScroll="True" />
</UserControl>MinimumLevel (default LogLevel.Trace) is the capture level and is set from code-behind:
viewer.MinimumLevel = NLog.LogLevel.Info; // raise it in chatty processesThe viewer uses the host application's theme (for example FluentTheme) and needs no theme reference of its own.
Custom UI — BGLogViewBuffer is the same bounded, thread-safe buffer the viewers use, and is available from BAUERGROUP.Shared.Core alone:
using BAUERGROUP.Shared.Core.Logging;
using NLog;
using System.Collections.Generic;
List<BGLogRecord> lines = new List<BGLogRecord>(); // the list your view is bound to
using var buffer = new BGLogViewBuffer(maxLines: 5000, minimumLevel: LogLevel.Info);
buffer.Attach(); // registers the live sink; Detach()/Dispose() removes it
// On the thread that owns your view, e.g. from a timer:
BGLogViewUpdate update = buffer.Drain();
if (update.IsReset)
lines.Clear();
else if (update.RemoveFromStart > 0)
lines.RemoveRange(0, update.RemoveFromStart);
foreach (BGLogRecord record in update.Added)
lines.Add(record); // record.DisplayText is "HH:mm:ss.fff LEVEL message"For a source that is not a list view, register a callback directly:
// The callback runs on the logging thread inside NLog's target lock: it must return immediately
// and must not block, must not log, and must not dispose the registration it belongs to.
using IDisposable registration = BGLogger.Configuration.AddLiveSink(record => queue.Enqueue(record),
LogLevel.Info);
int openSinks = BGLogger.Configuration.LiveSinkCount; // 0 means no live target is configuredusing BAUERGROUP.Shared.Data.EmbeddedDatabase;
// Create a thread-safe, persistent key-value dictionary backed by SQLite
using var storage = new ConcurrentPersistentDictionary<string, MyData>(
dataStorageDirectory: @"C:\Data",
databaseName: "MyDatabase",
tableName: "MyTable"
);
// Store and retrieve data
storage.Create("key1", new MyData { Name = "Example" });
var data = storage.Read("key1");
bool exists = storage.Exists("key1");
storage.Delete("key1");
// Read all entries
var allData = storage.Read();
var allWithKeys = storage.ReadWithKeys();using BAUERGROUP.Shared.Desktop.Browser;
// Show embedded Chrome browser window (non-blocking)
WPFToolboxBrowser.ChromeEmbeddedWebbrowserWindow(
title: "Web View",
url: "https://example.com",
owner: this,
wait: false
);
// Show browser and wait for it to close (modal dialog)
WPFToolboxBrowser.ChromeEmbeddedWebbrowserWindow(
title: "Web View",
url: "https://example.com",
owner: this,
wait: true
);
// Take a screenshot of a website
await WPFToolboxBrowser.MakeWebsiteScreenshot(
"https://example.com",
"screenshot.png"
);- .NET 10.0, .NET 8.0, or .NET Standard 2.0 compatible runtime
- Windows (for Desktop packages:
Desktop,Desktop.Browser,Desktop.Reporting) - Windows, Linux (X11/Wayland) or macOS for
BAUERGROUP.Shared.Avalonia— it targets plainnet10.0/net8.0and needs no-windowsTFM
- Stimulsoft License - Required for
BAUERGROUP.Shared.Desktop.Reporting - Sentry Account - For error tracking integration
BAUERGROUP.Shared/
├── src/
│ ├── BAUERGROUP.Shared.Core/ # Core utilities & logging
│ ├── BAUERGROUP.Shared.Data/ # Data persistence layer
│ ├── BAUERGROUP.Shared.API/ # Generic REST API client
│ ├── BAUERGROUP.Shared.Cloud/ # Cloud service integrations
│ ├── BAUERGROUP.Shared.Avalonia/ # Cross-platform UI (live log viewer)
│ ├── BAUERGROUP.Shared.Desktop/ # WPF/WinForms utilities
│ ├── BAUERGROUP.Shared.Desktop.Browser/ # Embedded browser
│ └── BAUERGROUP.Shared.Desktop.Reporting/ # Reporting components
├── tests/
│ ├── BAUERGROUP.Shared.Avalonia.Test/ # Avalonia headless UI tests
│ └── BAUERGROUP.Shared.Test/ # Unit tests
├── assets/ # Application icons
├── docs/
│ ├── BUILD.md # Build documentation
│ ├── DEPENDENCY-LICENSES.md # License analysis
│ ├── DOCUMENTATION-PLATFORM-SPEC.md # Platform specification
│ ├── INSTALLATION.md # Installation guide
│ └── VERSIONING.md # Version management
├── CHANGELOG.md # Version history
├── Directory.Build.props # Shared build configuration
├── Directory.Packages.props # Central package management
└── BAUERGROUP.Shared.slnx # Solution file
- .NET 10 SDK (includes support for .NET 8 and earlier)
- Visual Studio 2022 (17.12+) or JetBrains Rider 2024.3+
# Clone the repository
git clone https://github.com/bauer-group/LIB-Shared-NET.git
cd LIB-Shared-NET
# Restore dependencies
dotnet restore
# Build solution
dotnet build
# Run tests
dotnet testdotnet pack --configuration ReleasePackages will be output to bin/Release/*.nupkg
The library uses NLog for logging. Configuration is done programmatically via BGLogger.Configuration:
// Available logging targets (can be enabled/disabled at runtime)
BGLogger.Configuration.File = true; // File logging (default: enabled)
BGLogger.Configuration.Console = true; // Console output
BGLogger.Configuration.ConsoleColored = true; // Colored console output
BGLogger.Configuration.Network = true; // NLog Network target (UDP)
BGLogger.Configuration.NLogViewer = true; // NLog Viewer (Log4J XML format)
BGLogger.Configuration.Memory = true; // In-memory log storage
BGLogger.Configuration.Debugger = true; // VS Debugger output
BGLogger.Configuration.Eventlog = true; // Windows Event Log (.NET only)
BGLogger.Configuration.ErrorTracking = true; // Sentry integration
// In-process live sink: hands every event to a callback in the same process.
// Reference counted - the "LIVE" target and its rule exist only while a sink is registered.
using IDisposable liveSink = BGLogger.Configuration.AddLiveSink(record => Show(record.DisplayText));
int openSinks = BGLogger.Configuration.LiveSinkCount;The live sink is what the log viewers are built on — see Live Log Viewer (Avalonia) above, and WPFToolbox.LogMessageReceiverWindow() in BAUERGROUP.Shared.Desktop for WPF. It replaces the UDP round trip the old viewer used: BGLoggerNetworkListener and TextBoxTraceListener are [Obsolete] and will be removed in a future major version.
The target name LIVE is reserved for this sink — NLog replaces a same-named target silently, so do not add your own target called LIVE to BGLogger.Configuration.Targets.
What changed for the WPF viewer in 4.0.0: it no longer opens a UDP socket on port 9898 and no longer switches BGLogger.Configuration.Network on (which the previous version never switched off again). It shows the process's own events with a local HH:mm:ss.fff LEVEL message layout instead of the UTC file layout, keeps a rolling 5 000 lines instead of wiping the whole view past 1 000, and adds level colours, selection with copy, and a Follow toggle.
Sentry error tracking is integrated via the official Sentry.NLog package:
// Configure Sentry (must set DSN before enabling ErrorTracking)
BGLogger.Configuration.SentryDsn = "https://...@sentry.io/...";
BGLogger.Configuration.SentryEnvironment = "production";
BGLogger.Configuration.SentryMinimumEventLevel = NLog.LogLevel.Error;
BGLogger.Configuration.SentryMinimumBreadcrumbLevel = NLog.LogLevel.Debug;
// Offline cache (enabled by default): unsent reports survive network failures and process exit
BGLogger.Configuration.SentryCacheDirectoryPath = "/custom/ErrorReports"; // null or "" disables the cache
BGLogger.Configuration.SentryMaxCacheItems = 50; // oldest report is dropped beyond this
BGLogger.Configuration.SentryInitCacheFlushTimeout = TimeSpan.Zero; // start never waits for the cache
BGLogger.Configuration.ErrorTracking = true;Features:
- Automatic integration with NLog pipeline
- Breadcrumbs, context, and event capture
- User tracking with Windows identity
- Tags for ApplicationName, MachineName, ProcessName
- Offline cache: reports are written to disk before sending and sent on the next start if they could not be delivered. A cache folder that cannot be created disables the cache with a logged warning; reporting continues online.
The standalone BGErrorTracking.Init(dsn) API uses the same defaults via BGErrorTracking.Configuration.CacheDirectoryPath, MaxCacheItems and InitCacheFlushTimeout.
Settings stores, the embedded database, the default log directory and the Sentry offline cache all live below one application data folder. <App> is the entry assembly name (also correct in single-file applications); <ApplicationName> is BGLoggerConfiguration.ApplicationName, which defaults to the same value.
| What | Windows | Linux / macOS |
|---|---|---|
Data folder (ApplicationFolders.ExecutionAutomaticApplicationDataFolder) |
%ProgramData%\<App> |
/var/lib/<App> if that directory exists, otherwise ~/.local/share/<App> (per user) |
Data folder with BAUERGROUP_ROAMINGAPPLICATIONDATA=TRUE |
%APPDATA%\<App> |
~/.config/<App> |
Default log directory (BGLoggerConfiguration.LogDirectory) |
%ProgramData%\<ApplicationName>\Logging (always, see note) |
<data folder>/Logging |
| Log files | <ApplicationName>.log; daily archives <ApplicationName>_yyyy-MM-dd_00.log, 30 kept |
same |
| Sentry offline cache | <data folder>\ErrorReports |
<data folder>/ErrorReports |
Windows log directory: it deliberately keeps its historical location so installed stations do not move their logs. It is named after ApplicationName (not the executable) and ignores BAUERGROUP_ROAMINGAPPLICATIONDATA, so with the variable set, settings live in %APPDATA% while logs stay in %ProgramData%. Set BGLoggerConfiguration.LogDirectory explicitly to place logs elsewhere.
Linux stations: /usr/share (what .NET reports as CommonApplicationData) is never used, because normal users cannot write there. For one shared folder per station, let the installer create /var/lib/<App> with the owner the application runs as, e.g. install -d -o <user> /var/lib/<App> or systemd StateDirectory=<App>. Without it, each OS user gets their own folder. Folders are resolved without being created; stores and the logger create them on first write.
This project uses various open-source packages. See DEPENDENCY-LICENSES.md for a complete license analysis.
| Package | License | Notes |
|---|---|---|
| NLog | BSD 3-Clause | Logging framework |
| Avalonia | MIT | Cross-platform UI framework |
| CefSharp | BSD 3-Clause | Chromium browser |
| Sentry | MIT | Error tracking |
| Stimulsoft | Proprietary | Requires separate license |
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Microsoft's C# Coding Conventions
- Use meaningful names for variables, methods, and classes
- Write XML documentation for public APIs
- Include unit tests for new functionality
For questions or issues:
- Internal: Contact BAUER GROUP Development Team
- GitHub Issues: Report an issue
This project is licensed under the MIT License - see the LICENSE file for details.
Note: Some dependencies (Stimulsoft) require separate commercial licenses. See DEPENDENCY-LICENSES.md for details.
BAUER GROUP - Building Better Software Together