Skip to content

.NET 8 - Acces to the path is denied #99

@nk-alex

Description

@nk-alex

I'm developing a .NET Maui application for Android and Windows.

In the Windows application, I have a Windows BackgroundService doing some job with independence of the application state. My application and this BackgroundService should somehow communicate back and forth.

Since I don't have experience with Windows applications, I started searching documentation, and I found out about NamedPipes, and later, I found out about this wrapper that seems to make things easier.

So far, I tried these two scenarios:

First scenario

  • Debug on Visual Studio both my application and the Windows BackgroundService. I can successfully communicate back and forth.

Second scenario

  • Deploy my service on my computer and try to communicate from my application debugging on Visual Studio (on same computer).
  • For the Windows BackgroundService deploying part, I'm following this docs.
  • I can see my Windows BackgroundService running by Ctrl+Alt+Del and serching for its name.
  • Now the same code as before isn't working anymore. await client.ConnectAsync(); is throwing System.UnauthorizedAccessException in System.Private.CoreLib.dll ("Access to the path is denied.")

This is the code I'm using on both scenarios:

Windows BackgroundService:

public sealed class WindowsBackgroundService(VFService vfService, ILogger<WindowsBackgroundService> logger) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        PipeServer<PipeMessage> serverPipe = new PipeServer<PipeMessage>("01043009-CTPV_VF");
        logger.LogInformation("Server is awakening");
        serverPipe.ClientConnected += (o, args) => OnClientConnected(args);
        serverPipe.ClientDisconnected += (o, args) => OnClientDisconnected(args);
        serverPipe.MessageReceived += (sender, args) => OnMessageReceived(args.Message);
        serverPipe.ExceptionOccurred += (o, args) => OnExceptionOccurred(args.Exception);
        logger.LogInformation("Server pipe is UP");

        try
        {
            await serverPipe.StartAsync();
            logger.LogInformation("Server pipe is listening for connections now!");

            while (!stoppingToken.IsCancellationRequested)
            {
                await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
            }
        }
        catch (OperationCanceledException)
        {
            // When the stopping token is canceled, for example, a call made from services.msc,
            // we shouldn't exit with a non-zero exit code. In other words, this is expected...
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "{Message}", ex.Message);

            // Terminates this process and returns an exit code to the operating system.
            // This is required to avoid the 'BackgroundServiceExceptionBehavior', which
            // performs one of two scenarios:
            // 1. When set to "Ignore": will do nothing at all, errors cause zombie services.
            // 2. When set to "StopHost": will cleanly stop the host, and log errors.
            //
            // In order for the Windows Service Management system to leverage configured
            // recovery options, we need to terminate the process with a non-zero exit code.
            Environment.Exit(1);
        }
        finally
        {
            logger.LogInformation("Server has stopped");
            //await serverPipe.StopAsync();
        }
    }

    #region "  Server Pipe "
    private void OnClientConnected(ConnectionEventArgs<PipeMessage> args)
    {
        logger.LogInformation("New client connected");
    }

    private void OnClientDisconnected(ConnectionEventArgs<PipeMessage> args)
    {
        logger.LogInformation("Client disconnected");
    }

    private void OnMessageReceived(PipeMessage? message)
    {
        switch (message.Action)
        {
            case ActionType.SendText:
                logger.LogInformation($"Text from client: {message.Text}");
                break;

            case ActionType.ShowTrayIcon:
                throw new NotImplementedException();

            case ActionType.HideTrayIcon:
                throw new NotImplementedException();

            default:
                Console.WriteLine($"Unknown Action Type: {message.Action}");
                break;
        }
    }

    private void OnExceptionOccurred(Exception ex)
    {
        logger.LogInformation($"Exception occured in pipe: {ex}");
    }
    #endregion
}

My .NET Maui application:

Task.Run(async () =>
{
    try
    {
        await using var client = new PipeClient<PipeMessage>("01043009-CTPV_VF", reconnectionInterval:TimeSpan.FromSeconds(5));

        client.MessageReceived += (sender, args) => Debug.WriteLine(args.Message);
        client.Disconnected += (o, args) => Debug.WriteLine("Disconnected from server");
        client.Connected += (o, args) => Debug.WriteLine("Connected to server");
        client.ExceptionOccurred += (o, args) => Debug.WriteLine(args.Exception);

        await client.ConnectAsync();

        await client.WriteAsync(new PipeMessage
        {
            Action = ActionType.SendText,
            Text = "Hello from client",
        });
    }
    catch (Exception ex)
    {
        var tmp = ex;
    }
});

What I'm doing wrong?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions