2008-12-02 8 views
11

Aquí está la situación:necesita una manera de comprobar el estado del servicio de Windows mediante programación

he tenido que trabajar con InstallAnywhere 8, un IDE de instalación basada en Java, de todo tipo, que permite el arranque y parada de las ventanas servicios, pero no tiene un método incorporado para consultar sus estados. Afortunadamente, le permite crear acciones personalizadas en Java a las que se puede llamar en cualquier momento durante el proceso de instalación (a través de lo que yo considero una API complicada).

Solo necesito algo que me diga si un servicio específico se inicia o detiene.

IDE también permite llamar a secuencias de comandos por lotes, por lo que esta es una opción también, aunque una vez que se ejecuta la secuencia de comandos, casi no hay forma de verificar que tuvo éxito, así que estoy tratando de evitar eso.

Cualquier sugerencia o crítica es bienvenida.

Respuesta

14

Esto es lo que tenía que hacer. Es feo, pero funciona muy bien.

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 es un método privado que corre la cadena dada como un proceso de línea de comandos y devuelve la salida resultante. Como dije, feo, pero funciona. Espero que esto ayude.

+2

lo contiene runProcess? –

0

Durante el inicio, cree un archivo con File.deleteOnExit().

Compruebe la existencia del archivo en sus scripts.

3

He estado tratando con instaladores durante años y el truco es crear su propio EXE y llamarlo en la configuración. Esto ofrece una buena flexibilidad, como mostrar mensajes de error precisos en caso de que se produzca un error, y tener valores de retorno basados ​​en el éxito para que su instalador sepa lo que sucedió.

Así es como iniciar, detener y estados de consulta para los servicios de Windows (C++): http://msdn.microsoft.com/en-us/library/ms684941(VS.85).aspx (VB y C# ofrece funciones similares)

2

He tenido algo de suerte en el pasado con Java Service Wrapper. Dependiendo de su situación, es posible que deba pagar para usarlo. Pero ofrece una solución limpia que admite Java y podría usarse en el entorno InstallAnywhere con (creo) pocos problemas. Esto también le permitirá soportar servicios en cajas Unix también.

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

1

Un disparo en la oscuridad, pero echar un vistazo a la documentación de instalar en cualquier lugar de Java.

Específicamente,

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

La clase:

com.installshield.wizard.platform.win32 
Interface Win32Service 

All Superinterfaces: 
    Service 

El método:

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

Puede crear un pequeño VBS on-th-fly, ejecutarlo y capturar su código de retorno.

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); 
    } 
} 
+1

Guau, esto es muy creativo. No hubiera pensado en eso. Sin embargo, ya terminé yendo con el enfoque Java puro de aspecto horrible pero efectivo de Yuval. – Troy

1

Aquí hay una solución de invocación de C#/P/strand.

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

Sobre la base de las otras respuestas que construye el siguiente código para comprobar el estado del servicio de 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(); 
    } 
} 
+0

Gracias @Mohamed Samy. ¿Puedo saber cómo se escribe el fragmento de arriba para múltiples servidores remotos? también, ¿qué significa el término "consulta" en el generador de procesos? –

+0

@SravanKumarPadala Para el servidor remoto simplemente agregue \\ servername al comando sc. Verifique [link] (http://stackoverflow.com/a/187854/1364048). \ n consulta ----------- Consulta el estado de un servicio o enumera el estado de los tipos de servicios. Ejecute sc.exe para obtener la ayuda completa. –

+0

He agregado el servidor remoto como 'sc \\ remoteServer' pero arroja, el siguiente error 'No se puede ejecutar el programa sc \ remoteServer: CreateProcess error = 2, El sistema no puede encontrar el archivo especificado' –

Cuestiones relacionadas