Table of Contents

Logging

The wrapper is silent by default — zero overhead when no logger is configured. Three overloads of Attach and LaunchWithSso accept a logger:

Overload When to use
Attach() / LaunchWithSso(system) No logging needed
Attach(ILogger) / LaunchWithSso(system, logger:) ASP.NET Core DI, Serilog/NLog via MEL adapter
Attach(SapLogAction) / LaunchWithSso(system, logAction:) UiPath Log(), Serilog static Log, console — no MEL dependency

Log levels emitted

Level Events
Debug Every FindById / FindByIdDynamic call with component path
Information StartTransaction, ExitTransaction, session open/close, LaunchWithSso progress, popup dismissed
Warning Popup detected, retry attempt, WaitReady/WaitForReadyState near timeout
Error All thrown exceptions before they propagate

UiPath — route SAP logs to UiPath's Log() action

No dependency on Microsoft.Extensions.Logging is needed in your workflow:

// All levels
using var sap = SapGuiClient.Attach(
    logAction: (level, msg, ex) => Log(
        $"[SAP/{level}] {msg}",
        level switch
        {
            SapLogLevel.Error   => LogLevel.Error,
            SapLogLevel.Warning => LogLevel.Warn,
            SapLogLevel.Debug   => LogLevel.Trace,
            _                   => LogLevel.Info,
        }));
// Warning and Error only — less noise in production
using var sap = SapGuiClient.Attach(
    logAction: (level, msg, ex) => Log($"[SAP/{level}] {msg}"),
    minLevel: SapLogLevel.Warning);
// With LaunchWithSso (unattended jobs)
using var sap = SapGuiClient.LaunchWithSso(
    "PRD - Production",
    reuseExistingSession: true,
    logAction: (level, msg, ex) => Log(
        $"[SAP/{level}] {msg}",
        level switch
        {
            SapLogLevel.Error   => LogLevel.Error,
            SapLogLevel.Warning => LogLevel.Warn,
            SapLogLevel.Debug   => LogLevel.Trace,
            _                   => LogLevel.Info,
        }),
    minLevel: SapLogLevel.Warning);

ASP.NET Core / Serilog / NLog (via MEL adapter)

// ILogger injected by DI or created via LoggerFactory
using var sap = SapGuiClient.Attach(logger);

// With LaunchWithSso
using var sap = SapGuiClient.LaunchWithSso("PRD - Production", logger: logger);

Serilog static Log class (no MEL adapter)

using var sap = SapGuiClient.Attach(logAction: (level, msg, ex) =>
    Serilog.Log.Write(
        level switch
        {
            SapLogLevel.Debug   => Serilog.Events.LogEventLevel.Debug,
            SapLogLevel.Warning => Serilog.Events.LogEventLevel.Warning,
            SapLogLevel.Error   => Serilog.Events.LogEventLevel.Error,
            _                   => Serilog.Events.LogEventLevel.Information,
        },
        ex, "{SapMessage}", msg));

Console (quick debugging)

using var sap = SapGuiClient.Attach(
    logAction: (level, msg, ex) =>
        Console.WriteLine($"[{level}] {msg}{(ex is null ? "" : " – " + ex.Message)}"));

API surface

SapLogLevel, SapLogAction, and all Attach/LaunchWithSso overloads are public. The internal SapLogger bridge translates between the delegate and ILogger<T> so only Microsoft.Extensions.Logging.Abstractions (v8.0.0) is needed as a dependency — no concrete provider is pulled in.