【问题标题】:Need a way to check status of Windows service programmatically需要一种以编程方式检查 Windows 服务状态的方法
【发布时间】:2010-09-24 23:16:50
【问题描述】:

情况如下:

我被要求使用 InstallAnywhere 8,这是一种基于 Java 的安装程序 IDE,它允许启动和停止 Windows 服务,但没有内置方法来查询它们的状态。幸运的是,它允许您在 Java 中创建可以在安装过程中随时调用的自定义操作(通过我认为是相当复杂的 API)。

我只需要一些可以告诉我特定服务是启动还是停止的东西。

IDE 还允许调用批处理脚本,所以这也是一个选项,虽然一旦脚本运行,几乎没有办法验证它是否成功,所以我试图避免这种情况。

欢迎提出任何建议或批评。

【问题讨论】:

    标签: java command-line windows-services


    【解决方案1】:

    在启动过程中,使用File.deleteOnExit() 创建一个文件。

    检查脚本中是否存在该文件。

    【讨论】:

      【解决方案2】:

      多年来我一直在与安装程序打交道,诀窍是创建自己的 EXE 并在安装时调用它。这提供了很好的灵活性,例如在发生错误时显示精确的错误消息,并具有基于成功的返回值,以便您的安装人员知道发生了什么。

      以下是 Windows 服务 (C++) 的启动、停止和查询状态: http://msdn.microsoft.com/en-us/library/ms684941(VS.85).aspx (VB和C#提供类似的功能)

      【讨论】:

        【解决方案3】:

        这是我必须做的。它很丑,但效果很好。

        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 是一个私有方法,它将给定的字符串作为命令行进程运行并返回结果输出。正如我所说,丑陋,但有效。希望这会有所帮助。

        【讨论】:

        • runProcess 包含什么?
        • 这仅适用于将英语配置为区域设置的系统
        【解决方案4】:

        过去,我在 Java Service Wrapper 上遇到过一些运气。根据您的情况,您可能需要付费才能使用它。但它提供了一个干净的解决方案,支持 Java 并且可以在 InstallAnywhere 环境中使用(我认为)没有什么麻烦。这也将允许您在 Unix 机器上支持服务。

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

        【讨论】:

          【解决方案5】:

          在黑暗中拍摄,但请查看您的 Install Anywhere java 文档。

          具体来说,

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

          班级:

          com.installshield.wizard.platform.win32
          Interface Win32Service
          
          All Superinterfaces:
              Service 
          

          方法:

          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
          

          【讨论】:

            【解决方案6】:

            您可以即时创建一个小型 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);
              }
            }
            

            【讨论】:

            • 哇,这很有创意。我不会想到的。不过,我已经最终选择了 Yuval 看起来丑陋但有效的纯 Java 方法。
            【解决方案7】:

            这是一个严格的 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;
                };
            }
            

            【讨论】:

              【解决方案8】:

              根据其他答案,我构建了以下代码来检查 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();
                } 
              }
              

              【讨论】:

              • 谢谢@Mohamed Samy。我能知道上面的 sn-p 是如何为多个远程服务器编写的吗?还有流程构建器中的“查询”一词是什么意思。
              • @SravanKumarPadala 对于远程服务器,只需将 \\servername 添加到 sc 命令。检查link。 \n query-----------查询服务的状态,或者枚举服务类型的状态。运行 sc.exe 以获得完整的帮助。
              • 我已将远程服务器添加为 'sc \\remoteServer' 但它会抛出以下错误 'Cannot run program sc \remoteServer: CreateProcess error=2, The system cannot find the file specified'
              • @SravanKumarPadala 你可以试试以下吗?进程 process = new ProcessBuilder("C:\\Windows\\System32\\sc.exe", "\\servername query" , serviceName ).start();
              【解决方案9】:

              只需调用该方法即可查看服务是否运行状态。

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

              【讨论】:

                【解决方案10】:

                我对给定的解决方案进行了即兴创作,使其独立于语言环境。 比较字符串“RUNNING”在非英语语言环境为 Alejandro González rightly pointed out 的系统中不起作用。

                我使用了sc interrogate,寻找它返回的状态码。

                服务主要可以有3种状态:-

                1 - 不可用

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

                2 - 未运行

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

                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
                

                所以在下面的代码中使用它们,会给我们想要的结果:-

                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();
                    }
                }
                

                【讨论】:

                  猜你喜欢
                  • 2016-06-06
                  • 2012-04-10
                  • 2016-11-16
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-01-13
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-10-03
                  相关资源
                  最近更新 更多