簡體   English   中英

需要一種以編程方式檢查 Windows 服務狀態的方法

[英]Need a way to check status of Windows service programmatically

這是情況:

我被要求使用 InstallAnywhere 8,這是一個基於 Java 的安裝程序 IDE,它允許啟動和停止 Windows 服務,但沒有內置方法來查詢它們的狀態。 幸運的是,它允許您在 Java 中創建可以在安裝過程中隨時調用的自定義操作(通過我認為是相當復雜的 API)。

我只需要一些可以告訴我特定服務是啟動還是停止的信息。

IDE 還允許調用批處理腳本,因此這也是一個選項,盡管腳本運行后,幾乎無法驗證它是否成功,因此我試圖避免這種情況。

歡迎任何建議或批評。

這就是我必須做的。 它很丑,但效果很好。

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

根據其他答案,我構建了以下代碼來檢查 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();
  } 
}

我多年來一直與安裝程序打交道,訣竅是創建自己的 EXE 並在安裝時調用它。 這提供了良好的靈活性,例如在發生錯誤時顯示精確的錯誤消息,並具有基於成功的返回值,以便您的安裝人員知道發生了什么。

以下是如何啟動、停止和查詢 windows 服務 (C++) 的狀態: http : //msdn.microsoft.com/en-us/library/ms684941 (VS.85) .aspx (VB 和 C# 提供類似功能)

過去我在 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

班上:

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 解決方案。

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

在啟動期間,使用File.deleteOnExit()創建一個文件。

檢查腳本中是否存在該文件。

只需調用此方法即可檢查服務的狀態是否正在運行。

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

我即興創作了給定的解決方案,使其獨立於語言環境。 正如亞歷杭德羅·岡薩雷斯 (Alejandro González) 正確指出的那樣,比較字符串“RUNNING”在非英語語言環境的系統中不起作用。

我使用sc 詢問並查找它返回的狀態代碼。

主要是,該服務可以有 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();
    }
}

希望這對某人有所幫助:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM