从已打开的 CMD 中读取 - Java

3
有没有办法让Java应用程序从已经打开的CMD窗口中读取数据。例如,我打开了一个cmd窗口并运行了“dir”,然后决定运行我的应用程序,有没有办法让我的应用程序在不打开另一个窗口的情况下读取已经存在的CMD窗口中的信息?
更新: 我的希望是当一个Java应用程序运行时,它会检查任何当前打开的CMD窗口,以确保在它自己打开之前没有运行另一个命令行应用程序。

1
可能不需要,您能解释一下为什么需要吗?也许还有其他方法。 - assylias
4
不行,但你可以使用 ProcessBuilder 在 Java 中运行 dir 命令,并使用它的输出流读取内容。 - Rajeev Sreedharan
1
@RajeevSreedharan 感谢您的两次回复,我确实知道从ProcessBuilder中读取的能力。我的希望是,当运行一个Java应用程序时,它会检查任何当前打开的CMD窗口,以确保在它自己打开之前没有运行另一个命令行应用程序。 - John.Smith
3
@John.Smith 另一个应用程序还在运行吗?如果是这样,你可以检查正在运行的进程。如果不是,你可以查看上次运行的文件或数据库等信息。 - assylias
@RajeevSreedharan 抱歉,但是你刚才说的话让我一头雾水,什么是单个实例?就像文件只能一次运行一样吗? - John.Smith
显示剩余3条评论
1个回答

1
只需将执行命令的输出存储到文件中。
例如:执行 dir > spool.txt 命令,并从 java 程序使用 FileInputStream 打开 spool.txt 文件。
为确保内容在读取前完全写入,您可以:
  • 在编写的文件中使用标记以指示它
  • 检查编写的文件的修改日期(如果修改日期在定义的时间段内不发生变化,则可能是写入完成的信号)

更新带有更新的问题:检查CMD窗口是否已打开

更新:我希望当运行一个Java应用程序时,它将检查当前打开的任何CMD窗口,以确保在它自己打开之前没有运行另一个命令行应用程序。

您可以使用 tasklist.exe 程序列出 Windows 上正在运行的进程。
通过每个进程获取一行信息。
然后,检查其中一行是否以 cmd.exe 开头。
如果是这样,则表示已经运行了一个 cmd.exe 程序。

以下是示例代码;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class CmdProcessSearch {

    public static void main(String[] args) throws IOException {
        boolean anyCmdProgramOpened = isAnyCmdProgramOpened();
        System.out.println("isOpened = " + anyCmdProgramOpened);
    }
    public static boolean isAnyCmdProgramOpened() {
        Process p;
        try {
            p = Runtime.getRuntime().exec(System.getenv("windir") + "\\system32\\" + "tasklist.exe");
            String line;
            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            while ((line = input.readLine()) != null) {
                System.out.println(line);
                if (line.startsWith("cmd.exe")) {
                    return true;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }
}

C:\windows\system32通常在PATH环境变量中。
因此,p = Runtime.getRuntime().exec("tasklist.exe");应该足够了, 但为了防止任何副作用或配置问题,最好指定绝对路径。


新评论的新更新:检查Java应用程序是否正在运行

我已经在不同的部分使用了这个代码,但如果有一个命令窗口正在运行,就不能保证用户已经使用它来运行我的程序,进程包;

在这种情况下,如果您可以在客户端机器上安装jdk工具,则可以检查是否正在运行Java进程,使用您的应用程序的主类作为主类。
您可以使用jpsJava虚拟机进程状态工具)。

这里是可用的选项:

选项

jps 命令支持多个选项,可以修改命令的输出。这些选项可能会在未来发生变化或被删除。

-q

省略类名、JAR 文件名和传递给主方法的参数的输出,仅输出本地 VM 标识符列表。

-m

输出传递给主方法的参数。对于嵌入式 JVM,输出可能为空。

-l

输出应用程序主类的完整包名或应用程序 JAR 文件的完整路径名。

-v

输出传递给 JVM 的参数。

-V

输出通过标志文件(.hotspotrc 文件或 -XX:Flags= 指定的文件)传递给 JVM 的参数。

-J 选项

将选项传递给 jps 调用的 java 启动器。例如,-J-Xms48m 将启动内存设置为 48 兆字节。通常使用 -J 将选项传递给执行 Java 编写的应用程序的底层 VM。

jps -l 命令输出应用程序主类的完整包名或应用程序JAR文件的完整路径名。

这是一个示例代码,通过搜索应用程序的主类process.JavaProcessSearch

package process;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class JavaProcessSearch {

    public static void main(String[] args) throws IOException {
        boolean isProcessRunning = isAJavaProcessWithMainClass("process.JavaProcessSearch");
        System.out.println(isProcessRunning);
    }

    public static boolean isAJavaProcessWithMainClass(String mainClass) {
        Process p;
        try {
             String javaHome = System.getenv("JAVA_HOME");
             p = Runtime.getRuntime().exec(javaHome + File.separator + "bin/jps -l");

            String line;
            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            while ((line = input.readLine()) != null) {
                System.out.println(line);
                if (line.contains(mainClass)) {
                    return true;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return false;
    }

}

如果您无法安装jdk工具,可以在客户端计算机上“某个地方”存储应用程序启动时的进程ID。您可以使用以下方法检索此信息:ManagementFactory.getRuntimeMXBean().getName()
当它不再运行(停止或崩溃)时,您可以删除此进程ID信息。
当应用程序启动时,在客户端计算机上检索到进程ID时,不允许应用程序启动。
对于已停止的应用程序情况,关闭挂钩应该可以完成任务。
对于崩溃的应用程序情况,您可以使用守护线程定期检查应用程序是否始终运行并依靠存储的进程ID。

抱歉,示例有误导性,请查看更新。 - John.Smith
我曾在另一个部分使用过这段代码,但如果有一个命令行窗口正在运行,我无法保证用户是否使用它来运行我的程序,我只知道他们可能在早些时候运行了ipconfig,但没有关闭窗口。 - John.Smith
在这种情况下,你只需要检查你的程序是否正在运行,可以使用jps -l命令。我已经更新了新的代码。 - davidxxx
那么,使用您提供的新代码,我只需要将“process.JavaProcessSearch”更改为“包名._类名_”吗? - John.Smith
我还遇到了一个错误:“无法运行程序'jps'”,我猜测这与“PATH”配置有关,这意味着我可能无法使用它,因为我无法保证用户已正确配置其计算机的“PATH”。 - John.Smith
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接