以编程方式启动Windows服务

57

我正在创建一个应用程序,遇到了一个问题。我试图通过我的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:指定的服务不作为已安装的服务存在--- 内部异常堆栈的末尾

我知道该服务存在。我需要在服务名称前添加什么来告诉它要查找哪台服务器吗?


2
你确定服务没有卡在启动状态吗?我记得服务控制面板在显示这一点上并不完美(至少在某些 Windows 版本之前)。 - Rup
你说的“当我登录服务器”的意思是什么?你是想在另一台机器上使用源代码管理工具吗? - BrokenGlass
哦,而且两个系统都在运行Server 2003。 - Matt
4
将“1秒钟对于远程服务启动来说相当短”改为“将它改为60秒,看看是否有所不同。”请注意不要改变原意。 - Samuel Neff
这可能是显而易见的,但你确定你要启动的服务已经安装在你打算启动它的机器上了吗? - Merav Kochavi
显示剩余2条评论
6个回答

44

如果你展示的代码是在与服务运行位置不同的机器上执行(从你的评论中我不确定是否是这种情况),你需要在ServiceController构造函数中提供机器名。

你是否成功启动了服务,但并非在你认为的机器上?这将符合你所描述的症状。

ServiceController service = new ServiceController(serviceName, serverName);

同时请参阅ServiceController构造函数文档


我已经编辑过了,展示了使用带有远程服务器名称的构造函数。 - hatchet - done with SOverflow
我认为你是正确的,因为现在我收到了一个错误提示,说需要其他权限才能执行此操作。 - Matt
如果我以被模仿用户的身份登录源服务器,我可以打开目标服务器的服务管理器并远程启动和停止服务。但我无法从 Web 应用程序中执行此操作。 - Matt
1
可能取决于您如何设置Web应用程序安全性,但我认为Web应用程序的应用程序池正在运行的帐户将需要在服务将要运行的计算机上拥有启动/停止服务的权限。 - hatchet - done with SOverflow
我已经将模拟身份注释掉了。我需要更加注意。现在运行得非常好。非常感谢。 - Matt

21

以下是我在一个Windows服务中编写的代码,它负责停止启动同一台服务器上运行的其他服务。

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

if (controller.Status==ServiceControllerStatus.Stopped)
    controller.Start(); 

8
这是一个旧的帖子,但我通过谷歌来到这里。即使我的服务已经成功启动,它仍然会查询是否停止。 如果您添加了


service.Refresh();

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

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


7
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;

这是否为问题中的代码添加了任何内容? - Rup

2

首先,您需要在项目的引用中添加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);

2
从问题中的代码来看,我认为 OP 已经超越了那个阶段。 - Rup

0
只需尝试 service.Start();,不需要超时或等待状态,并挂钩其事件以查看发生了什么。

一切看起来都在运行。只是没有显示服务正在运行。 - Matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接