简体   繁体   English

运行应用程序可执行文件时,无法在WinForm应用程序中托管WCF服务

[英]Hosting WCF Service within WinForm Application doesn't work when running the application executable

Over the past few weeks I have developed a 64-bit WinForms application that needs to communicate with a 32-bit DLL (job specs require it). 在过去的几周中,我开发了一个需要与32位DLL通信的64位WinForms应用程序(作业规范要求使用它)。

After doing some reading around the internet and finding out that there is not going to be any fun way of doing this, I decided to go with hosting a WCF Service Application within my WinForms application for communicating to the 32-bit DLL... or so I thought I was doing. 在浏览了互联网并发现没有任何有趣的方法之后,我决定在WinForms应用程序中托管WCF服务应用程序以与32位DLL进行通信...或所以我以为我在做

During development (while running within Visual Studio) it has been working really well, but of course, now that I need to deploy, I am running into problems. 在开发过程中(在Visual Studio中运行),它确实运行良好,但是,当然,由于需要部署,因此遇到了问题。 I am having trouble getting a strong enough understanding of WCF Services to know if I am going about this in a terrible way or if I am just missing some minute detail. 我很难对WCF服务有足够的了解,以至于我是否会以一种糟糕的方式来解决这个问题,或者我只是缺少一些细节。

I created the project as Admin. 我将项目创建为Admin。 After development was finished I tried to run the WinForm executable (both debug and release), WindowsFormsApplication1.exe. 开发完成后,我尝试运行WinForm可执行文件(调试和发行版)WindowsFormsApplication1.exe。 The application started up, but after I tried to complete a task involving the use of the WCF service, an exception was thrown: 该应用程序已启动,但是在我尝试完成涉及WCF服务使用的任务后,引发了异常:

异常消息

This has led me to believe that Visual Studio was doing the hosting of the service during development instead of the WinForm application, or my configs and/or directory structures are incorrect. 这使我相信Visual Studio在开发过程中是在托管服务而不是WinForm应用程序,或者我的配置和/或目录结构不正确。

[UPDATED] WCF Service Web.config: [更新] WCF服务Web.config:

<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5.2" />
    <httpRuntime targetFramework="4.5.2" maxRequestLength="2147483647"/>
  </system.web>

  <system.net>
    <defaultProxy>
      <proxy usesystemdefault="False"/>
    </defaultProxy>
  </system.net>

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="Information, ActivityTracing"
              propagateActivity="true" >
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>
      <source name="myUserTraceSource"
              switchValue="Information, ActivityTracing">
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add name="xml"
           type="System.Diagnostics.XmlWriterTraceListener"
                 initializeData="C:\logs\Traces.svclog" />
    </sharedListeners>
  </system.diagnostics>

  <system.serviceModel>
    <diagnostics wmiProviderEnabled="true">
      <messageLogging
           logEntireMessage="true"
           logMalformedMessages="true"
           logMessagesAtServiceLevel="true"
           logMessagesAtTransportLevel="true"
           maxMessagesToLog="3000"
       />
    </diagnostics>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadadiscovery>
          <!-- 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="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

<services>
  <service name="ServiceReference1.Service1" behaviorConfiguration="metadadiscovery">
    <endpoint address="" binding="basicHttpBinding" contract="ServiceReference1.IService1"></endpoint>
  </service>
</services>

    <protocolMapping>
        <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="false"/>
  </system.webServer>

</configuration>

WinForm App.config: WinForm App.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
  </startup>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IService2" />
        <binding name="BasicHttpBinding_IService3" />
        <binding name="BasicHttpBinding_IService1" />
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:45053/Service2.svc" binding="basicHttpBinding"
        bindingConfiguration="BasicHttpBinding_IService2" contract="ServiceReference2.IService2"
        name="BasicHttpBinding_IService2" />
      <endpoint address="http://localhost:46351/Service3.svc" binding="basicHttpBinding"
        bindingConfiguration="BasicHttpBinding_IService3" contract="ServiceReference3.IService3"
        name="BasicHttpBinding_IService3" />
      <endpoint address="http://localhost:44848/Service1.svc" binding="basicHttpBinding"
        bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
        name="BasicHttpBinding_IService1" />
    </client>
  </system.serviceModel>
  <appSettings>
    <add key="ClientSettingsProvider.ServiceUri" value="" />
  </appSettings>
  <system.web>
    <membership defaultProvider="ClientAuthenticationMembershipProvider">
      <providers>
        <add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
      </providers>
    </membership>
    <roleManager defaultProvider="ClientRoleProvider" enabled="true">
      <providers>
        <add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
      </providers>
    </roleManager>
  </system.web>
</configuration>

Directory Where EXE resides: EXE所在的目录:

目录

The directory containing the WCF Service resides within the directory WcfService1 from the image above. 包含WCF服务的目录位于上图中的WcfService1目录中。

I have mostly been using the following method of instantiating the service: 我主要使用以下实例化服务的方法:

ServiceReference1.Service1Client = new ServiceReference1.SErvice1Client();

Once I tried to switch to using a service host (below), but when I used that method, the service would timeout whenever it tried to communicate to the DLL. 一旦我尝试切换到使用服务主机(如下),但是当我使用该方法时,只要它尝试与DLL通信,该服务就会超时。

Uri address = new Uri("http://localhost:44848/Service1.svc");
ServiceHost host = new ServiceHost(typeof(ServiceReference1.Service1Client), address);
host.Open();

And then I closed the host later. 然后我关闭了主机。 At this point, I am willing to try anything to get this working. 在这一点上,我愿意尝试一切以使它起作用。

[EDIT] Below is the code of my WindowsFormsApplication1.exe.config file. [编辑]下面是我的WindowsFormsApplication1.exe.config文件的代码。 All three contracts are giving the warning that they're "invalid according to its datatype 'clientContractType'". 所有这三个合同都警告说它们“根据其数据类型'clientContractType'是无效的”。 I think this could be the source of my problems, but I do not know why it is showing this warning: 我认为这可能是我遇到的问题的根源,但我不知道为什么它显示此警告:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
  </startup>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IService2" />
        <binding name="BasicHttpBinding_IService3" />
        <binding name="BasicHttpBinding_IService1" />
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:45053/Service2.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService2" contract="ServiceReference2.IService2" name="BasicHttpBinding_IService2" />
      <endpoint address="http://localhost:46351/Service3.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService3" contract="ServiceReference3.IService3" name="BasicHttpBinding_IService3" />
      <endpoint address="http://localhost:44848/Service1.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1" name="BasicHttpBinding_IService1" />
    </client>
  </system.serviceModel>
</configuration>

Thank you for any help and guidance you can provide. 感谢您提供的任何帮助和指导。

There is no endpoint configured for your service. 没有为您的服务配置端点。

    <behaviors>
          <serviceBehaviors>
            <behavior name="metadadiscovery">
              <!-- 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="false"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
     <service name="ServiceReference2.Yourimplementingservice" behaviorConfiguration="metadadiscovery">
      <endpoint address="" binding="basicHttpBinding" contract="ServiceReference2.IService2">          
       </endpoint>

Above I have configured for Service2 ,similarly you have to configure for Service1 and Service3. 上面我已经为Service2配置了,类似地,您也必须为Service1和Service3配置。

After sufficient struggling I decided to get rid of the WCF service that visual studio generates for you when you create it as a new project. 经过充分的努力后,我决定摆脱Visual Studio在将其创建为新项目时​​为您生成的WCF服务。 I instead followed this tutorial verbatim: 相反,我逐字遵循了本教程:

Hosting Service In App 应用内托管服务

Doing this came with huge advantages: 这样做具有巨大的优势:

  1. No configuration file was necessary 无需配置文件
  2. Running it this way must've gotten rid of a large amount of overhead because the communication to the DLL (what I am using the service for) used to take several seconds to do large amounts of calls to the DLL, but now is able to handle 10k+ calls in the blink of an eye. 以这种方式运行它必须消除大量的开销,因为与DLL的通信(我正在使用该服务用于的通信)过去需要花费几秒钟来进行对DLL的大量调用,但是现在能够眨眼间即可处理10k多个电话。
  3. No service reference is necessary. 无需服务参考。 I just needed the file for my main function, the file containing the service function implementations and the file containing the interface for the implementation. 我只需要用于我的主要功能的文件,包含服务功能实现的文件和包含实现接口的文件。

So far, this has been the easiest and most robust way I have found for using a 32 bit DLL in a 64 bit application. 到目前为止,这是我发现在64位应用程序中使用32位DLL的最简单,最可靠的方法。 Let me know if I can give any guidance for anyone else who may be struggling with this problem. 让我知道我是否可以为其他可能遇到此问题的人提供任何指导。 I know this is not a fun thing to deal with if you've never done anything like it before. 我知道,如果您以前从未做过类似的事情,这并不是一件有趣的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM