【问题标题】:Need to automate a batch file which takes two arguments runtime one after another需要自动化一个批处理文件,该批处理文件一个接一个地采用两个参数运行时
【发布时间】:2014-06-09 10:02:37
【问题描述】:

我想自动化一个批处理文件。这需要一个接一个地运行时的两个参数。

以下是我执行此批处理文件的手动步骤--

1-从命令行执行一个 ext.bat 文件。

2- 询问路径-

请输入代码路径

3-手动输入--c:/

4- 按回车键。

5- 询问文件夹名称。

请输入目录名

6-手动输入--mydir

7-按回车键。

有没有类似的期望(仅适用于 .sh 脚本)。

添加以下更多详细信息 ---

这个批处理文件在内部调用了一个独立的java类—— 以下是批处理文件

@echo off
setlocal
set classpath=C:\Users\abc\Documents\jar\instance.jar;%classpath%
"%JAVA_HOME%"\bin\java nstance.ABCUtil

这会一一提出两个问题。以下是类中的调用部分。

这个 ABCUtil 类

final Console console = System.console();
// Read Instance absolute directory from the console
final String DirHome = console.readLine(abc.HOME_ABSOLUTE_path);
final String Dir = console.readLine(abc.HOME_ABSOLUTE_DIR_name);

所以它只会从控制台获取价值......我不能这样打电话。这行不通。

java ABCUtil path dir

注意 - 我无法安装任何其他工具来执行此操作,例如 TCL、cygwin ETC。我的 M/C 有 os-windows 7 64 位

请帮助--亲爱的大师......

【问题讨论】:

  • 您要解决的真正问题是什么? meta.stackexchange.com/questions/66377/what-is-the-xy-problem。如果批处理文件运行 java 程序,您可以使用 process builder 或直接从 java 程序调用它。此外,如果这与 Jenkins 等远程执行/作业编排工具相关的事情可能会好得多。
  • 添加了附加信息..请帮助
  • 我首先回答了一个批处理解决方案,然后我看到你从 Console 读取的 java 代码:我更新了我的答案。

标签: java windows batch-file batch-processing expect


【解决方案1】:

如果你真的在寻找简单的 Windows 批处理解决方案,这里有一个源自 PostgreSQL 的批处理。

SET path=c:\
SET /P path="Path of code [%path%]: "

SET folder=\
SET /P folder="Folder name [%folder%]: "

REM and do what you want with those values ...
echo %path%
echo %folder%

此方法甚至允许提出默认值。

编辑

我刚刚看到你的 java 代码是从控制台而不是从标准输入读取的,所以没有重定向解决方案会有所帮助。也许你应该看看 SO How to simulate keyboard presses in java? 的以下帖子

EDIT2

所以问题不是我最初想到的批量询问参数,而是自动化一个在控制台上询问两个参数的java程序。机器人是自动化此类事情的好方法。我写了一段 java 来模拟它在键盘上输入的参数,然后输入。我自己的技巧是使用 Alt xyz 为任何字符发送正确的 KeyEvent。

你应该只做java -jar ...\RoboSend.jar "ext.bat" "real_path" "real_folder"java -jar ...\RoboSend.jar "ext.bat" %path% %folder%

package org.sba.robotsend;

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;

/**
 * This program simulates the typing of its arguments on Console keyboard.
 * Each argument is send via Robot to the console, followed by an Enter key
 * Ex : java -j RobotSend.jar "echo foo" "echo bar"  gives :
 *  c:\> echo foo
 *  foo
 *  c:\> echo bar
 *  bar
 *
 * It is intented to automate programs reading their input on the Console
 * 
 * @author serge.ballesta
 */
public class RobotSend {
    private Robot robot;
    private Charset cp850;
    private static final int[] keys = { KeyEvent.VK_NUMPAD0, KeyEvent.VK_NUMPAD1,
         KeyEvent.VK_NUMPAD2, KeyEvent.VK_NUMPAD3, KeyEvent.VK_NUMPAD4,
         KeyEvent.VK_NUMPAD5, KeyEvent.VK_NUMPAD6, KeyEvent.VK_NUMPAD7,
         KeyEvent.VK_NUMPAD8, KeyEvent.VK_NUMPAD9
    };

    /**
     * This program simulates the typing of its arguments on Console keyboard.
     * Each argument is send via Robot to the console, followed by an Enter key
     * Ex : java -j RobotSend.jar "echo foo" "echo bar"  gives :
     *  c:\> echo foo
     *  foo
     *  c:\> echo bar
     *  bar
     *
     * It is intented to automate programs reading their input on the Console
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        RobotSend robot = new RobotSend();

        try {
            robot.run(args);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void run(String[] args) throws AWTException {
        robot = new Robot();
        cp850 = Charset.forName("IBM850");
        for (String str: args) {
            sendString(str);
        }
    }

    /**
     * Send a byte using the Alt xyz sequence.
     * the byte must be in CP850 code page, indipendently of the actual code
     * page of the console (at least for System natively in CP850 ...)
     * @param c the byte (char) to be inputted via keyboard
     */
    public void sendByte(byte c) {
            int i = (int) c;
            if (i < 0) { i = 256 + i; }
            if (i < 0  || i > 255) { i = 'X'; }
            int i1 = i / 100;
            int i2 = (i % 100) / 10;
            int i3 = i % 10;
            robot.keyPress(KeyEvent.VK_ALT);
            robot.keyPress(keys[i1]);
            robot.keyRelease(keys[i1]);
            robot.keyPress(keys[i2]);
            robot.keyRelease(keys[i2]);
            robot.keyPress(keys[i3]);
            robot.keyRelease(keys[i3]);
            robot.keyRelease(KeyEvent.VK_ALT);
    }

    /**
     * Simulate a Enter
     */
    public void sendEnter() {
        robot.keyPress(KeyEvent.VK_ENTER);
        robot.keyRelease(KeyEvent.VK_ENTER);
    }

    /**
     * Send a String via the Console keyboard.
     * The string is first encoded in CP850, sent one char at a time via sendByte
     * and followed by an Enter key
     * @param str 
     */
    public void sendString(String str) {
        ByteBuffer buf = cp850.encode(str);
        for (byte b: buf.array()) {
            sendByte(b);
        }
        sendEnter();
    }
}

【讨论】:

  • 亲爱的 Serge-- 在上面的脚本中,我应该将 ext.bat 作为它的设置路径仅用于两个 args。我认为它需要人工干预
  • 如果您可以使用 args 调用 ext.bat,只需在批处理末尾添加 call ext.bat %path% %folder% ...但另请参阅我的编辑。
  • 不,正如我在问题中所说的,我不能用 args 调用批处理:(
  • 非常感谢亲爱的塞尔吉。根据你的建议,我做到了。作为回答,我已经输入了整个代码。它的工作非常出色。谢谢拥抱~你。 +50 给你.... :)
  • @smriti 我刚刚完成了我的测试(同时去吃饭:-))。它似乎有效,请参阅我更新的帖子中的代码。
【解决方案2】:

Java 确实有执行命令行命令的方法。使用以下代码行运行命令行命令:Runtime.getRuntime().exec("my command"); 其中“my command”是您要执行的行,例如运行批处理文件。

正在发生的事情是 Java 代码正在获得一个“运行时”,它基本上是一个控制台。在 Java 代码中执行字符串与在命令行中键入命令的效果相同。

对于您的问题,将文件和目录输入转换为字符串,然后将这些字符串用作批处理文件的参数。将该命令构建为一个新字符串,并附加参数,然后运行该命令。还要确保在命令前面包含“cmd”,因为这将实际执行批处理文件。

例如,Runtime.getRuntime().exec("my command" + " " + arg1 + " " + arg2);

有人问过类似的问题,所以看看他们是如何解决这个问题的。 How do I run a batch file from my Java Application?

还请查看以下链接,因为它可能会提供有用且相关的示例。 http://omtlab.com/java-how-to-run-exe-file-and-batch-file-using-java-program/

【讨论】:

  • Jonathan 感谢您的调查;我试过这个。但是批处理文件是-不接受这样的参数..不知道为什么:(。批处理文件在内部调用了一个java文件。在java中它从控制台获取两个参数。请提出它不接受的原因是什么来自 exec 方法的参数...
  • 只是为了突出一件事,即使我直接调用java类,如--java myclass args1 args2。它不工作。因为它需要一个一个...我的意思是如果程序对第一个 arg 感到满意,那么它会要求第二个;我不应该改变 java 类的方式...
  • 您是在尝试从您的 java 代码中自动执行批处理文件,还是尝试从批处理文件中执行一个 java 类?我发布的代码假设您正在尝试从 java 程序执行批处理文件。
  • 基本上——我正在运行一个用于自动化的 java 类。它调用这个批处理文件。这个批处理文件(称为可执行的 java 文件)具有不同的所有者,我无法修改或更改。批处理文件只有 --%JAVA_HOME%/bin/java myclass
  • 确保您的路径变量设置正确,也许可以尝试在批处理文件中明确列出 java 的路径。我将通过编辑我的答案来提供链接/其他相关建议,所以看看那里
【解决方案3】:

*使用机器人类。

首先从 java exec 代码打开批处理文件并模拟键盘按键 ...*

//@Author Smriti.

import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.lang.reflect.Field;



public class TestExpect {

    /**
     * @param args
     */
    public static void main(String[] args) {

        // TODO Auto-generated method stub

    String filePath="C:/ext.bat";

        try {
            Process p = Runtime.getRuntime().exec("cmd /c start"+filePath);

        } catch (IOException e1) {
            // TODO Auto-generated catch block
        System.out.println(e1.getMessage());    
        e1.printStackTrace();
        }


        try {


                Robot robot = new Robot();
                typeCharacter(robot, "c");
                robot.keyPress(KeyEvent.VK_SHIFT);
                robot.keyPress(KeyEvent.VK_SEMICOLON);
                robot.keyRelease(KeyEvent.VK_SEMICOLON);
                robot.keyRelease(KeyEvent.VK_SHIFT);
                robot.keyPress(KeyEvent.VK_ENTER);
                typeCharacter(robot, "c");
                robot.keyPress(KeyEvent.VK_SHIFT);
                robot.keyPress(KeyEvent.VK_SEMICOLON);
                robot.keyRelease(KeyEvent.VK_SEMICOLON);
                robot.keyRelease(KeyEvent.VK_SHIFT);
                robot.keyPress(KeyEvent.VK_SLASH);
                typeCharacter(robot, "i");
                typeCharacter(robot, "n");
                typeCharacter(robot, "s");
                typeCharacter(robot, "t");
                typeCharacter(robot, "1");
                robot.keyPress(KeyEvent.VK_ENTER);

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

     public static void typeCharacter(Robot robot, String letter)
        {
            try
            {
                boolean upperCase = Character.isUpperCase( letter.charAt(0) );
                String variableName = "VK_" + letter.toUpperCase();

                Class clazz = KeyEvent.class;
                Field field = clazz.getField( variableName );
                int keyCode = field.getInt(null);

                robot.delay(1000);

                if (upperCase) robot.keyPress( KeyEvent.VK_SHIFT );

                robot.keyPress( keyCode );
                robot.keyRelease( keyCode );

                if (upperCase) robot.keyRelease( KeyEvent.VK_SHIFT );
            }
            catch(Exception e)
            {
                System.out.println(e);
            }
        }

}

【讨论】:

  • 请问您在这个解决方案中的原始问题的expect("Please enter the path for code") 请求在哪里?请参阅我的答案中的编辑...
  • 感谢@Aacini 的帮助和时间,我删除了期望,因为我想打开窗口的命令提示符,这也可以通过 exec 命令完成,打开后我调用机器人类来模拟键盘打字,这就是我要找的。顺便说一句,我尝试使用您编辑的代码再次失败 --"'cscript' is not Recognized as an internal or external command,"
  • 如果你开始赏金,你应该非常小心,如果你在运行中更改规范。您应该确保更改不会对参与由赏金点吸引的主题的任何回答者造成不利或利益。毕竟,这是赏金的目的,不是吗? :(
【解决方案4】:

虽然您要求的是 Java 解决方案,但显然您也可以运行 Batch 文件,因此我编写了一个 Batch 文件解决方案。嗯,它确实是一个 Batch-JScript 混合脚本,它充分利用了 WSH WScript.Shell.Exec 方法特性,可以访问执行过程的 Stdin 和 Stdout 通道。当然,如果您愿意,也可以只取出 JScript 代码。

@if (@CodeSegment == @Batch) @then

@echo off
cscript //nologo //E:JScript "%~F0"
goto :EOF

@end

// Execute the bat file
var batFile = new ActiveXObject("WScript.Shell").Exec("c:\\ext.bat");

// Expect the first prompt
while ( batFile.StdOut.ReadLine() != "Please enter the path for code" );

// Respond to first prompt
batFile.StdIn.WriteLine("c:\\");

// Expect the second prompt
while ( batFile.StdOut.ReadLine() != "Please enter the directory name" );

// Respond to second prompt
batFile.StdIn.WriteLine("test");

编辑:在您的问题中,您似乎需要识别(等待)特定提示。但是,如果您只想将键输入到键盘缓冲区中,您可以通过 JScript Sendkeys 方法以更简单的方式执行此操作:

@if (@CodeSegment == @Batch) @then

@echo off
cscript //nologo //E:JScript "%~F0"
goto :EOF

@end

var WshShell = WScript.CreateObject("WScript.Shell");
WshShell.Exec("c:\\ext.bat");
WshShell.SendKeys("c:\\{ENTER}");    
WshShell.SendKeys("test{ENTER}");

【讨论】:

  • 亲爱的 Aacini-- 我在这里复制了脚本格式并保存为 sol.bat。我收到以下错误 - C:\ext.bat(16, 32) Microsoft JScript 编译错误:未终止的字符串常量。我在那里仔细检查了没有未终止的字符串,请查看,第二点 - 在我运行这个 bat 文件之前,我需要安装/设置一些路径吗?我在win7上运行,没有像vb等特定的ms工具......等待你的回复..
  • 糟糕,我的错误! 1. 您需要将两行中的引号内的反斜杠加倍:"c:\\...";我已经在上面的代码中做到了。 2. 你不需要任何额外的东西就可以在任何电脑上运行这个程序,从 Win XP 开始。更多详情请见:msdn.microsoft.com/en-us/library/yek4tbz0(v=vs.84).aspx
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-24
  • 1970-01-01
  • 1970-01-01
  • 2012-12-18
  • 2010-10-18
  • 2018-01-23
  • 1970-01-01
相关资源
最近更新 更多