【问题标题】:Calling Web Service in a Windows Service在 Windows 服务中调用 Web 服务
【发布时间】:2016-12-31 17:38:36
【问题描述】:

我使用了一个简单的 Windows 服务来使某个方法在特定时间工作,并且它工作正常。之后我已经尝试过了:

protected override void OnStart(string[] args)
{
    this.WriteToFile("Simple Service started {0}");
    this.ScheduleService();
}

protected override void OnStop()
{
    this.WriteToFile("Simple Service stopped {0}");
    this.Schedular.Dispose();
}

private Timer Schedular;

public void ScheduleService()
{
    try
    {
        Schedular = new Timer(new TimerCallback(SchedularCallback));
        string mode = ConfigurationManager.AppSettings["Mode"].ToUpper();
        this.WriteToFile("Simple Service Mode: " + mode + " {0}");

        //Rest of the code here
    }
    catch(Exception ex)
    {
        WriteToFile("Simple Service Error on: {0} " + ex.Message + ex.StackTrace);

        //Stop the Windows Service.
        using (System.ServiceProcess.ServiceController serviceController = new System.ServiceProcess.ServiceController("SimpleService"))
        {
            serviceController.Stop();
        }
    }
}

这是在一个简单的 Windows 应用程序中完成的。所以我想做的是在windows服务中调用一个web服务(在特定时间操作的特定方法)。我正在构建的应用程序是基于 Web 的,并且有点困惑如何将 Windows 服务集成到其中?我需要任何替代方案或任何建议将不胜感激。

注意:我想知道的是需要在web应用程序中为windows服务创建另一个项目还是任何其他方式来实现?

【问题讨论】:

  • 是的。您的 Windows 服务需要是一个单独的项目。
  • 感谢您的回复,我正在考虑@PhillipH。顺便问一下,您知道或有任何有用的教程或链接吗?
  • 请看我更完整的答案。

标签: c# asp.net web-services windows-services


【解决方案1】:

要从 Windows 服务应用程序调用 Web 服务,您首先要从该 Web 服务生成一个 DLL,然后实例化其命名空间。假设您拥有该 Web 服务的代码和/或知道其名称空间,您可以执行以下命令来执行此操作:

  1. 在命令行上执行这些行:

    cd C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools
    wsdl /l:CS /protocol:SOAP %svc%?WSDL

    其中%svc% 是您的Web 服务的URL,即http://localhost:777/MyWebService.asmx

    如果代码是 VB 而不是 C#,请将 /l:CS 更改为 /l:VB。 这将输出一个可以转换为 DLL 的代理类文件。

  2. MyWebService.cs 文件从C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools 移动到C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ 目录。

  3. 在命令行运行这两个命令:
    cd C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
    csc /t:library %name%.cs /reference:System.Web.Services.dll /optimize

    其中%name% 是类的名称(没有.cs,因为命令会附加它)。在我们的例子中,我们将使用MyWebService。 (对于 VB 类,将 .cs 更改为 .vb。)

  4. 通过 Windows 资源管理器导航到 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727。您应该会看到在该文件夹中创建的具有类名 (MyWebService.dll) 的 DLL。将此文件复制到服务项目的bin 文件夹中。您需要将bin 文件夹设置为包含在您的项目中,然后右键单击该文件夹以Add > Existing Item。选择 DLL。导入后,选择 DLL 并将其属性更改为:

    构建操作:内容
    复制到输出目录:如果更新则复制(或根据您的喜好始终复制)

  5. 右键单击引用>添加引用。导航到您的 Web 服务的 bin 文件夹中的 DLL。

  6. 右键单击引用>添加服务引用。假设您的 Web 服务正在运行,请获取其完整 URL(即http://localhost:777/MyWebService.asmx)并将其放在地址行中。在命名空间文本框中,给它一些比ServiceReference1 更有意义的东西,但它不应与MyWebService(ASMX 文件的名称/命名空间)相同。也许MWS

  7. 在您的 Windows 服务中实例化您的网络服务:

    MWS.MyWebServiceSoapClient webService = new MWS.MyWebServiceSoapClient();
    webService.Open();
    string someDataYouWant = webService.SomeMethodToGetData();
    webService.Close();

    或者你可以这样做:

    MyWebService webService = new MyWebService();
    string someDataYouWant = webService.SomeMethodToGetData();
    webService.Dispose();

【讨论】:

  • 我这样做了(不同的是我从 Visual Studio 项目中自动创建的 .cs 创建了 .dll)。但是,即使我先导入,webservice 也不会引用 .dll。所以 dll 中的 SoapClass1 != ServiceRef 中的 SoapClass1。我不知道这是否是我安装服务时出现 InvalidOperationException 的原因? (未找到端点名称)。是否遗漏了需要复制到服务安装文件夹的文件/文件夹(我不在项目文件夹中测试!)
  • 您必须非常小心地遵循这些说明。不要跳过任何步骤!您需要将 DLL 复制到 Visual Studio 项目的 bin 文件夹中(步骤 4)。这是实际的 Windows Explorer 文件夹。然后,通过右键单击 VS 解决方案资源管理器中的 bin 文件夹并选择“包含在项目中”,将其带入 Visual Studio。然后右键单击文件夹和“添加现有项目”并选择 DLL。然后像任何普通程序集一样引用 DLL(步骤 5),然后添加服务引用(步骤 6)。这些是最重要的步骤。
  • 如果您不首先构建服务引用,您将无法实例化该类。 Web 服务必须在使用 VS 的网络上运行且可访问。那是你得到错误的地方,还是在代码中的实例化期间?在代码中,你可以试试SoapClass1 webSvc = new SoapClass1(); string myResult = webSvc.SomeMethod(someParam); webSvc.Dispose();
  • 谢谢你vapcguy。我忘记将服务引用设置为重用程序集中的类型。设置后一切正常!
【解决方案2】:

回答您对我的评论的询问;

另一种方法是使用包含 Windows 服务逻辑的 IIS 自动启动网站。 IIS 自动启动优于使用 Windows 服务,因为它包含所有 IIS 应用程序托管逻辑,包括自动重启和积极的资源管理。编写不佳的 Windows 服务可以关闭服务器,但 ASP.net IIS 托管应用程序需要花费很多时间才能关闭其主机(几乎不可能)。

您的自动启动网站不需要对外界可见 - 它只需要有一个内部计时器,让它在启动时保持活动状态。请注意,由于各种原因,IIS 可能会启动和停止 Web 应用程序;但结果是,只要您的其他 Web 服务应用程序运行,它就会运行。内部计时器可以等待特定时间来执行您调用第二个 Web 服务所需的逻辑。

要记住的关键是,Windows 服务被设计为由 Windows 托管并持续运行的应用程序。 IIS 应用程序设计为由 Windows 运行,但仅在调用时运行。 IIS 自动启动网站概念允许您提供一个“持续运行”的网站,但由强大的 IIS 应用程序托管组件托管,而不是直接作为操作系统进程运行。

通常人们不会这样做,因为他们不知道,或者想避免需要 IIS 基础架构来运行“Windows 服务”类型的应用程序,但在您的情况下,您已经支付了使用 IIS 托管您的第二个应用程序的费用web服务,所以你不妨充分利用IIS(并避免Windows服务部署的第二技术堆栈和部署头痛)。

所以我建议在您的情况下使用 IIS 自动启动而不是 Windows 服务,因为;

  1. 您只需要在解决方案中使用技术堆栈,这正是您的 OP 所要求的
  2. IIS 对其所有应用程序执行主动资源管理,如果它们变得无法运行,则根据需要终止和重新启动。 Windows 服务没有该功能。
  3. 您的基于 IIS 的服务代码可以 XCOPY 部署,无需在目标计算机上使用管理员访问凭据。
  4. 您的 IIS 服务无需操作系统级别的管理员权限即可热升级 - IIS 无需您执行任何操作即可处理升级时的停止和重新启动。

【讨论】:

  • 很抱歉,但这听起来有点像毫无根据的“IIS 是幸福的,服务很烂”的咆哮。愿意用证据支持您的主张吗?
  • @CodeCaster - 糟糕的一天?不是真正有用或建设性的评论;但是为了更全面地解释我的建议,我更新了我的答案。
  • PhillipH 我必须同意@CodeCaster,因为问题是如何将 Windows 服务与(调用?)Web 服务集成。除了关于为什么要访问 IIS 自动启动网站的解释之外,对于如何在实际使用 Windows 服务调用 Web 服务的上下文中执行 OP 询问的基本问题,我们没有答案 - 或者如果它可以/不能完成 - 不仅仅是 IYHO,不应该尝试,应该使用 IIS 自动启动网站,这里没有足够的信息来说明如何这样做以及如何实施一步一步来。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-19
  • 2011-07-25
  • 1970-01-01
  • 2014-08-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多