1. Setup The Plagues Protocol
Preparing Your Environment
For this example, let's copy the format of Plagues Protocol
- Download Pariah Cybersecurity's DLL from Here
- Install MagicOnion
Setup The Projects
- Create A Service Worker from templates (Ensuring it's the one which supports Windows/Linux and others) and name it XRUIOS.Windows.PublicAccountDataHandler, then create another named XRUIOS.Linux.PublicAccountDataHandler
These will be our service workers (As the name suggests)
- Create A .DLL Project Named XRUIOS.Windows and a second named XRUIOS.Linux
These will be the DLLs responsible for platform specific code
- Create a .DLL Project Named XRUIOS.Interfaces
This will contain shared definitions between platforms and the main core
- Create a .DLL Named XRUIOS.Core
This will contain cross platform code and the code responsible for selecting between XRUIOS.Windows or XRUIOS.Linux at runtime
- (Optional) For testing, create a CMD Project Named XRUIOS Arch Test
A simple test site for CMD related issues
Connecting Dependencies
| Project | Dependencies To Add | Project Refs To Add |
|---|---|---|
| XRUIOS.Windows. PublicAccountDataHandler |
- Pariah Cybersecurity - Magic Onion |
-XRUIOS.Windows -XRUIOS.Interface |
| XRUIOS.Linux.PublicAccountDataHandler | - Pariah Cybersecurity - Magic Onion |
-XRUIOS.Linux -XRUIOS.Interface |
| XRUIOS.Windows | - Pariah Cybersecurity - Magic Onion |
-XRUIOS.Interfaces |
| XRUIOS.Linux | - Pariah Cybersecurity - Magic Onion |
-XRUIOS.Interfaces |
| XRUIOS.Interfaces | - Pariah Cybersecurity - Magic Onion |
|
| XRUIOS.Core | - Pariah Cybersecurity | -XRUIOS.Windows -XRUIOS.Linux |
Creating Your First Worker
1. Create the Shared Interface (XRUIOS.Interfaces)
This is the only contract that crosses the Plagues boundary.
// XRUIOS.Interfaces/IPublicAcc.cs
using MagicOnion;
public interface IPublicAcc : IService<IPublicAcc>
{
UnaryResult<PublicAccount> GetAccInfo(string accountName);
}
// XRUIOS.Interfaces/PublicAccount.cs
using System.Runtime.Serialization;
[DataContract]
public struct PublicAccount
{
[DataMember] public string Name;
[DataMember] public string LastCheck;
[DataMember] public string OSFolder;
public PublicAccount(string name, string lastCheck, string osFolder)
{
Name = name; LastCheck = lastCheck; OSFolder = osFolder;
}
}
2. Create the Worker (Windows Example)
Project: XRUIOS.Windows.PublicAccountDataHandler (Worker Service template)
// Program.cs
using MagicOnion.Server;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using XRUIOS.Windows.PublicAccountDataHandler;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
options.ListenLocalhost(5000, o => o.Protocols = HttpProtocols.Http2);
// Later: switch to named pipe → options.ListenNamedPipe("xruios-publicacc");
});
builder.Services.AddHttpContextAccessor();
builder.Services.AddSingleton<Worker>();
builder.Services.AddHostedService<Worker>();
builder.Services.AddMagicOnion();
var app = builder.Build();
app.MapMagicOnionService<PublicAccService>();
app.Run();
// Worker.cs + PublicAccService
using MagicOnion;
using MagicOnion.Server;
using XRUIOS.Interfaces;
using Pariah_Cybersecurity;
using static Pariah_Cybersecurity.EasyPQC;
using System.Diagnostics;
namespace XRUIOS.Windows.PublicAccountDataHandler
{
public class PublicAccService : ServiceBase<IPublicAcc>, IPublicAcc
{
private readonly Worker _worker;
public PublicAccService(Worker worker) => _worker = worker;
public async UnaryResult<PublicAccount> GetAccInfo(string accountName)
=> await _worker.GetAccInfo(accountName);
}
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly IHttpContextAccessor _httpContext;
private readonly IServer _server;
public Worker(ILogger<Worker> logger, IHttpContextAccessor http, IServer server)
{
_logger = logger; _httpContext = http; _server = server;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await Start();
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Windows Plague alive: {time}", DateTimeOffset.Now);
await Task.Delay(1000, stoppingToken);
}
}
public async UnaryResult<PublicAccount> GetAccInfo(string accountName)
{
if (!await VerifyIntegrity2())
throw new Exception("Integrity Check 2 Failed");
var folder = $@"C:\Users\{accountName}\XRUIOS";
var lastCheck = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
_logger.LogInformation("[Windows] Served account: {name}", accountName);
return new PublicAccount(accountName, lastCheck, folder);
}
private async Task Start()
{
// Optional startup integrity
}
private async Task<bool> VerifyIntegrity2()
{
try
{
string exePath = Process.GetCurrentProcess().MainModule!.FileName;
byte[] hash;
using (var fs = new FileStream(exePath, FileMode.Open, FileAccess.Read))
hash = await FileOperations.HashFile(fs);
using (var fs = new FileStream(exePath, FileMode.Open, FileAccess.Read))
return await FileOperations.VerifyHash(fs, hash);
}
catch { return false; }
}
}
}
3. Create the Client Proxy (XRUIOS.Windows / XRUIOS.Linux)
// XRUIOS.Windows/Accounts.cs
using Grpc.Net.Client;
using MagicOnion.Client;
using XRUIOS.Interfaces;
namespace XRUIOS.Windows
{
public class Accounts
{
public async Task<PublicAccount?> GetAccData(string accountName)
{
var addr = Utils.SecureStore.Get<string>("worker_addr")
?? "https://localhost:5000";
using var channel = GrpcChannel.ForAddress(addr);
var client = MagicOnionClient.Create<IPublicAcc>(channel);
return await client.GetAccInfo(accountName);
}
}
}
Same for Linux — just change the fallback path
4. Cross-Platform Dispatcher (XRUIOS.Core)
// XRUIOS.Core/AccountsProvider.cs
using System.Runtime.InteropServices;
using XRUIOS.Interfaces;
#if WINDOWS
using XRUIOS.Windows;
#elif LINUX
using XRUIOS.Linux;
#endif
namespace XRUIOS.Core
{
public static class AccountsProvider
{
public static async Task<PublicAccount> GetPublicAcc(string username)
{
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? await new Windows.Accounts().GetAccData(username)
: await new Linux.Accounts().GetAccData(username)
?? throw new Exception("Failed to get account data");
}
}
}
5. Test Client (Console)
using XRUIOS.Core;
using XRUIOS.Interfaces;
var result = await AccountsProvider.GetPublicAcc(Environment.UserName);
Console.WriteLine($"Name: {result.Name}");
Console.WriteLine($"Folder: {result.OSFolder}");
Console.WriteLine($"Checked: {result.LastCheck}");