4

问题

我想使用 Windows API 控制任何 Windows 服务,但我不能:(

=我的“想要的解决方案”有什么问题?

当前解决方案

我使用的最丑陋但实用的方式如下(用于Stop命令):

void StopService()
{
    ShellExecute(Application->Handle,
                 "open",
                 "stop.bat",
                 NULL,
                 ExtractFilePath(Application->ExeName).c_str(),
                 SW_SHOW);
}

stop.bat包含以下命令的 Windows 批处理文件在哪里:

::the command
sc stop "service name"
::a pause to see if something goes wrong
pause

不得不关闭已启动的 cmd 窗口非常烦人...

想要解决方案

下面的功能似乎没问题。如果我尝试执行命令来停止不存在的服务,它将显示一条错误消息。但是当我尝试为现有服务运行它时,它会运行,但服务没有任何反应(如果我决定停止它,它什么也不做)......

void ControlService(AnsiString ServiceName, DWORD Order)
{
    SC_HANDLE Scm, Svc;
    SERVICE_STATUS Status;

    Scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

    if(Scm != 0)
    {
        Svc = OpenService(Scm, PChar(ServiceName.c_str()), SERVICE_ALL_ACCESS);

        if(Svc != 0)
        {
            ControlService(Svc, Order, &Status);

            // handle Status....
            CloseServiceHandle(Svc);
        }
        else
        {
            ShowLastError();
        }
        CloseServiceHandle(Scm);
    }
    else
    {
        ShowLastError();
    }
}

void ShowLastError()
{
    LPVOID lpMsgBuf;

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        GetLastError(),
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
        (LPTSTR) &lpMsgBuf,
        0,
        NULL
    );

    // Display the string.
    MessageBox(NULL, (char*)lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION);

    // Free the buffer.
    LocalFree(lpMsgBuf);
}

怎么了?????

4

1 回答 1

4

您可能会遇到两个可能的问题:

  1. 您过早地检查服务状态。ServiceControl 立即返回,无需等待服务完成请求。您的服务可能会转换为 SERVICE_STOP_PENDING,在这种情况下,您必须给它一些时间并再次检查。
  2. 存在运行状态的依赖服务。您将不得不枚举依赖服务,首先将它们关闭,然后停止您的服务。

在 #2 上,在MSDN上有一个很好的示例代码解释。这是同一页面的引述:

但是,如果 SCM 确定其他正在运行的服务依赖于指定的服务,则不会转发停止请求。相反,它返回 ERROR_DEPENDENT_SERVICES_RUNNING。因此,要以编程方式停止此类服务,您必须首先枚举并停止其依赖的服务。

于 2013-06-03T14:55:36.230 回答