简体   繁体   English

需要一种以编程方式检查 Windows 服务状态的方法

[英]Need a way to check status of Windows service programmatically

Here is the situation:这是情况:

I have been called upon to work with InstallAnywhere 8, a Java-based installer IDE, of sorts, that allows starting and stopping of windows services, but has no built-in method to query their states.我被要求使用 InstallAnywhere 8,这是一个基于 Java 的安装程序 IDE,它允许启动和停止 Windows 服务,但没有内置方法来查询它们的状态。 Fortunately, it allows you to create custom actions in Java which can be called at any time during the installation process (by way of what I consider to be a rather convoluted API).幸运的是,它允许您在 Java 中创建可以在安装过程中随时调用的自定义操作(通过我认为是相当复杂的 API)。

I just need something that will tell me if a specific service is started or stopped.我只需要一些可以告诉我特定服务是启动还是停止的信息。

The IDE also allows calling batch scripts, so this is an option as well, although once the script is run, there is almost no way to verify that it succeeded, so I'm trying to avoid that. IDE 还允许调用批处理脚本,因此这也是一个选项,尽管脚本运行后,几乎无法验证它是否成功,因此我试图避免这种情况。

Any suggestions or criticisms are welcome.欢迎任何建议或批评。

here's what I had to do.这就是我必须做的。 It's ugly, but it works beautifully.它很丑,但效果很好。

String STATE_PREFIX = "STATE              : ";

String s = runProcess("sc query \""+serviceName+"\"");
// check that the temp string contains the status prefix
int ix = s.indexOf(STATE_PREFIX);
if (ix >= 0) {
  // compare status number to one of the states
  String stateStr = s.substring(ix+STATE_PREFIX.length(), ix+STATE_PREFIX.length() + 1);
  int state = Integer.parseInt(stateStr);
  switch(state) {
    case (1): // service stopped
      break;
    case (4): // service started
      break;
   }
}

runProcess is a private method that runs the given string as a command line process and returns the resulting output. runProcess是一个私有方法,它将给定的字符串作为命令行进程运行并返回结果输出。 As I said, ugly, but works.正如我所说,丑陋,但有效。 Hope this helps.希望这可以帮助。

You can create a small VBS on-th-fly, launch it and capture its return code.您可以即时创建一个小型 VBS,启动它并捕获其返回代码。

import java.io.File;
import java.io.FileWriter;

public class VBSUtils {
  private VBSUtils() {  }

  public static boolean isServiceRunning(String serviceName) {
    try {
        File file = File.createTempFile("realhowto",".vbs");
        file.deleteOnExit();
        FileWriter fw = new java.io.FileWriter(file);

        String vbs = "Set sh = CreateObject(\"Shell.Application\") \n"
                   + "If sh.IsServiceRunning(\""+ serviceName +"\") Then \n"
                   + "   wscript.Quit(1) \n"
                   + "End If \n"
                   + "wscript.Quit(0) \n";
        fw.write(vbs);
        fw.close();
        Process p = Runtime.getRuntime().exec("wscript " + file.getPath());
        p.waitFor();
        return (p.exitValue() == 1);
    }
    catch(Exception e){
        e.printStackTrace();
    }
    return false;
  }


  public static void main(String[] args){
    //
    // DEMO
    //
    String result = "";
    msgBox("Check if service 'Themes' is running (should be yes)");
    result = isServiceRunning("Themes") ? "" : " NOT ";
    msgBox("service 'Themes' is " + result + " running ");

    msgBox("Check if service 'foo' is running (should be no)");
    result = isServiceRunning("foo") ? "" : " NOT ";
    msgBox("service 'foo' is " + result + " running ");
  }

  public static void msgBox(String msg) {
    javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
       null, msg, "VBSUtils", javax.swing.JOptionPane.DEFAULT_OPTION);
  }
}

Based on the other answers I constructed the following code to check for Windows Service status:根据其他答案,我构建了以下代码来检查 Windows 服务状态:

public void checkService() {
  String serviceName = "myService";  

  try {
    Process process = new ProcessBuilder("C:\\Windows\\System32\\sc.exe", "query" , serviceName ).start();
    InputStream is = process.getInputStream();
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);

    String line;
    String scOutput = "";

    // Append the buffer lines into one string
    while ((line = br.readLine()) != null) {
        scOutput +=  line + "\n" ;
    }

    if (scOutput.contains("STATE")) {
        if (scOutput.contains("RUNNING")) {
            System.out.println("Service running");
        } else {
            System.out.println("Service stopped");
        }       
    } else {
        System.out.println("Unknown service");
    }
  } catch (IOException e) {
    e.printStackTrace();
  } 
}

I have been dealing with installers for years and the trick is to create your own EXE and call it on setup.我多年来一直与安装程序打交道,诀窍是创建自己的 EXE 并在安装时调用它。 This offers good flexibility like displaying precise error messages in the event an error occurs, and have success-based return values so your installer knows about what happened.这提供了良好的灵活性,例如在发生错误时显示精确的错误消息,并具有基于成功的返回值,以便您的安装人员知道发生了什么。

Here's how to start, stop and query states for windows services (C++): http://msdn.microsoft.com/en-us/library/ms684941(VS.85).aspx (VB and C# offers similar functions)以下是如何启动、停止和查询 windows 服务 (C++) 的状态: http : //msdn.microsoft.com/en-us/library/ms684941 (VS.85) .aspx (VB 和 C# 提供类似功能)

I have had some luck in the past with the Java Service Wrapper.过去我在 Java Service Wrapper 上有过一些运气。 Depending upon your situation you may need to pay in order to use it.根据您的情况,您可能需要付费才能使用它。 But it offers a clean solution that supports Java and could be used in the InstallAnywhere environment with (I think) little trouble.但它提供了一个干净的解决方案,支持 Java 并且可以在 InstallAnywhere 环境中使用(我认为)没有什么麻烦。 This will also allow you to support services on Unix boxes as well.这也将允许您支持 Unix 机器上的服务。

http://wrapper.tanukisoftware.org/doc/english/download.jsp http://wrapper.tanukisoftware.org/doc/english/download.jsp

A shot in the dark but take a look at your Install Anywhere java documentation.在黑暗中拍摄,但请查看您的 Install Anywhere java 文档。

Specifically,具体来说,

/javadoc/com/installshield/wizard/platform/win32/Win32Service.html /javadoc/com/installshield/wizard/platform/win32/Win32Service.html

The class:班上:

com.installshield.wizard.platform.win32
Interface Win32Service

All Superinterfaces:
    Service 

The method:方法:

public NTServiceStatus queryNTServiceStatus(String name)
                                     throws ServiceException

    Calls the Win32 QueryServiceStatus to retrieve the status of the specified service. See the Win32 documentation for this API for more information.

    Parameters:
        name - The internal name of the service. 
    Throws:
        ServiceException

Here's a straignt C# / P/Invoke solution.这是一个严格的 C#/P/Invoke 解决方案。

        /// <summary>
    /// Returns true if the specified service is running, or false if it is not present or not running.
    /// </summary>
    /// <param name="serviceName">Name of the service to check.</param>
    /// <returns>Returns true if the specified service is running, or false if it is not present or not running.</returns>
    static bool IsServiceRunning(string serviceName)
    {
        bool rVal = false;
        try
        {
            IntPtr smHandle = NativeMethods.OpenSCManager(null, null, NativeMethods.ServiceAccess.ENUMERATE_SERVICE);
            if (smHandle != IntPtr.Zero)
            {
                IntPtr svHandle = NativeMethods.OpenService(smHandle, serviceName, NativeMethods.ServiceAccess.ENUMERATE_SERVICE);
                if (svHandle != IntPtr.Zero)
                {
                    NativeMethods.SERVICE_STATUS servStat = new NativeMethods.SERVICE_STATUS();
                    if (NativeMethods.QueryServiceStatus(svHandle, servStat))
                    {
                        rVal = servStat.dwCurrentState == NativeMethods.ServiceState.Running;
                    }
                    NativeMethods.CloseServiceHandle(svHandle);
                }
                NativeMethods.CloseServiceHandle(smHandle);
            }
        }
        catch (System.Exception )
        {

        }
        return rVal;
    }

public static class NativeMethods
{
    [DllImport("AdvApi32")]
    public static extern IntPtr OpenSCManager(string machineName, string databaseName, ServiceAccess access);
    [DllImport("AdvApi32")]
    public static extern IntPtr OpenService(IntPtr serviceManagerHandle, string serviceName, ServiceAccess access);
    [DllImport("AdvApi32")]
    public static extern bool CloseServiceHandle(IntPtr serviceHandle);
    [DllImport("AdvApi32")]
    public static extern bool QueryServiceStatus(IntPtr serviceHandle, [Out] SERVICE_STATUS status);

    [Flags]
    public enum ServiceAccess : uint
    {
        ALL_ACCESS = 0xF003F,
        CREATE_SERVICE = 0x2,
        CONNECT = 0x1,
        ENUMERATE_SERVICE = 0x4,
        LOCK = 0x8,
        MODIFY_BOOT_CONFIG = 0x20,
        QUERY_LOCK_STATUS = 0x10,
        GENERIC_READ = 0x80000000,
        GENERIC_WRITE = 0x40000000,
        GENERIC_EXECUTE = 0x20000000,
        GENERIC_ALL = 0x10000000
    }

    public enum ServiceState
    {
        Stopped = 1,
        StopPending = 3,
        StartPending = 2,
        Running = 4,
        Paused = 7,
        PausePending =6,
        ContinuePending=5
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public class SERVICE_STATUS
    {
        public int dwServiceType;
        public ServiceState dwCurrentState;
        public int dwControlsAccepted;
        public int dwWin32ExitCode;
        public int dwServiceSpecificExitCode;
        public int dwCheckPoint;
        public int dwWaitHint;
    };
}

During startup, create a file with File.deleteOnExit() .在启动期间,使用File.deleteOnExit()创建一个文件。

Check for the existence of the file in your scripts.检查脚本中是否存在该文件。

Simply call this method to check the status of service whether running or not.只需调用此方法即可检查服务的状态是否正在运行。

public boolean checkIfServiceRunning(String serviceName) {
    Process process;
    try {
      process = Runtime.getRuntime().exec("sc query " + serviceName);
      Scanner reader = new Scanner(process.getInputStream(), "UTF-8");
      while(reader.hasNextLine()) {
         if(reader.nextLine().contains("RUNNING")) {
           return true;
         }
      }
     } catch (IOException e) {
         e.printStackTrace();
     }            
     return false;
}

I improvised on the given solutions, to make it locale independent.我即兴创作了给定的解决方案,使其独立于语言环境。 Comparing the string "RUNNING" would not work in systems with non-english locales as Alejandro González rightly pointed out.正如亚历杭德罗·冈萨雷斯 (Alejandro González) 正确指出的那样,比较字符串“RUNNING”在非英语语言环境的系统中不起作用。

I made use of sc interrogate and look for the status codes returned by it.我使用sc 询问并查找它返回的状态代码。

Mainly, the service can have 3 states:-主要是,该服务可以有 3 个状态:-

1 - Not available 1 - 不可用

[SC] OpenService FAILED 1060: The specified service does not exist as an installed service.

2 - Not running 2 - 不运行

([SC] ControlService FAILED 1062: The service has not been started)

3 - Running 3 - 跑步

    TYPE               : 10  WIN32_OWN_PROCESS
    STATE              : 2  START_PENDING
                            (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
    WIN32_EXIT_CODE    : 0  (0x0)
    SERVICE_EXIT_CODE  : 0  (0x0)
    CHECKPOINT         : 0x0
    WAIT_HINT          : 0x7d0
    PID                : 21100code here

So using them in following code, gives us the desired result :-所以在下面的代码中使用它们,给了我们想要的结果:-

public static void checkBackgroundService(String serviceName) {
    Process process;
    try {
        process = Runtime.getRuntime().exec("sc interrogate " + serviceName);
        Scanner reader = new Scanner(process.getInputStream(), "UTF-8");
        StringBuffer buffer = new StringBuffer();
        while (reader.hasNextLine()) {
            buffer.append(reader.nextLine());
        }
        System.out.println(buffer.toString());
            if (buffer.toString().contains("1060:")) {
                System.out.println("Specified Service does not exist");
            } else if (buffer.toString().contains("1062:")) {
                System.out.println("Specified Service is not started (not running)");
            } else {
                System.out.println("Specified Service is running");
            }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

hope this helps somebody :)希望这对某人有所帮助:)

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

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