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

Java 需要一种以编程方式检查Windows服务状态的方法,java,command-line,windows-services,Java,Command Line,Windows Services,情况如下: 我被要求使用InstallAnywhere 8,这是一种基于Java的安装程序IDE,它允许启动和停止windows服务,但没有内置的方法来查询它们的状态。幸运的是,它允许您在爪哇中创建自定义操作,这些操作可以在安装过程中的任何时候调用(通过我认为是一个相当复杂的API)。p> 我只需要一些东西,可以告诉我,如果一个特定的服务启动或停止 IDE还允许调用批处理脚本,因此这也是一个选项,尽管脚本一旦运行,几乎无法验证它是否成功,所以我试图避免这种情况 欢迎提出任何建议或批评。在启动过程

情况如下:

我被要求使用InstallAnywhere 8,这是一种基于Java的安装程序IDE,它允许启动和停止windows服务,但没有内置的方法来查询它们的状态。幸运的是,它允许您在爪哇中创建自定义操作,这些操作可以在安装过程中的任何时候调用(通过我认为是一个相当复杂的API)。p> 我只需要一些东西,可以告诉我,如果一个特定的服务启动或停止

IDE还允许调用批处理脚本,因此这也是一个选项,尽管脚本一旦运行,几乎无法验证它是否成功,所以我试图避免这种情况


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

在启动过程中,使用创建一个文件


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

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

以下是如何启动、停止和查询windows服务(C++)的状态:
(VB和C提供了类似的功能)

以下是我必须做的事情。它很难看,但它工作起来很漂亮

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

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


这是一个不确定的事实,但请看一下您的InstallAnywhere 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

您可以动态创建一个小型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);
  }
}
这里有一个straignt 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;
    };
}
//
///如果指定的服务正在运行,则返回true;如果指定的服务不存在或未运行,则返回false。
/// 
///要检查的服务的名称。
///如果指定的服务正在运行,则返回true;如果指定的服务不存在或未运行,则返回false。
静态布尔IServiceRunning(字符串serviceName)
{
bool-rVal=false;
尝试
{
IntPtr smHandle=NativeMethods.OpenSCManager(null,null,NativeMethods.ServiceAccess.ENUMERATE\u服务);
if(smHandle!=IntPtr.Zero)
{
IntPtr svHandle=NativeMethods.OpenService(smHandle、serviceName、NativeMethods.ServiceAccess.ENUMERATE\u服务);
if(svHandle!=IntPtr.Zero)
{
NativeMethods.SERVICE_STATUS servStat=新的NativeMethods.SERVICE_STATUS();
if(NativeMethods.QueryServiceStatus(svHandle,servStat))
{
rVal=servStat.dwCurrentState==NativeMethods.ServiceState.Running;
}
NativeMethods.CloseServiceHandle(svHandle);
}
NativeMethods.CloseServiceHandle(smHandle);
}
}
捕获(System.Exception)
{
}
返回rVal;
}
公共静态类NativeMethods
{
[DllImport(“AdvApi32”)]
公共静态外部IntPtr OpenSCManager(字符串machineName、字符串databaseName、ServiceAccess);
[DllImport(“AdvApi32”)]
公共静态外部IntPtr OpenService(IntPtr serviceManagerHandle,字符串serviceName,ServiceAccess);
[DllImport(“AdvApi32”)]
公共静态外部布尔CloseServiceHandle(IntPtr serviceHandle);
[DllImport(“AdvApi32”)]
公共静态外部布尔查询服务状态(IntPtr serviceHandle,[Out]服务状态);
[旗帜]
公共枚举服务访问:uint
{
所有_访问=0xF003F,
创建_服务=0x2,
CONNECT=0x1,
枚举_服务=0x4,
锁=0x8,
修改启动配置=0x20,
查询\锁定\状态=0x10,
一般读取=0x8000000,
一般写入=0x40000000,
通用_EXECUTE=0x20000000,
通用_ALL=0x10000000
}
公共枚举服务状态
{
停止=1,
停止终止=3,
起始结束=2,
运行=4,
暂停=7,
暂停暂停=6,
连续结束=5
}
[StructLayout(LayoutKind.Sequential,Pack=1)]
公共类服务状态
{
公共服务类型;
公共服务国家;
接受公共内部控制;
公共int dwWin32ExitCode;
公共int dwServiceSpecificExitCode;
公共检查点;
公共int dwWaitHint;
};
}

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

只需调用此方法即可检查服务的状态是否正在运行

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

哇,这很有创意。我不会想到的。不过,我已经使用了Yuval的丑陋但有效的纯Java方法。谢谢@Mohamed Samy。我可以知道如何为多个远程服务器编写上述代码段吗!在process builder中,术语“查询”是什么意思。@远程服务器的SravanKumarPadala只需将\\servername添加到sc命令中即可。检查\n查询----------查询服务的状态,或枚举服务类型的状态。运行sc.exe以获取完整帮助。我已将远程服务器添加为“sc\\remoteServer”,但它会引发以下错误“无法运行程序sc\remoteServer:CreateProcess error=2,系统无法