继上一篇Process应用之惑后,继续在为此不断修改,后来因为需求变化,又开始了process的进步一发掘。
先交代下背景。第三方软件发布了命令接口,根据执行发布的命令,可以得到第三方硬件的信息。而我现在需要软件直接执行我排好序的命令,以便获取硬件信息,这时需要做个远程的命令登陆,然后远程执行命令,再退出。这其实就好比要模拟telnet、ftp等的客户端,当远程登陆后执行一个指令,然后返回一大堆执行结果,从而实现与客户端的命令交互。
起先,去下了个common-net.jar的源码看了看,发现telnet、ftp等通信协议都是有专门的消息通道,产生专门的端口来做通讯传输。而这个第三方的命令接口只是个在dos下能执行命令的客户端,再说,即使人家做成了类似telnet的通信协议,俺也不可能知道人家用的端口啥啥的。那现在唯一能做的是,模拟DOS窗口,进行命令的交互。
有了这个思路,就又想到Process可是能执行命令的,那这个是不是可以呢!Process是为了执行命令而产生的一个独立的执行线程。理论上如果只要这个线程不被销毁,那么会一直可以执行命令。可是Process三个流InputStream、OutputStream、ErrorStream在API上说的是提供输出信息的,未知获得了这输入、输出流是否能干出一番事业呢!
1.自动执行命令的交互
试试直接就退出了,证明传进去的exit命令起作用了。之所以用sqlplus做替代的命令测试,因为其和我要做的第三方接口命令类似。
然后依据这个简单的测试封装了一个命令交互的类。直接上代码:
我在配置文件里设置如下:
测试方法:
测试结果如下:
真正做到了自动执行命令,并且获取到该命令的结果。
2.如果是想直接敲命令的互动,可是尝试如下:
看看测试结果:
和在dos下执行是完全一样的
产生process = Runtime.getRuntime().exec()时为什么要选择这种方式呢?为什么不是ProcessBuilder了呢?
我们现在不论使用哪种方式产生的命令执行进程都会读取进程的流,所以就不会再有流堵塞而导致无法执行下去的问题了。
ProcessBuilder在加入命令时是以数组的形式,如果是sqlplus orcl/orcl@db就需要分为两个参数加入,而现在我们更希望是一个命令是一个字符串。
有什么问题希望指正。
先交代下背景。第三方软件发布了命令接口,根据执行发布的命令,可以得到第三方硬件的信息。而我现在需要软件直接执行我排好序的命令,以便获取硬件信息,这时需要做个远程的命令登陆,然后远程执行命令,再退出。这其实就好比要模拟telnet、ftp等的客户端,当远程登陆后执行一个指令,然后返回一大堆执行结果,从而实现与客户端的命令交互。
起先,去下了个common-net.jar的源码看了看,发现telnet、ftp等通信协议都是有专门的消息通道,产生专门的端口来做通讯传输。而这个第三方的命令接口只是个在dos下能执行命令的客户端,再说,即使人家做成了类似telnet的通信协议,俺也不可能知道人家用的端口啥啥的。那现在唯一能做的是,模拟DOS窗口,进行命令的交互。
有了这个思路,就又想到Process可是能执行命令的,那这个是不是可以呢!Process是为了执行命令而产生的一个独立的执行线程。理论上如果只要这个线程不被销毁,那么会一直可以执行命令。可是Process三个流InputStream、OutputStream、ErrorStream在API上说的是提供输出信息的,未知获得了这输入、输出流是否能干出一番事业呢!
1.自动执行命令的交互
public class Demo { public static void main(String[] args) { Process process=null; BufferedOutputStream out=null; BufferedInputStream in=null; try { process=Runtime.getRuntime().exec("sqlplus ethiopia1103/ethiopia1103@db90"); out=new BufferedOutputStream(process.getOutputStream()); in=new BufferedInputStream(process.getInputStream()); out.write("exit".getBytes()); out.write("\r\n".getBytes()); out.flush(); BufferedReader br=new BufferedReader(new InputStreamReader(in)); String line=null; while((line=br.readLine())!=null){ if(line.indexOf(">")!=-1) break; System.out.println(line); } }catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { if(null!=out){ out.close(); out=null; } if(null!=in){ in.close(); in=null; } int value=process.waitFor(); if(null!=process) process.destroy(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
试试直接就退出了,证明传进去的exit命令起作用了。之所以用sqlplus做替代的命令测试,因为其和我要做的第三方接口命令类似。
然后依据这个简单的测试封装了一个命令交互的类。直接上代码:
public class DosCommandInteraction { private static Logger logger=Logger.getLogger(DosCommandInteraction.class); private static final String ENTER="\r\n"; //每次输入命令后回车,然后命令执行,出结果 private static final String END="> "; //遇到>时就退出,证明上一个命令已经执行完 private static final String ERROR="ERROR"; //登录时报ERROR就证明已经登录失败 private Process process=null; private BufferedOutputStream out=null; private BufferedInputStream in=null; /** * 登录到该命令下,创建执行命令的环境进程 * @param command 登陆命令 */ public boolean loggin(String command){ boolean flag=true; try { process=Runtime.getRuntime().exec(command); out=new BufferedOutputStream(process.getOutputStream()); in=new BufferedInputStream(process.getInputStream()); String result=writeCommandResult(in); //把登录时的信息取出来,判断是否登录成功!其实也为后面能正常输出命令结果做了清理 String[] lines=result.split(ENTER); for(String line :lines){ if(line.indexOf(ERROR)!=-1){ flag=false; break; } } }catch (IOException e) { // TODO Auto-generated catch block logger.error(e); close(); } if(!flag) close(); return flag; } /** * 将输入的命令转化为流执行命令得到执行的记录 * @param command * @return */ public List<String> execCommand(String command){ logger.info("exec command : "+command); InputStream input = new ByteArrayInputStream((command+ENTER).getBytes()); readerCommand(out,input); String result=writeCommandResult(in); logger.info(result); try { input.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return Arrays.asList(result.split(ENTER)); } /** * 将命令写入输出流 * @param outs 全局输出流 * @param ins 输入命令的流 */ private void readerCommand(OutputStream outs,InputStream ins){ int ch; try { while ((ch = ins.read()) != -1) { outs.write(ch); outs.flush(); } } catch (IOException e) { close(); logger.error("readerCommand",e); } } /** * 读取命令返回的结果 * @param ins 全局的输入流 * @return 命令结果 */ private String writeCommandResult(InputStream ins){ int length = -1; byte[] buffer = new byte[10240]; String readLine = null; StringBuilder readResult = new StringBuilder(""); try { while((length=ins.read(buffer))>0){ readLine = new String(buffer, 0 , length,"gbk"); readResult.append(readLine); if(readLine.indexOf(ERROR)!=-1) break; if(readResult.toString().endsWith(END)||readResult.toString().endsWith(END.trim())) break; } } catch (IOException e) { close(); logger.error("writeCommandResult",e); } return readResult.toString(); } /** * 所有命令执行完成后推出命令,关闭进程 */ public void quit(){ execCommand("quit"); close(); } /** * 关闭所有的流和进程 */ private void close(){ try { if(null!=out){ out.close(); out=null; } if(null!=in){ in.close(); in=null; } int value=process.waitFor(); logger.info("process end state :" +value); if(null!=process) process.destroy(); } catch (IOException e) { // TODO Auto-generated catch block logger.error(e); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
我在配置文件里设置如下:
<bean id="command" class="java.util.ArrayList"> <constructor-arg> <list> <value>sqlplus orcl/orcl@db</value> <value>select 1 from dual;</value> <value>select 2 from dual;</value> <value>select 3 from dual;</value> <value>select 4 from dual;</value> </list> </constructor-arg> </bean>
测试方法:
public void handler(){ List<String> commList=(List<String>) SpringUtil.getObject("command"); logger.info("start................."); DosCommandInteraction dos=new DosCommandInteraction(); if(!dos.loggin(commList.get(0))){ logger.info("connection error!"); return; } for(int i=1;i<commList.size();i++) dos.execCommand(commList.get(i)); dos.quit(); logger.info("end................."); }
测试结果如下:
main [2011-06-27 16:33:59] - start................. main [2011-06-27 16:33:59] - exec command : select 1 from dual; main [2011-06-27 16:33:59] - 1 ---------- 1 SQL> main [2011-06-27 16:33:59] - exec command : select 2 from dual; main [2011-06-27 16:33:59] - 2 ---------- 2 SQL> main [2011-06-27 16:33:59] - exec command : select 3 from dual; main [2011-06-27 16:33:59] - 3 ---------- 3 SQL> main [2011-06-27 16:33:59] - exec command : select 4 from dual; main [2011-06-27 16:33:59] - 4 ---------- 4 SQL> main [2011-06-27 16:33:59] - exec command : quit main [2011-06-27 16:33:59] - 从 Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options 断开 main [2011-06-27 16:33:59] - process end state :0 main [2011-06-27 16:33:59] - end.................
真正做到了自动执行命令,并且获取到该命令的结果。
2.如果是想直接敲命令的互动,可是尝试如下:
public class TwoDemo { public static void main(String[] args) { Process process = null; BufferedOutputStream out = null; BufferedInputStream in = null; try { process = Runtime.getRuntime().exec( "sqlplus orcl/orcl@db"); out = new BufferedOutputStream(process.getOutputStream()); in = new BufferedInputStream(process.getInputStream()); readWrite(in, out, System.in, System.out); //该方法借用common-net的测试例子部分的一个工具类的方法 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { if (null != out) { out.close(); out = null; } if (null != in) { in.close(); in = null; } int value = process.waitFor(); if (null != process) process.destroy(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static final void readWrite(final InputStream remoteInput, final OutputStream remoteOutput, final InputStream localInput, final OutputStream localOutput) { Thread reader, writer; reader = new Thread() { @Override public void run() { int ch; try { while (!interrupted() && (ch = localInput.read()) != -1) { remoteOutput.write(ch); remoteOutput.flush(); } } catch (IOException e) { // e.printStackTrace(); } } }; writer = new Thread() { @Override public void run() { try { Util.copyStream(remoteInput, localOutput); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } }; writer.setPriority(Thread.currentThread().getPriority() + 1); writer.start(); reader.setDaemon(true); reader.start(); try { writer.join(); reader.interrupt(); } catch (InterruptedException e) { } } }
看看测试结果:
SQL*Plus: Release 10.2.0.1.0 - Production on 星期一 6月 27 16:45:58 2011 Copyright (c) 1982, 2005, Oracle. All rights reserved. 连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options SQL> select * from dual; DU -- X SQL> select 1 from dual; 1 ---------- 1 SQL> exit 从 Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options 断开
和在dos下执行是完全一样的
产生process = Runtime.getRuntime().exec()时为什么要选择这种方式呢?为什么不是ProcessBuilder了呢?
我们现在不论使用哪种方式产生的命令执行进程都会读取进程的流,所以就不会再有流堵塞而导致无法执行下去的问题了。
ProcessBuilder在加入命令时是以数组的形式,如果是sqlplus orcl/orcl@db就需要分为两个参数加入,而现在我们更希望是一个命令是一个字符串。
有什么问题希望指正。
相关推荐
在.NET框架中,C#提供了一种方便的方式来与操作系统交互,包括执行DOS命令,这就是通过使用`System.Diagnostics.Process`类。本篇文章将详细介绍如何利用`Process`类在C#中调用DOS命令,以及相关的核心概念和步骤。 ...
这些文件可能包含了如何使用C#来模拟DOS命令,比如执行ping(ICMP协议的命令)或其他网络相关的命令的实例。 8. **学习和调试**: 对于初学者,可以通过打开`ICMP_App.sln`在Visual Studio中查看和运行项目,理解...
首先,执行DOS命令的核心在于使用`System.Diagnostics.Process`类。这个类提供了启动外部进程、与之通信以及控制其生命周期的能力。在C#中,我们可以通过以下方式创建并执行一个DOS命令: ```csharp using System....
在Java编程中,有时我们需要与操作系统进行交互,执行一些DOS命令,比如创建文件、删除文件、拷贝文件等。这种需求通常是通过Java的Runtime类或者ProcessBuilder类来实现的。下面将详细介绍如何使用Java执行DOS命令...
1. **使用System.Diagnostics命名空间**:在C#中,我们可以利用`System.Diagnostics`命名空间中的`Process`类来启动外部程序,包括执行DOS命令。 2. **创建Process对象**:首先,创建一个`Process`对象,然后设置它...
总之,VC调用DOS命令是通过C++程序与操作系统进行交互的一个重要手段,它允许开发者在C++环境中执行各种系统级操作,增强了程序的功能性和灵活性。而“windows补丁安装器”则是一个实际应用案例,展示了这种技术在...
下面将详细阐述如何在C#中执行DOS命令以及相关的知识点。 首先,导入System.Diagnostics命名空间,这是执行DOS命令的基础: ```csharp using System.Diagnostics; ``` 然后,创建一个ProcessStartInfo对象,设置...
总结起来,C#执行DOS命令主要涉及`System.Diagnostics.Process`类的使用,包括设定命令、处理命令执行后的退出行为以及重定向输出。掌握这一技巧,对于编写需要与操作系统底层交互的应用程序是非常有用的。
以上就是关于Java调用DOS命令的基本知识,通过这些技术,开发者可以在Java程序中灵活地与操作系统交互,执行各种系统级任务。在实际应用中,可以根据具体需求选择Runtime或ProcessBuilder,并确保正确处理命令输出和...
通过这个类,我们可以启动、控制和管理应用程序,甚至可以执行DOS命令。以下将详细阐述如何利用`Process`类来调用外部程序并执行DOS命令。 1. **创建Process对象** 在C#代码中,首先需要实例化一个`Process`对象,...
DELPHI在Windows环境下执行DOS命令并获取返回结果是一个常见的需求,这通常涉及到系统交互和进程控制。在Delphi编程中,我们可以使用内置的`ShellExecute`函数或者通过创建进程对象来实现这一功能。本项目提供的代码...
总之,通过使用`System.Diagnostics.Process`类,我们可以方便地在C# WinForm应用中执行DOS命令,并通过设置`ProcessStartInfo`的属性来隐藏命令窗口,提供用户友好的体验。这个功能在很多自动化和脚本执行场景中...
在Windows操作系统中,DOS命令(也称为命令行接口或命令提示符命令)是一种与操作系统交互的方式,允许用户执行各种任务,如创建、删除文件,查看目录结构,以及运行可执行程序等。 描述"Labview通过调用Dos命令,...
了解如何获取DOS命令的返回结果对于进行自动化脚本编写、系统管理和故障排查至关重要。 标题"取DOS命令返回结果"指的是通过编程或脚本方式调用DOS命令,并获取该命令执行后的输出信息。在Windows系统中,这通常涉及...
在QT5中,我们可以通过QProcess类来调用外部的系统命令,比如DOS命令,实现与操作系统进行交互。这个小例子展示了如何在QT5环境中使用QProcess来执行像`ipconfig`和`ping`这样的命令,不仅限于Windows,也适用于...
例如,我们可以使用`Runtime.getRuntime().exec(command)`方法来执行DOS命令。这里的`command`字符串就是你要执行的DOS命令。这种方法简洁明了,适用于简单的命令执行,但它的缺点在于处理命令输出和错误流时不够...
其中,C#能够直接调用DOS命令(亦称CMD命令)进行系统级操作,这为开发者提供了一种高效、灵活的方式来执行特定任务,如文件管理、网络诊断、系统配置等。本文将深入探讨如何在C#程序中直接调用DOS命令,并通过示例...
本文将深入探讨如何使用Java执行DOS命令,并给出具体示例。 首先,`Runtime`类是每个Java应用程序都有的一个实例,它允许程序与正在执行它的环境进行交互。我们可以通过`Runtime.getRuntime().exec()`方法来执行DOS...
C#中调用DOS命令主要通过`System.Diagnostics.Process`类实现,该类提供了启动、控制和监视外部应用程序的功能。下面详细介绍几种常见方法: #### 方法一:使用`Process`类直接调用命令行程序 这是最直接的方法,...
在VC(Visual C++)环境下,我们经常需要与操作系统进行交互,执行一些系统级别的操作,例如运行DOS命令。这个“VC运行DOS命令源代码”示例就是为了解决这样的需求,它允许开发者在VC程序中调用并执行DOS命令。下面...