【问题标题】:Start Windows Service programmatically以编程方式启动 Windows 服务
【发布时间】:2011-10-03 19:29:43
【问题描述】:

我正在创建的应用程序有问题。我正在尝试通过我的 C# 应用程序启动 Windows 服务。当我单击我的开始按钮时,看起来一切都通过了,但是当我登录服务器时,该服务仍然没有显示它正在运行。但是,第二次运行它时,我得到一个异常,说明该服务的实例已经在运行。当我再次登录服务器时,服务似乎已停止。有人见过这个吗?

这是我的代码。

try
{
    while (reader.Read())
    {
        int timeoutMilliseconds = 1000;
        string serviceName = reader["ServiceName"].ToString();
        string permission = reader["Permission"].ToString();

        if (permission == "E")
        {
            lblServStartSuccess.Visible = true;

            ServiceController service = new ServiceController(serviceName);
            TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

            service.Start();
            service.WaitForStatus(ServiceControllerStatus.Running, timeout);
        }
        else
        {
            lblServErrorStart.Visible = true;
        }
    }
}
catch (Exception ex)
{
    Response.Write(ex.ToString());
}

编辑:这是我在一项服务中收到的例外情况:

System.InvalidOperationException:服务逻辑磁盘管理器 在计算机“.”上找不到管理服务。 ---> System.ComponentModel.Win32Exception:指定的服务没有 作为已安装服务存在 --- 内部异常堆栈跟踪结束

我知道该服务存在。我是否需要在服务前面添加一些内容来告诉它要查看哪个服务器?

【问题讨论】:

  • 您确定服务没有卡在启动状态吗?我记得服务控制面板在显示这一点方面并不出色(至少在某些 Windows 版本之前)
  • “当我登录服务器时”是什么意思 - 您是否尝试在不同的机器上使用 SCM?
  • 是的,我正在从远程服务器运行 Web 服务。我正在使用具有管理员访问权限的帐户。我不确定它是否卡住了。我的超时时间是否太短而超时?
  • 哦,有问题的两个系统都在运行 Server 2003。
  • 1 秒对于远程服务启动来说非常短。将其更改为 60 秒,看看是否有区别。

标签: c# windows-services


【解决方案1】:

如果您显示的代码在与服务应该运行的位置不同的机器上执行(我不清楚您的 cmets 是否是这种情况),您需要在 ServiceController 中提供机器名称构造函数。

您是否有可能成功启动服务,但不是在您认为的机器上?这符合你描述的症状。

ServiceController service = new ServiceController(serviceName, serverName);

Also see ServiceController constructor documentation.

【讨论】:

  • 我已编辑以显示使用远程服务器名称的构造函数。
  • 我认为您是正确的,因为现在我收到一条错误消息,指出需要其他权限才能执行此操作。
  • 如果我冒充用户登录源服务器,可以拉起目标服务器的服务管理器,远程启动和停止服务。我只是无法从网络应用程序中执行此操作。
  • 这可能取决于您如何设置 Web 应用程序的安全性,但我认为运行 Web 应用程序的应用程序池的帐户需要在服务所在的机器上启动/停止服务的权限运行。
  • 我已经注释掉了我的冒名顶替。我需要多加注意。现在效果很好。非常感谢。
【解决方案2】:

首先你需要在你的项目References中添加DLL(ServiceProcess)的引用,如下:

Right click on References in Solution Explorer -> Add Reference -> Assemblies -> 
Framework -> System.ServiceProcess

然后在你的项目中添加ServiceProcess DLL:

using System.ServiceProcess;

之后使用此代码:

ServiceController service = new ServiceController(yourServiceName);

【讨论】:

  • 从问题中的代码来看,我认为 OP 已经过了这一点。
【解决方案3】:

这是一个旧线程,但谷歌让我在这里。我的服务,即使在成功启动后,仍然会在停止状态下查询。 如果你添加

service.Refresh();

它将查询实际的当前状态,而不是先前查询中存储的状态。我不知道为什么会这样,但确实如此。

P.S.:我添加了一分钟的超时时间,但仍然得到服务停止响应而没有刷新。

【讨论】:

    【解决方案4】:
    public static void StartService(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);
            try
            {
                int millisec1 = 0;
                TimeSpan timeout;
    
                // count the rest of the timeout
                int millisec2 = Environment.TickCount;
                timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds - (millisec1));
                service.Start();
                service.WaitForStatus(ServiceControllerStatus.Running, timeout);
    
            }
            catch (Exception e)
            {
                Trace.WriteLine(e.Message);
            }
        }
        public static void StopService(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);
            try
            {
                int millisec1 = 0;
                TimeSpan timeout;
                if (service.Status == ServiceControllerStatus.Running)
                {
                    millisec1 = Environment.TickCount;
                    timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);
                    service.Stop();
                    service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
                }
    
    
            }
            catch (Exception e)
            {
                Trace.WriteLine(e.Message);
            }
        }
        public static void RestartService(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);
            try
            {
                int millisec1 = 0;
                TimeSpan timeout;
                if (service.Status == ServiceControllerStatus.Running)
                {
                    millisec1 = Environment.TickCount;
                    timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);
                    service.Stop();
                    service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
                }
                // count the rest of the timeout
                int millisec2 = Environment.TickCount;
                timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds - (millisec2 - millisec1));
                service.Start();
                service.WaitForStatus(ServiceControllerStatus.Running, timeout);
    
            }
            catch (Exception e)
            {
                Trace.WriteLine(e.Message);
            }
        }
    

    不要忘记添加 ServiceProcess 作为参考 使用 System.ServiceProcess;

    【讨论】:

    • 这是否会在问题中的代码中添加任何内容?
    【解决方案5】:

    这是我在窗口服务中的代码,负责停止启动在同一服务器上运行的其他服务。

    ServiceController controller = new ServiceController(serviceName);
    if (controller.Status==ServiceControllerStatus.Running)
        controller.Stop();
    
    if (controller.Status==ServiceControllerStatus.Stopped)
        controller.Start(); 
    

    【讨论】:

      【解决方案6】:

      试试 service.Start();没有超时或 waitforstatus 并挂钩其事件以查看发生了什么。

      【讨论】:

      • 一切正常。它只是没有显示服务正在运行。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-04
      • 1970-01-01
      • 1970-01-01
      • 2018-10-07
      • 2010-09-18
      • 2017-10-22
      相关资源
      最近更新 更多