-
Notifications
You must be signed in to change notification settings - Fork 0
Services
SimpleXisoDrive ships with a set of supporting services for logging, diagnostics, telemetry, and update checks. This page documents each one and where its output ends up.
LoggingSetup.ConfigureLogger() builds the global Serilog logger. It is called once at startup.
| Setting | Value |
|---|---|
| Minimum level | Debug |
| Console sink | Output template [{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}, color theme None
|
| File sink |
logs/simplexisodrive-.log next to the executable, rolling daily, 7 files retained |
| File template | {Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception} |
| Bug report sink | Attached for Warning and above |
If logger configuration itself throws, the application continues with no logging rather than failing to start.
| File | Format | Contents |
|---|---|---|
logs\simplexisodrive-YYYYMMDD.log |
Serilog text | Everything from Debug level up |
error.log |
Bug report blocks | Warning level and above, plus fatal exceptions |
critical_error.log |
Plain text | Failures inside the logging/reporting pipeline itself |
All paths are relative to the directory containing SimpleXisoDrive.exe.
[HH:mm:ss INF] === SimpleXisoDrive Started ===
[HH:mm:ss INF] Arguments: D:\Games\Halo.iso | Z: | -l
[HH:mm:ss DBG] Resolved 'D:\Games\Halo' to 'D:\Games\Halo.iso'
[HH:mm:ss INF] Mount successful: 'D:\Games\Halo.iso' -> 'Z:'
[HH:mm:ss INF] Unmount signal received. Cleaning up...
[HH:mm:ss INF] Unmounted.
ApiKeyProvider supplies the shared API key for the bug report and stats endpoints. The key is
never stored in plain text: two independent layers protect it in the assembly (an AES-256-CBC
outer layer over a SHA-256 XOR inner layer), and Preload() decrypts it once during startup.
Decryption failures are logged at Error level and disable remote reporting without affecting the
mount.
SerilogDokanLogger implements DokanNet.Logging.ILogger and forwards Dokan's internal messages to
Serilog:
| Dokan method | Serilog level |
|---|---|
Debug |
Debug |
Info |
Information |
Warn |
Warning |
Error |
Error |
Fatal |
Fatal |
DebugEnabled mirrors Log.IsEnabled(LogEventLevel.Debug) so Dokan can skip formatting when debug
logging is off.
DokanInstallation.Check() probes %SystemRoot%\System32\dokan2.dll (the user-mode runtime) and
%SystemRoot%\System32\drivers\dokan2.sys (the driver), printing installation guidance to the
console and returning a DokanInstallationStatus:
| Status | Meaning | Startup behavior |
|---|---|---|
Installed |
Library and driver present | Mounting proceeds |
DriverMissing |
Library present, driver missing | A warning is printed, then the download offer is shown; mounting still proceeds |
RuntimeMissing |
Library missing | Guidance is printed, then the download offer is shown, and the application exits |
Unknown |
The probe itself failed (for example an I/O or ACL error) | No download offer; mounting proceeds and may fail later |
DokanDownloadPrompt.OfferDownload(component) warns that a component is missing and offers to open
the Dokan releases page (https://github.com/dokan-dev/dokany/releases) in the default browser via
a native WindowsMessageBox Yes/No dialog. Non-interactive runs (scripts, scheduled tasks, CI)
never show a modal window: the URL is printed to standard error instead. These conditions are
logged at Information level and are not forwarded to the bug report API.
BugReport is the local and remote reporting pipeline for warnings, errors, and crashes.
BuildReport produces a text report with three sections:
- Environment details - date/time with offset, application name and version, OS description, OS and process architecture, process/OS bitness, operating system name and version string, processor count, base directory, and temp path.
- Error details - severity level and message.
-
Exception details - type, message, source, and stack trace (or
Noneplaceholders).
| Method | Destination | Behavior |
|---|---|---|
WriteLocalErrorLog(report) |
error.log |
Appends the report plus a separator, protected by a lock. Failure falls back to the critical log. |
LogFatalException(ex, context) |
error.log + console |
Prints --- CRITICAL CRASH ---, writes the report, and starts a fire-and-forget API submission. |
WriteToCriticalLog(...) (private) |
critical_error.log |
Last-resort logging when the normal pipeline fails. |
SendToApiAsync posts the report as JSON to the configured endpoint. The payload contains:
| Field | Value |
|---|---|
message |
The rendered report text |
applicationName |
SimpleXisoDrive |
version |
Assembly version |
userInfo |
Environment.UserName |
environment |
OS description and architecture |
stackTrace |
Exception ToString() or No exception attached.
|
The request carries an API key header and uses a 30-second timeout. Non-success responses and
exceptions are written to critical_error.log. The static HttpClient is disposed automatically
on process exit (ProcessExit). All API clients (bug report, stats, update check) are created by
the shared ApiHttpClientFactory, which reuses one connection pool and TLS configuration.
| Trigger | Path |
|---|---|
| Serilog event at Warning level or higher | BugReportSink.Emit |
| Unhandled exception on the main thread |
AppDomain.UnhandledException -> LogFatalException
|
| Unobserved task exception |
TaskScheduler.UnobservedTaskException -> LogFatalException
|
Update checker network failures are deliberately logged at Information level only and are not
forwarded. Expected user-setup and input conditions are likewise kept below the threshold and not
reported: a missing Dokan runtime or driver (DokanInstallation, DokanDownloadPrompt), a missing
FUSE library (FuseAvailability), missing image files, invalid images, a failed
explorer.exe/xdg-open launch, and a failed FUSE session setup (FuseFileSystem). Lookup misses
for paths that do not exist in the mounted image (XisoVfsVolume) are also kept below the
threshold. See Privacy and Networking for the full data-flow description.
Remote reports are tracked while in flight (BugReport.PendingReports), and both front ends call
BugReport.WaitForPendingReportsAsync(TimeSpan.FromSeconds(5)) during shutdown so a clean exit does
not cut off a report that is already being sent.
BugReportSink is a Serilog sink that connects the logging pipeline to BugReport.
| Property | Behavior |
|---|---|
| Threshold | Attached at Warning; ignores lower levels |
| Rate limit | Maximum 8 reports per minute per process (the API permits 10) |
| Local output | Every accepted report is appended to error.log
|
| Remote output | Tracked background send (SendTrackedAsync); shutdown can wait for it via WaitForPendingReportsAsync
|
| Failure policy | All exceptions are swallowed; a sink must never break logging |
Rate limiting uses a static queue of timestamps, trimmed to a one-minute window.
CheckAccess.IsAdministrator() uses WindowsIdentity.GetCurrent() and WindowsPrincipal.IsInRole
with WindowsBuiltInRole.Administrator.
- Returns
truewhen the process is elevated. - Returns
falseon non-Windows or on any exception (the failure is logged at Error level).
The result controls two behaviors:
-
Dokan options -
MountManageris enabled only for elevated processes. - Console warning - mounting a drive letter without administrator rights prints a hint.
StatsService.ReportLaunch() reports an anonymous launch event. It is fire-and-forget and never
blocks startup, but the request is tracked so shutdown can wait briefly for it
(StatsService.WaitForPendingReportAsync). The internal ReportLaunchAsync(HttpClient) overload
is the awaitable, testable core and skips the request when no API key is available.
| Property | Value |
|---|---|
| Method | POST |
| Endpoint | https://www.purelogiccode.com/ApplicationStats/stats |
| Authentication |
Bearer token header |
| Payload | { "applicationId": "simplexisodrive", "version": "<assembly version>" } |
| Timeout | 10 seconds |
| Failure handling | Timeouts, connection failures, and other errors are logged at Debug level and ignored (never forwarded to the bug report API) |
No user, machine, or file information is included in this request.
UpdateChecker.CheckForUpdateAsync() queries the GitHub releases API immediately at startup, before
argument handling and mounting. When a newer release exists the user is notified and asked whether
to open the download page. The front end supplies the user prompt: Windows uses a native message
box, Unix uses the console prompt.
| Step | Detail |
|---|---|
| Request |
GET https://api.github.com/repos/purelogiccode/SimpleXisoDrive/releases/latest with User-Agent: SimpleXisoDrive-UpdateChecker
|
| Timeout | 5 seconds |
| Parsing | Extracts tag_name and html_url, then matches \d+\.\d+\.\d+ (1-second regex timeout) |
| Comparison | Newer than the entry assembly version wins |
| Prompt (Windows) | Native message box (WindowsUpdatePrompt.ConfirmOpenRelease) showing current/latest versions and asking whether to open the release page; Yes opens the browser |
| Prompt (Unix) | Console prompt: Open the release page in your browser? [Y/n]; pressing n/N cancels |
| Non-interactive runs | The prompt is always skipped when input/output is redirected or the process has no interactive session: the version details and download URL are printed instead, so scripts and scheduled tasks can never block on a dialog (on Windows a modal message box would otherwise wait indefinitely) |
| Browser launch | Uses the default browser via shell execute |
| Failure handling | Logged at Information level only and never forwarded to the bug report API |
flowchart LR
App["Application code"] -->|Serilog API| Log["Serilog logger"]
Log --> Console["Console sink"]
Log --> File["Rolling file sink"]
Log -->|Warning+| Sink["BugReportSink"]
Sink --> Local["error.log"]
Sink -->|fire-and-forget| API["Bug report API"]
Crash["Fatal handlers"] --> BugReport["BugReport.LogFatalException"]
BugReport --> Local
BugReport --> API
Startup["Startup"] --> Stats["StatsService"]
Startup --> Update["UpdateChecker"]
Stats --> Api2["Stats API"]
Update --> GitHub["GitHub releases API"]
User guide
Technical reference
Development
Project