Нужен способ программно проверить статус службы Windows

Вот ситуация:

Меня призвали работать с InstallAnywhere 8, своего рода IDE-установщиком на основе Java, который позволяет запускать и останавливать службы Windows, но не имеет встроенного метода для запроса их состояния. К счастью, он позволяет вам создавать настраиваемые действия на Java, которые можно вызывать в любое время в процессе установки (из-за того, что я считаю довольно запутанным API).

Мне просто нужно что-то, что скажет мне, запущена ли конкретная служба или остановлена.

IDE также позволяет вызывать пакетные скрипты, так что это тоже вариант, хотя после запуска скрипта практически невозможно проверить, успешно ли он выполнен, поэтому я пытаюсь этого избежать.

Любые предложения или критика приветствуются.


person Troy    schedule 02.12.2008    source источник


Ответы (9)


вот что я должен был сделать. Это некрасиво, но работает красиво.

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 — это закрытый метод, который запускает заданную строку как процесс командной строки и возвращает результат. Как я уже сказал, некрасиво, но работает. Надеюсь это поможет.

person Yuval    schedule 02.12.2008
comment
что содержит runProcess? - person S K padala; 07.03.2016
comment
Это работает только для систем с английским языком, настроенным в качестве локали. - person Alejandro González; 23.01.2020

Вы можете создать небольшой 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);
  }
}
person RealHowTo    schedule 03.12.2008
comment
Вау, это очень креативно. Я бы не подумал об этом. Тем не менее, я уже остановился на отвратительно выглядящем, но эффективном чисто Java-подходе Юваля. - person Troy; 04.12.2008

Основываясь на других ответах, я создал следующий код для проверки статуса службы 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();
  } 
}
person Mohamed Samy    schedule 22.01.2014
comment
Спасибо @Mohamed Samy. Могу ли я узнать, как приведенный выше фрагмент может быть написан для нескольких удаленных серверов! также что означает термин «запрос» в построителе процессов. - person S K padala; 04.03.2016
comment
@SravanKumarPadala Для удаленного сервера просто добавьте \\имя_сервера в команду sc. Проверьте ссылку . \n query----------- Запрашивает состояние службы или перечисляет состояние типов служб. Запустите sc.exe, чтобы получить полную справку. - person Mohamed Samy; 06.03.2016
comment
Я добавил удаленный сервер как «sc \\remoteServer», но он выдает следующую ошибку: «Не удается запустить программу sc \\remoteServer: ошибка CreateProcess = 2, система не может найти указанный файл» - person S K padala; 07.03.2016
comment
@SravanKumarPadala, можешь попробовать следующее? Процесс процесса = новый ProcessBuilder(C:\\Windows\\System32\\sc.exe, \\запрос имя_сервера, имя_службы).start(); - person Mohamed Samy; 07.03.2016

Я имею дело с установщиками в течение многих лет, и хитрость заключается в том, чтобы создать свой собственный EXE-файл и вызвать его при установке. Это обеспечивает хорошую гибкость, например отображение точных сообщений об ошибках в случае возникновения ошибки, а также возвращаемые значения на основе успеха, чтобы ваш установщик знал о том, что произошло.

Вот как запускать, останавливать и запрашивать состояния для служб Windows (C++): http://msdn.microsoft.com/en-us/library/ms684941(VS.85).aspx (VB и C# предлагают аналогичные функции)

person David    schedule 02.12.2008

В прошлом мне повезло с Java Service Wrapper. В зависимости от вашей ситуации вам может потребоваться заплатить, чтобы использовать его. Но он предлагает чистое решение, которое поддерживает Java и может быть использовано в среде InstallAnywhere (я думаю) с небольшими трудностями. Это также позволит вам поддерживать службы на устройствах Unix.

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

person borq    schedule 02.12.2008

Выстрел в темноте, но взгляните на свою документацию по 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
person Community    schedule 02.12.2008

Вот прямое решение С#/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;
    };
}
person Wil S    schedule 21.10.2010

Во время запуска создайте файл с Файл.deleteOnExit().

Проверьте наличие файла в ваших сценариях.

person Aaron Digulla    schedule 02.12.2008

Просто вызовите этот метод, чтобы проверить статус службы, работает она или нет.

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;
}
person Muhammad Aasharib Nawshad    schedule 12.08.2020