在 Java 中使用 ProcessBuilder 的问题
Posted
技术标签:
【中文标题】在 Java 中使用 ProcessBuilder 的问题【英文标题】:Problems using ProcessBuilder with Java 【发布时间】:2021-08-09 23:21:36 【问题描述】:我试图让几个 .bat 文件从一个文件夹运行,得到一个错误,只有第一个 bat 运行,其他的被忽略。
final String direct = "FOLDER";
File[] archives ;
File diretorio = new File(direct);
archives = diretorio.listFiles();
try
for (int i = 0; i < archives.length; i++)
ProcessBuilder pb = new ProcessBuilder(archives[i].getPath());
Process p = pb.start();
//Only for printing the commands
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String trace = null;
while ((trace = reader.readLine()) != null)
System.out.println(trace);
catch (IOException e)
e.printStackTrace();
【问题讨论】:
您能否编辑您的帖子并包括您的故障排除步骤?例如,reader.readLine()
是否永远不会返回 null,这就是为什么您的程序永远不会尝试启动第二个?
【参考方案1】:
-
确保您实际处理的是
.bat
批处理文件。
请务必关闭阅读器,以便释放资源。
完成后销毁进程以释放资源。
这应该可行:
File[] archives;
File diretorio = new File(direct);
archives = diretorio.listFiles();
try
for (int i = 0; i < archives.length; i++)
// Is it a .bat file
String fileName = archives[i].getName();
if (!fileName.contains(".")
|| !fileName.substring(fileName.lastIndexOf(".")).equalsIgnoreCase(".bat"))
// No...
continue;
if (archives[i].isFile() && archives[i].canExecute())
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/C", archives[i].getPath());
Process p = pb.start();
//Only for printing the commands
// 'Try With Resources' used here to auto-close reader.
try (java.io.BufferedReader reader = new BufferedReader(new java.io.InputStreamReader(p.getInputStream())))
String trace = null;
while ((trace = reader.readLine()) != null)
System.out.println(trace);
p.waitFor();
p.destroy(); // In case of abnormal process termination though 'waitFor()'.
catch (IOException | InterruptedException e)
e.printStackTrace();
更新:
代码已根据有效的 cmets 进行了更新。 Process#waitFor() 在此更新后的代码中使用。
在 Windows 操作系统中,批处理文件通过 Windows 命令处理器(命令提示符)运行,但如果在 Windows 文件资源管理器中双击批处理文件,则可以通过 Windows 文件关联运行。
如果关联可用,则以前版本的代码应该可以工作
ProcessBuilder pb = new ProcessBuilder(archives[i].getPath());
但有时 .bat 文件的关联可能会无意中与文本编辑器关联,或者注册表中的设置已被篡改。一旦您使用 Open With 对话框或默认程序为 .bat 文件设置了文件关联,显然无法使用用户界面恢复到默认设置。解决此问题的唯一方法是更改注册表中的设置。您可以按照以下步骤进行操作:
在继续之前,请创建一个系统还原点作为安全措施。错误修改 Windows 注册表可能会导致严重问题。
-
打开记事本或您喜欢的文本编辑器。
复制以下行并将其粘贴到记事本中:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.bat]
@="batfile"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\batfile\shell]
@=-
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\batfile\shell\open\command]
@="\"%1\" %*"
[-HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.bat]
-
使用具有 .reg 扩展名的任何名称保存文件,例如
BAT_File_Association.reg
双击BAT_File_Association.reg应用配置
进入注册表。在提示输入时单击 Yes
确认。
您现在已修复批处理文件关联设置。批处理文件现在应该在双击时正确执行。你可以阅读更多关于这个here的信息。
无论如何,上面更新的代码现在将通过命令处理器 (cmd.exe) 运行批处理文件,并且再次...应该可以工作。因为我的系统有 .bat 文件关联,所以任何一种方式都适合我。
为确保您的批处理文件没有问题,请在每个 .bat 文件的顶部添加一个回显,例如:
@echo:Batch File 1
... the rest of batch file code ...
随着每个 bat 文件的运行,您应该会在控制台窗口中看到:
Batch File 1
Batch File 2
Batch File 3
etc
【讨论】:
使用 waitFor(timeout) 比使用 destroy() 更好 - 这允许进程正常结束并在杀死它之前检查退出状态。 @that-other-guy 我试图在没有时间的情况下运行,但它只运行第一个(出于某种原因,不要全部运行) @DevilsHnd 我尝试运行此代码,它识别 .bat 文件但不会运行任何【参考方案2】:@DevilsHnd 代码效果很好! 问题出在带有“暂停”命令的 .bat 文件上。
【讨论】:
是的...这样就可以了。顺便说一句,这应该是评论而不是答案。 ://以上是关于在 Java 中使用 ProcessBuilder 的问题的主要内容,如果未能解决你的问题,请参考以下文章
在 Java 中使用 ProcessBuilder 读取输出 git-bash
为啥我在 ProcessBuilder --Java 中收到 IllegalThreadStateException 错误?
无法从 Java 进程(Runtime.getRuntime().exec() 或 ProcessBuilder)读取 InputStream