使用 App.Config 在 Windows 服务中的 WCF 命名管道
Posted
技术标签:
【中文标题】使用 App.Config 在 Windows 服务中的 WCF 命名管道【英文标题】:WCF Named Pipe in Windows Service using App.Config 【发布时间】:2019-08-17 11:30:53 【问题描述】:我很沮丧。好的,这是错误。
在 net.pipe://localhost/MyIpcAppToService 上没有可以接受消息的端点侦听。这通常是由不正确的地址或 SOAP 操作引起的。有关详细信息,请参阅 InnerException(如果存在)。
我终于让 App.Config 文件工作了,至少没有抱怨。
当前 App.Config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
</startup>
<system.serviceModel>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="MyService.Communication.IpcAppToService">
<endpoint address="net.pipe://localhost/MyIpcAppToService" binding="wsDualHttpBinding" bindingConfiguration="MyAppToServiceEndpointBinding" contract="MyIpc.IIpcAppToService"/>
<endpoint address="mex" binding="mexHttpBinding" name="mex" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/MyService/"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add scheme="http" binding="wsHttpBinding" bindingConfiguration="MyAppToServiceEndpointBinding" />
</protocolMapping>
<bindings>
<wsDualHttpBinding>
<!-- https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/wcf/wshttpbinding -->
<binding name="MyAppToServiceEndpointBinding"
transactionFlow="true"
sendTimeout="00:01:00"
maxReceivedMessageSize="2147483647"
messageEncoding="Mtom">
</binding>
</wsDualHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
<baseAddressPrefixFilters>
<add prefix="http://localhost:8733"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
</system.serviceModel>
<appSettings>
<add key="countoffiles" value="7"/>
<add key="logfilelocation" value="abc.txt"/>
</appSettings>
</configuration>
我曾经有:
<endpoint address="http://localhost:8733/MyIpcAppToService" ...
在 Windows 服务OnStart()
事件中:
(从这个问题帖子开始,以下代码现在已被注释掉,因为App.config
文件应该启动 named.pipe。)
public Boolean CreatePipeServer()
string eventText = $"My Service: CommAppToService::CreatePipeServer(IPC App to Service)Environment.NewLine";
try
if (null != this.ServiceParent.HostIpcAppToService)
this.ServiceParent.HostIpcAppToService = null;
string pipeBaseAddress = @"net.pipe://localhost/MyIpcAppToService";
this.ServiceParent.HostIpcAppToService = new ServiceHost(typeof(IpcAppToService), new Uri(pipeBaseAddress));
NetNamedPipeBinding pipeBinding = new NetNamedPipeBinding()
//ReceiveTimeout = new TimeSpan(0, 0, 0, 0, Constants.My_TimeoutMsSendReceive),
//SendTimeout = new TimeSpan(0, 0, 0, 0, Constants.My_TimeoutMsSendReceive),
;
this.ServiceParent.HostIpcAppToService.AddServiceEndpoint(typeof(IIpcAppToService), pipeBinding, "MyIpcAppToService");
this.ServiceParent.HostIpcAppToService.UnknownMessageReceived += HostIpcAppServer_UnknownMessageReceived;
this.ServiceParent.HostIpcAppToService.Faulted += HostIpcAppServer_Faulted;
this.ServiceParent.HostIpcAppToService.Closing += HostIpcAppServer_Closing;
this.ServiceParent.HostIpcAppToService.Closed += HostIpcAppServer_Closed;
this.IpcAppToService = new IpcAppToService();
this.IpcAppToService.ApplyDispatchBehavior(this.ServiceParent.HostIpcAppToService);
this.IpcAppToService.Validate(this.ServiceParent.HostIpcAppToService);
this.ServiceParent.HostIpcAppToService.Open();
return true;
我读到该服务将自动启动放在App.Config
文件中的服务,实际上是MyExeName.exe.config
文件。我一直在查看代码,发现它几乎相同,所以我将 http://
替换为 net.pipe://
。
可悲的是,旧代码,新代码,在代码之间,什么都没有。我一直收到同样的错误。
我使用以下内容从我的桌面应用程序连接到服务。
public static Boolean ConnectToService()
try
var callback = new IpcCallbackAppToService();
var context = new InstanceContext(callback);
var pipeFactory = new DuplexChannelFactory<IIpcAppToService>(context, new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/MyIpcAppToService"));
Program.HostIpcAppToService = pipeFactory.CreateChannel();
Program.HostIpcAppToService.Connect();
CommAppToService.IsPipeAppToService = true;
return true;
catch (Exception ex)
// Log the exception.
Errors.LogException(ex);
return false;
不管它值多少钱,这里是:
界面
[ServiceContract(SessionMode = SessionMode.Allowed, CallbackContract = typeof(IIpcCallbackAppToService))]
public interface IIpcAppToService
[OperationContract(IsOneWay = false)]
[FaultContractAttribute(typeof(IpcAppToServiceFault))]
UInt16 GetServiceId();
...
服务:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class IpcAppToService : IIpcAppToService, IErrorHandler
public static IIpcCallbackAppToService Callback get; set; = null;
public void OpenCallback()
IpcAppToService.Callback = OperationContext.Current.GetCallbackChannel<IIpcCallbackAppToService>();
public void CloseCallback()
IpcAppToService.Callback = null;
public void SendMessage(string message)
//MessageBox.Show(message);
public UInt16 GetServiceId()
return Constants.My_Id_AppToService;
...
内部异常来自我的桌面 WinForms 应用程序 (注意,没有比这个更进一步的内部例外。):
“在您的本地计算机上找不到管道端点 'net.pipe://localhost/MyIpcAppToService'。”
为什么我总是看到这个错误?
第一次回答后更新
我想采取的方向与答案相反,但相同,即服务以App.config
开头,client
使用C#代码。
很遗憾,我仍然遇到同样的错误。
修订的服务器端 App.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
</startup>
<system.serviceModel>
<services>
<service behaviorConfiguration="BehaviorMyService" name="MyService.Communication.IpcAppToService">
<endpoint address="net.pipe://localhost/MyIpcAppToService"
binding="netNamedPipeBinding"
bindingConfiguration="EndpointBindingMyAppToService"
contract="MyIpc.IIpcAppToService"
/>
<endpoint address="mex" binding="mexHttpBinding" name="mex" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/MyService/"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="BehaviorMyService">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true"
httpsGetEnabled="true"
/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netNamedPipeBinding>
<!-- https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/wcf/wshttpbinding -->
<binding name="EndpointBindingMyAppToService"
closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:10:00"
sendTimeout="00:01:00"
transactionFlow="false"
transferMode="Buffered"
transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288"
maxBufferSize="65536"
maxConnections="10"
maxReceivedMessageSize="2147483647"
>
<security mode="None">
<transport protectionLevel="None" />
</security>
</binding>
</netNamedPipeBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
<baseAddressPrefixFilters>
<add prefix="http://localhost:8733"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
</system.serviceModel>
<appSettings>
<add key="countoffiles" value="7"/>
<add key="logfilelocation" value="abc.txt"/>
</appSettings>
</configuration>
修改客户端 C# 代码:
var callback = new IpcCallbackAppToService();
InstanceContext context = new InstanceContext(callback);
NetNamedPipeBinding binding = new NetNamedPipeBinding();
binding.Security.Mode = NetNamedPipeSecurityMode.None;
EndpointAddress endpointAddress = new EndpointAddress("net.pipe://localhost/MyIpcAppToService");
var pipeFactory = new DuplexChannelFactory<IIpcAppToService>(context, binding, endpointAddress);
Program.HostIpcAppToService = pipeFactory.CreateChannel();
Program.HostIpcAppToService.Connect();
CommAppToService.IsPipeAppToService = true;
该服务不会引发我可以检测到的异常,因为 EventViewer 是干净的,只有 OnStart() 成功完成消息。我知道系统会处理App.config
文件,就像之前我遇到错误时,Windows Event Viewer
会一直抱怨,但现在不会了。
以下是我使用的一些 Microsoft 文档:
netNamedPipeBinding
netNamedPipeBinding2
我确实尝试了IO Ninja,但为File Stream
、Pipe Listener
和Pipe Monitor
指定了\\.\pipe\MyIpcToService
,但即使我尝试使用我的 WinForms 桌面应用程序进行连接,也没有显示任何内容,然后它会抛出未发现管道侦听器异常。
可能是什么问题?
【问题讨论】:
那么,有 InnerException 吗? @stuartd 在这种情况下有,但它说的是同样的事情:““在您的本地计算机上找不到管道端点 'net.pipe://localhost/MyIpcAppToService'。” 右键单击我的客户端应用程序并选择添加 > 添加服务引用并粘贴“net.pipe://localhost/MyIpcAppToService/mex”会产生相同的消息,暗示服务器端问题。 【参考方案1】:<endpoint address="net.pipe://localhost/MyIpcAppToService" binding="wsDualHttpBinding" bindingConfiguration="MyAppToServiceEndpointBinding" contract="MyIpc.IIpcAppToService"/>
确保服务地址与绑定类型的格式(传输协议)一致。
TCP(net.tcp://localhost:8000/myservice) NetTcpBinding IPC(net.pipe://localhost/mypipe) NetNamedPipeBindingHttp/Https(http://localhost:8000/myservice) Wshttpbinding,Wsdualhttpbinding,basichttpbinding
WebSocket(ws://localhost:3434) Nethttpbinding
MSMQ(net.msmq://localhost/private/myservice) NetMsmqBinding
我们应该使用 NetnamedPipeBinding 作为服务地址。请参考我的例子。
更新 我有一个使用 IIS 中托管的 NetNamedPipeBinding 的 wcf 服务,希望它对您有用。服务器(wcf 服务应用程序)
[ServiceContract]
public interface IService1
[OperationContract]
string GetData(int value);
public class Service1 : IService1
public string GetData(int value)
return string.Format("You entered: 0", value);
Web.config(服务器端)
<system.serviceModel>
<services>
<service behaviorConfiguration="BehaviorMyService" name="WcfService1.Service1">
<endpoint address="MyIpcAppToService"
binding="netNamedPipeBinding"
bindingConfiguration="EndpointBindingMyAppToService"
contract="WcfService1.IService1"
/>
<endpoint address="mex" binding="mexHttpBinding" name="mex" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="BehaviorMyService">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netNamedPipeBinding>
<binding name="EndpointBindingMyAppToService"
closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:10:00"
sendTimeout="00:01:00"
transactionFlow="false"
transferMode="Buffered"
transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288"
maxConnections="10"
maxReceivedMessageSize="2147483647"
>
<security mode="None">
<transport protectionLevel="None" />
</security>
</binding>
</netNamedPipeBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
</serviceHostingEnvironment>
</system.serviceModel>
启用 WCF 新功能。IIS 站点(启用 net.pipe)@987654324 @客户端(控制台应用程序)
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
var result = client.GetData(34);
Console.WriteLine(result);
客户端 app.config(自动生成) 我使用http地址(服务元数据GET地址http://localhost:8733/Service1.svc?wsdl)来生成配置。
<system.serviceModel>
<bindings>
<netNamedPipeBinding>
<binding name="NetNamedPipeBinding_IService1">
<security mode="None" />
</binding>
</netNamedPipeBinding>
</bindings>
<client>
<endpoint address="net.pipe://mynetpipe/Service1.svc/MyIpcAppToService"
binding="netNamedPipeBinding" bindingConfiguration="NetNamedPipeBinding_IService1"
contract="ServiceReference1.IService1" name="NetNamedPipeBinding_IService1" />
</client>
</system.serviceModel>
如果有什么我可以帮忙的,请随时告诉我。
【讨论】:
我实现了你的建议,看到我更新的问题,正好相反,即服务器端的 App.config 和客户端的 C#。我仍然得到同样的错误。 IO Ninja,并不是说我是那个工具的专家,对调试没有帮助。 我从服务器上的 App.config 中注释掉了该服务并添加到了 C# 代码中。我将 C# 代码保留在客户端上并收到相同的错误。有趣的是“没有端点监听”的第二部分,即“可以接受消息”。这可能意味着客户端问题并且服务器端很好。我会调查的。 在我看来,通过 NetPipe 发布服务有问题。我已经通过修改我的示例更新了我的回复,希望它对你有用。 虽然我必须在 Windows Server 上使用 C# 而不是App.config
,但我在没有额外屏幕截图的情况下使服务正常工作。我无法让服务与配置文件一起使用。现在我正在写作,也许我需要创建一个 .SVC 文件而不仅仅是 4 个 C# 文件。这是工作。谢谢!附加信息是有用的。以上是关于使用 App.Config 在 Windows 服务中的 WCF 命名管道的主要内容,如果未能解决你的问题,请参考以下文章
在带有 WCF 的 App.config 中使用 Windows 角色身份验证
基于Debug模式windows应用程序app.config设置