有谁知道如何检测Windows服务是否通过Java运行

时间:2010-04-13 13:34:32

标签: java windows-services

有关运行Java应用程序作为服务的大量信息,但我需要知道如何检测Windows服务是否正在运行。有谁知道怎么???

在DOS提示符下,我可以运行:

tasklist /svc|findstr "NonRunningService"
echo Return code for N onRunningService is %ERRORLEVEL%
tasklist /svc|findstr "RunningService"
echo Return code for RunningService is %ERRORLEVEL%

我得到以下内容:

Return code for NonRunningService is 1
Return code for RunningService is 0

在代码中,我有:

int retCode = Runtime.getRuntime.exec("tasklist /svc|findstr \"NonRunningService\"").waitFor();
System.out.println("Return code for NonRunningService is " + retCode);
retCode = Runtime.getRuntime.exec("tasklist /svc|findstr \"RunningService\"").waitFor();
System.out.println("Return code for RunningService is " + retCode);

我得到以下输出

Return code for NonRunningService is 1
Return code for RunningService is 1

根据JavaDocs,waitFor()应该阻塞,直到进程结束,并给出进程的退出值。

我也尝试过使用Process / ProcessBuilder命令行调用:

//'tasklist /nh /fi "SERVICES eq RunningService"' will return a line for 
// each running service of the requested type.
Process p1 = new ProcessBuilder("tasklist", "/nh", "/fi" "SERVICES eq RunningService").start();
p1.waitFor();
BufferedReader is = new BufferedReader(new InputStreamReader(p1.getInputStream()));
String line = is.readLine();
System.out.println("Service - " + line);
System.out.println("Running? ", (line==null?"No":"Yes");

给出:

Service -
Running? No

即使我在命令行的输出中获得了行!

4 个答案:

答案 0 :(得分:2)

我通过创建一个类来打印来自进程的输出来重新创建代码并添加一些额外的调试输出:

private static class Writer implements Runnable {

    private InputStream is;

    public Writer(InputStream is) {
        this.is = is;
    }

    @Override
    public void run() {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
}

在main方法中,我在调用waitFor()之前启动了一个实例:

public static void main(String[] args) throws Exception {
    String command = "tasklist /svc | findstr \"svchost.exe\"";
    Process p = Runtime.getRuntime().exec(command);

    new Thread(new Writer(p.getInputStream())).start();
    new Thread(new Writer(p.getErrorStream())).start();

    System.out.println("Return code: " + p.waitFor());

}

这个输出是:

ERROR: Invalid argument/option - '|'.
Type "TASKLIST /?" for usage.

因为命令没有在shell中执行,所以首先需要调用Windows shell,并将命令作为参数传递:

String command = "cmd /c tasklist /svc | findstr \"svchost.exe\"";

更改此设置后,输出现为Return code: 0

我发现了一个奇怪的问题,因为如果你不处理进程的stdout通道的输出,由于某种原因,进程不会终止。为了解决这个问题,我不得不放入一个循环来读取并丢弃该过程的输出:

public static void main(String[] args) throws Exception {
    String command = "cmd /c tasklist /svc | findstr \"svchost.exe\"";
    Process p = Runtime.getRuntime().exec(command);
    while(p.getInputStream().read() != -1) {} //hangs without this line

    System.out.println("Return code: " + p.waitFor());

}

答案 1 :(得分:1)

这是我用来查找索引服务是否已启动并运行的内容:

为此,您必须知道服务的名称并使用SC命令:

public boolean isIndexingServiceOperational() {
    String[] result = getResultFor("SC QUERY \"CiSvc\"");
    if (result != null) {
        if (!result[0].contains("does not exist")) {
            return true;
        }
    }
    return false;
}

public boolean isIndexingServiceRunning() {
    String[] result = getResultFor("SC QUERY \"CiSvc\"");
    if (result != null) {
        if (result[0].contains("RUNNING")) {
            return true;
        }
    }
    return false;
}

private String[] getResultFor(String command) {
    try {
        Process p = Runtime.getRuntime().exec(command);
        BufferedInputStream in = new BufferedInputStream(p.getInputStream());
        BufferedInputStream err = new BufferedInputStream(p
                .getErrorStream());
        StringBuffer inS = new StringBuffer();
        byte[] b = new byte[1024];
        while (in.read(b) != -1) {
            inS.append(new String(b));
        }
        StringBuffer errS = new StringBuffer();
        b = new byte[1024];
        while (err.read(b) != -1) {
            errS.append(new String(b));
        }
        in.close();
        err.close();
        return new String[] { inS.toString(), errS.toString() };
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

答案 2 :(得分:0)

这是一个疯狂的猜测。您的waitFor似乎在错误的位置。我会在进程运行时读取,然后等待退出:

Process p1 = new ProcessBuilder("tasklist", "/nh", "/fi" "SERVICES eq RunningService").start();
BufferedReader is = new BufferedReader(new InputStreamReader(p1.getInputStream()));
String line = is.readLine();
System.out.println("Service - " + line);
System.out.println("Running? ", (line==null?"No":"Yes");
p1.waitFor();

您还可以重定向错误流以确保阅读所有输出:

p1.redirectErrorStream(true);

答案 3 :(得分:0)

您的第一个示例是失败的,因为您无法在运行时#exec中使用shell或命令/ cmd功能(管道)。

正如已经指出的那样,您的第二个示例看起来没问题,但您粘贴的代码与您指称的输出不符。如果line确实为空,则第一个println将写入“Service - null”而不是“Service - ”。根据第一个println的输出,line必须是空字符串(“”),但在这种情况下,第二个println将打印“是”而不是“否”。