Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

some windows 10 and windows 11 clients can't connect to the PipeServer if hosted in a service #14

Closed
PeterPann23 opened this issue Mar 4, 2022 · 17 comments

Comments

@PeterPann23
Copy link

I have a service that would need to accept client data that runs without elevated permissions
I use this code

_server = new PipeServer<T>(pipeName, new NewtonsoftJsonFormatter());
_server.AllowUsersReadWrite();

My developer machine can connect just fine, some other machines however can't. If I take the NuGet package where I wrapped the PipeServer and PipeClient in and create a chat app using Winforms that same machine accepts the client without any issues, both are .net 6.0

If I take the Production client and have it connect to the Winforms test service all seems to work well.

The only difference is that one is hosted in service, the other is in a normal WinForms, with no changes made to the machines that are being problematic.

What am I doing wrong, how can I solve the issue?

@HavenDV
Copy link
Owner

HavenDV commented Mar 4, 2022

Hello. I want to note that the code in the service runs with administrator rights. However, if you run pipeServer in a normal application, it also needs administrator rights to work correctly

@HavenDV
Copy link
Owner

HavenDV commented Mar 5, 2022

You may also need to set up more advanced permissions.

AllowUsersReadWrite makes this easy for the easy case

public static void AllowUsersReadWrite<T>(this IPipeServer<T> server)
{
    server = server ?? throw new ArgumentNullException(nameof(server));

    server.AddAccessRules(
        new PipeAccessRule(
            new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null),
            PipeAccessRights.ReadWrite,
            AccessControlType.Allow));
}

@PeterPann23
Copy link
Author

PeterPann23 commented Mar 5, 2022

I have the service running as administrator, however, it doesn't accept a connection, is there a way to "trace" the accept/ deny access as I have no luck in the windows event logs and not on any of the events.

Remember, the same class that hosts the service is used in a winforms app and runs without any issues, same users same pc.

@HavenDV
Copy link
Owner

HavenDV commented Mar 6, 2022

image

I'm not experienced with tracking down problematic connections. Here, the system class has a rather meager API. I only use WaitForConnectionAsync to wait for new clients.

@HavenDV
Copy link
Owner

HavenDV commented Mar 6, 2022

Another idea: perhaps you have some kind of resource cleanup problem (because Dispose is required after pipes is finished), and when creating a new server inside the service, an exception is thrown that the name is already taken? Try to subscribe to all events that the server issues and log them

@PeterPann23
Copy link
Author

I wrote a small test-rig allowing you to get some code to reproduce ... the issue is that the test works on the client machines... there must be a difference not sure where... the sample code I generated

Not sure if my code is "standard"

BackgroundWorker2022030712.txt
ClientLog20220307.txt
NamedPipeSandbox Code.zip

@PeterPann23
Copy link
Author

PeterPann23 commented Mar 11, 2022

looks like, depending on the frameworks installed on the target machines the code fails.
Looking at NamedPipeServerStream I see a lot of code that is obsolete and no longer executes as it's simply ignored, the conditional compilers force Net 6.0 to execute in a not 2.1 as .net is not net6.0 going to a lower framework, perhaps consider 6.0 and 7.0 support

#if NETSTANDARD2_1 

#else 

#endif

Also, some code that only executes on windows is interweaved with platform generic code making it windows only.

@HavenDV
Copy link
Owner

HavenDV commented Mar 11, 2022

I met some issues with .Net 6 and .Net Standard. I can try adding an explicit .Net 6 TargetFramework and see if that gives the desired result.

@HavenDV
Copy link
Owner

HavenDV commented Mar 11, 2022

image

While adding, I noticed that this API is only available on Windows

@PeterPann23
Copy link
Author

Perhaps also have a look at public async Task StartAsync(CancellationToken cancellationToken = default)
in PipeServer.cs it is not communicating the exceptions to the hosting application

@HavenDV
Copy link
Owner

HavenDV commented Mar 11, 2022

Perhaps also have a look at public async Task StartAsync(CancellationToken cancellationToken = default)
in PipeServer.cs it is not communicating the exceptions to the hosting application

It transmits, but only through an ExceptionOccurred event, because it starts a Worker inside to process incoming signals.

@PeterPann23
Copy link
Author

I met some issues with .Net 6 and .Net Standard. I can try adding an explicit .Net 6 TargetFramework and see if that gives the desired result.

Perhaps NET6_0_OR_GREATER

@HavenDV
Copy link
Owner

HavenDV commented Mar 11, 2022

Perhaps also have a look at public async Task StartAsync(CancellationToken cancellationToken = default)
in PipeServer.cs it is not communicating the exceptions to the hosting application

It will also explicitly throw an exception if it fails to create a server

@PeterPann23
Copy link
Author

Perhaps also have a look at public async Task StartAsync(CancellationToken cancellationToken = default)
in PipeServer.cs it is not communicating the exceptions to the hosting application

It transmits, but only through an ExceptionOccurred event, because it starts a Worker inside to process incoming signals.
Perhaps consider the order ...

catch (Exception exception)
{
       if (WaitFreePipe)
       {
               throw;
         }

         source.TrySetException(exception);
         break;
 }

@HavenDV
Copy link
Owner

HavenDV commented Mar 11, 2022

source.TrySetException(exception);

These exceptions will be received here:

try
{
await source.Task.ConfigureAwait(false);
}
catch (Exception)
{
await StopAsync(cancellationToken).ConfigureAwait(false);
throw;
}

@HavenDV
Copy link
Owner

HavenDV commented Mar 11, 2022

Perhaps NET6_0_OR_GREATER

https://docs.microsoft.com/en-us/dotnet/standard/library-guidance/cross-platform-targeting
I studied this article again, it still doesn't make sense to add explicit .Net 5/6 targets here, because we don't use specific APIs in them (they implement .Net Standard 2.1).
The only plus from their explicit presence is new warnings and nullable markup in dependent libraries

@HavenDV
Copy link
Owner

HavenDV commented Mar 11, 2022

However, I've added explicit .Net 5/.Net 6 frameworks (for the ability to call the OperatingSystem.IsWindows() method) to test for the ability to call WaitForPipeDrain. Please check your problem when the new version becomes available on NuGet (in about 10 minutes)

@HavenDV HavenDV closed this as completed Mar 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants