使用命名管道的 WCF 服务在从共享目录托管时导致阻塞线程

WCF Service using named pipes causes blocking thread when hosted from shared directory

我正在构建一个 Web 应用程序,其中包含一个带有命名管道端点的内部自托管 WCF 服务。这很好用,除非我想在 IIS 上托管此 Web 应用程序,使用共享的 UNC 虚拟路径('\server\share')结合物理路径凭据。 每当我尝试 运行 这种情况时,我都会收到错误消息:

Error: System.ServiceModel.EndpointNotFoundException: 'There was no endpoint listening at net.pipe://localhost/futurama/pid4988/instance2 that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.'
    AddressAccessDeniedException: The pipe name could not be obtained for net.pipe://localhost/futurama/pid4988/instance2.
    PipeException: The pipe name could not be obtained for the pipe URI: Unrecognized error 5 (0x5)

怀疑这是 credentials/rights-issue,但我不知道如何修复它。有人有想法吗?

我已经在一个示例中简化了问题,每当我启动这个示例时,线程就会阻塞,并且该进程使用了​​ 25% 的处理器。

Global.asax 文件:

public class Global : System.Web.HttpApplication
{
    public static ClientProvider<ITestService> Provider { get; set; }

    protected void Application_Start(object sender, EventArgs e)
    {
        Provider = new ClientProvider<ITestService>(typeof(TestService));

        using (var client = Provider.GetClient())
        {
            string result = client.Proxy.SayHello("world");

            // this is never reached :(
        }
    }

    protected void Application_End(object sender, EventArgs e)
    {
        Provider.Dispose();
    }
}

内部服务:

[ServiceContract]
public interface ITestService
{
    [OperationContract]
    string SayHello(string name);
}

public class TestService : ITestService
{
    public string SayHello(string name)
    {
        return string.Format("Hello, {0}", name);
    }
}

自托管class:

public class ClientProvider<T> : IDisposable
{
    protected ServiceHost ServiceHost { get; set; }

    public string Address { get; protected set; } = "net.pipe://localhost/test/instance";

    public ClientProvider(Type implementingType)
    {
        ServiceHost = new ServiceHost(implementingType);
        System.ServiceModel.Channels.Binding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
        ServiceHost.AddServiceEndpoint(typeof(T), binding, Address);
        ServiceHost.Open();
    }

    internal Client<T> GetClient()
    {
        var client = new Client<T>(this, Address.ToString());

        return client;
    }

    internal void Close()
    {
        ServiceHost.Close();
    }

    public void Dispose()
    {
        Close();
    }
}

提供代理的客户端:

public class Client<T> : IDisposable
{
    public T Proxy { get; protected set; }

    protected ChannelFactory<T> Factory { get; set; }

    protected ClientProvider<T> Provider { get; set; }        

    internal Client(ClientProvider<T> provider, string address)
    {
        Provider = provider;

        System.ServiceModel.Channels.Binding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);

        EndpointAddress endpointAddress = new EndpointAddress(address);
        Factory = new ChannelFactory<T>(binding, endpointAddress);
        Proxy = Factory.CreateChannel();
    }

    public void Dispose()
    {
        IClientChannel channel = Proxy as IClientChannel;
        try { channel.Close(); }
        catch { channel.Abort(); }
        try { Factory.Close(); }
        catch { Factory.Abort(); }
    }
}

有人知道为什么带有 UNC 虚拟路径的 IIS 会搞砸吗?

最后,我们解决了这个问题 bij 设置 Impersonationcontext 以暂时撤消任何模拟:

WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();
if (!currentIdentity.IsSystem && currentIdentity.ImpersonationLevel == TokenImpersonationLevel.Impersonation)
{
    impersonationContext = WindowsIdentity.Impersonate(IntPtr.Zero);   //revert to previous identity (apppool identity)
}

这似乎解决了我们的问题。