【问题标题】:How to change command prompt (console) window title from command line Java app?如何从命令行 Java 应用程序更改命令提示符(控制台)窗口标题?
【发布时间】:2010-11-02 22:00:00
【问题描述】:

如何从 java 命令行应用程序更改和更新命令提示符窗口的标题?每次我运行我的应用程序时,命令提示符窗口标题都会显示: C:\WINDOWS\system32\cmd.exe - java MyApp.

我想在 java 程序运行时更改和更新窗口标题,例如 wget(win32) 更新标题中的下载状态:Wget [12%]

【问题讨论】:

    标签: java windows command-line


    【解决方案1】:

    虽然我自己没有尝试过,但在 Windows 中,可以使用 Win32 API 调用 SetConsoleTitle 来更改控制台的标题。

    但是,由于这是对本机库的调用,因此需要使用 Java Native Interface (JNI) 之类的东西才能进行调用,这仅适用于 Windows 2000 及更高版本。

    编辑 - 使用 JNI 的解决方案

    以下是使用 JNI 来更改 Windows 中 Java 控制台窗口标题的示例。要实现这一点,先决条件是了解 C 语言并使用编译器/链接器。

    首先,结果如下:


    (来源:coobird.net

    免责声明:这是我第一个使用 JNI 的 Java 应用程序,因此它可能不是一个很好的使用示例——我根本不执行任何错误检查,而且我可能会遗漏一些细节.

    Java 程序如下:

    class ChangeTitle {
    
        private static native void setTitle(String s);
    
        static {
            System.loadLibrary("ChangeTitle");
        }
    
        public static void main(String[] args) throws Exception {
    
            for (int i = 0; i < 5; i++) {
                String title = "Hello! " + i;
                System.out.println("Setting title to: " + title);
                setTitle(title);
                Thread.sleep(1000);
            }
        }
    }
    

    基本上,标题每 5 秒更改一次,方法是调用名为 ChangeTitle 的外部原生库中的 setTitle 原生方法。

    一旦上面的代码被编译成ChangeTitle.class文件,javah命令被用来创建一个C头文件,在创建C库时使用。

    编写原生库

    编写库将涉及针对 javah 生成的 C 头文件编写 C 源代码。

    ChangeTitle.h 标头如下:

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class ChangeTitle */
    
    #ifndef _Included_ChangeTitle
    #define _Included_ChangeTitle
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     ChangeTitle
     * Method:    setTitle
     * Signature: (Ljava/lang/String;)V
     */
    JNIEXPORT void JNICALL Java_ChangeTitle_setTitle
      (JNIEnv *, jclass, jstring);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    

    现在,实现,ChangeTitle.c

    #include <windows.h>
    #include <stdio.h>
    #include <conio.h>
    #include <jni.h>
    #include "ChangeTitle.h"
    
    JNIEXPORT void JNICALL
    Java_ChangeTitle_setTitle(JNIEnv* env, jclass c, jstring s) {
        const jbyte *str;
        str = (*env)->GetStringUTFChars(env, s, NULL);
    
        SetConsoleTitle(str);
    
        (*env)->ReleaseStringUTFChars(env, s, str);
    };
    

    传递给本机函数的String 被更改为 UTF-8 编码的 C 字符串,该字符串被发送到 SetConsoleTitle function,正如函数名称所暗示的那样,它会更改控制台的标题。

    (注意:将字符串传入SetConsoleTitle 函数可能会出现一些问题,但根据文档,它也接受Unicode。我不太确定上面的代码会如何工作发送各种字符串时。)

    以上基本上是从The Java Native Interface Programmer's Guide and SpecificationSection 3.2: Accessing Strings获得的示例代码,以及来自MSDN的SetConsoleTitle Function页面。

    如需更多涉及错误检查的示例代码,请参阅Section 3.2: Accessing StringsSetConsoleTitle Function 页面。

    构建 DLL

    我花了最多时间弄清楚的部分是将 C 文件编译成一个 DLL,实际上可以读取该 DLL 而不会导致UnsatisfiedLinkError

    经过大量搜索和尝试,我能够将 C 源代码编译为可以从 Java 调用的 DLL。由于我使用的是MinGW,所以我找到了一个页面表单mingw.org,其中described exactly how to build a DLL for JNI

    来源:

    【讨论】:

    • 请不要把所有的精力都花在做 JNI 上,转至 jna.dev.java.net。使用 JNA 比使用 JNI 容易得多。这是自 Python ctypes 以来最好的东西。
    【解决方案2】:

    这是我使用 JNA 的解决方案:

    import com.sun.jna.Library;
    import com.sun.jna.Native;
    import com.sun.jna.Platform;
    
    public class SetTitle {
    
        public interface CLibrary extends Library {
            CLibrary INSTANCE = (CLibrary)
                Native.loadLibrary((Platform.isWindows() ? "kernel32" : "c"),
                                   CLibrary.class);
    
            boolean SetConsoleTitleA(String title);
        }
    
        public static void main(String[] args) {
            CLibrary.INSTANCE.SetConsoleTitleA("Testing 123");
            System.exit(0);
        }
    }
    

    【讨论】:

    • 在现代 JNA (net.java.dev.jna) 中,Native.loadLibrary 已被弃用,取而代之的是 Native.load,并且 (CLibrary) 强制转换是多余的。否则很好的答案!
    【解决方案3】:

    这取决于您的终端模拟器,但本质上它只是将控制序列打印到控制台。

    现在我不清楚 CMD.EXE 响应什么控制序列(我没有可以尝试这个),但我听说有一个名为 TITLE 的命令可以设置窗口的标题。我尝试将 TITLE 的输出通过管道传输到文件,但显然,它实际上并没有通过输出控制字符来设置标题。 START 命令可以带一个参数,该参数是窗口的标题,后面是要在窗口中运行的命令。所以像

    cmd TITLE "lovely Application that is in a command window." && "java" MyApp
    REM or
    start "lovely Application that is java based." java MyApp
    

    就我个人而言,我只是将整个内容与一个快捷方式捆绑在一起,您可以在其中编辑当前目录、命令、它的参数以及窗口大小、样式和标题等属性(如果我没记错的话)。给它一个漂亮的图标,人们就会使用它。

    【讨论】:

    • 他希望在程序运行时更改标题,而不仅仅是在从命令行界面启动 Java 应用程序时。
    • 是的,我知道,所以我告诉某人在 cmd 中找到标题更改的转义序列(它必须存在但我找不到它,即使在 ANSI.SYS 中),或者询问者可以在需要时使用 Java.lang.runtime 来执行 title 命令。如果这适用于同一个窗口。
    • 不幸的是,使用带有“title”的 Runtime.exec 不起作用——至少从我的尝试来看,我无法让它工作。我怀疑这是因为 Runtime.exec 将启动一个与当前运行 java.exe 的进程分开的新进程。
    • 没错。 Runtime.exec 产生新进程。是的,我正在寻找即时更新标题的解决方案。
    【解决方案4】:

    遵循 dlamblin 的启示 ;-) 这是一个python代码。 请注意,大多数编程语言中有 2 种不同的命令:

    • 系统
    • 执行

    system 将发出系统命令,exec 确实产生了一个新进程。因此:

    C:\>python
    >>> import os
    >>> os.system("title berry tsakala")
    

    在正在运行的程序中工作。只需找到 j​​ava 等效项即可。

    【讨论】:

    • 谢谢,这正是我想要的。 (stackoverflow)系统有效!
    • 拒绝投票,因为这甚至没有接近回答“如何更改窗口标题 IN JAVA?”
    猜你喜欢
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-02
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多