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

情况如下:

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

我只需要能告诉我是否启动或停止特定服务的东西。

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

欢迎任何建议或批评。

这就是我必须做的事情。 这很难看,但效果很好。

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

您可以在运行中创建一个小型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); } } 

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

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

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

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

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

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

特别,

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

class上:

 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 

这是一个直接的C#/ P / Invoke解决方案。

  ///  /// Returns true if the specified service is running, or false if it is not present or not running. ///  /// Name of the service to check. /// Returns true if the specified service is running, or false if it is not present or not running. 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; }; } 

在启动期间,使用File.deleteOnExit()创建一个文件。

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