java Process在windows的使用匯總(轉)


最常用的是ant(java工程中流行),maven,及通用的exec(只要有shell腳本如.sh,.bat,.exe,.cmd等).而其實前兩者不容易出錯,后者卻遇到了以下問題:
Caused by: java.io.IOException: Cannot run program "DailyBuild.bat"...java.io.IOException: CreateProcess error=2

而現在的問題是覺得<exec>節點的workingdir屬性設置正確,而command 屬性也是指向了要執行的批處理文件"DailyBuild.bat",為什么還要報錯呢?於是先把相對路徑全改成了絕對,發現不行;又試了把workingdir屬性去掉,把command屬性寫全路徑(因為工作目錄去掉了,所以一定得寫全),發現能運行了,只是報錯,因為引用不對了. 這樣一來,問題明了了,補回workingdir屬性,運行成功! 
得出這樣的結論,workingdir屬性會讓人產生錯覺使你在command屬性中不再寫這個所謂重復的工作目錄部分了,而實際上恰恰要寫全路徑.效果可能類似這樣的:)
<exec
             workingdir="projects/${project.name}/deploy/build/"
            command="projects/${project.name}/deploy/build/DailyBuild.bat"
            errorstr="build failed"/> 

http://www.verydemo.com/demo_c128_i15102.html

在執行bat時如果將commnd 改為 cmd /c DailyBuild.bat也可以。

 

Runtime.getRuntime().exec()方法執行bat時,如果bat沒有按預期執行,可以使用如下形式:

Process p = Runtime.getRuntime().exec("cmd /c start D:\\catalina.bat start", null, new File("D:\\apache-tomcat-6.0.35"));
http://www.oschina.net/question/927474_84637


java中用Runtime.getRuntime().exec() 調用外部程序, 獲取"標准輸出流", 老是阻塞.
在網上找了找, 覺得應該是"錯誤輸出流"的問題. 果然, 為"錯誤輸出流"單開一個線程讀取之, "標准輸出流"就不再阻塞了.
源碼如下:

/**執行外部程序,並獲取標准輸出*/
public static String excuteCmd_multiThread(String[] cmd,String encoding)
{
BufferedReader bReader=null;
InputStreamReader sReader=null;
try
{
Process p = Runtime.getRuntime().exec(cmd);
/*為"錯誤輸出流"單獨開一個線程讀取之,否則會造成標准輸出流的阻塞*/
Thread t=new Thread(new InputStreamRunnable(p.getErrorStream(),"ErrorStream"));
t.start();

/*"標准輸出流"就在當前方法中讀取*/
BufferedInputStream bis = new BufferedInputStream(p.getInputStream());

if(encoding!=null && encoding.length()!=0)
{
sReader = new InputStreamReader(bis,encoding);//設置編碼方式
}
else
{
sReader = new InputStreamReader(bis,"GBK");
}
bReader=new BufferedReader(sReader);

StringBuilder sb=new StringBuilder();
String line;

while((line=bReader.readLine())!=null)
{
sb.append(line);
sb.append("/n");
}

bReader.close();
p.destroy();
return sb.toString();
}
catch(Exception e)
{
e.printStackTrace();
return ErrorString;
}
finally
{
}
}

/**讀取InputStream的線程*/
class InputStreamRunnable implements Runnable
{
BufferedReader bReader=null;
String type=null;
public InputStreamRunnable(InputStream is, String _type)
{
try
{
bReader=new BufferedReader(new InputStreamReader(new BufferedInputStream(is),"UTF-8"));
type=_type;
}
catch(Exception ex)
{
}
}
public void run()
{
String line;
int lineNum=0;

try
{
while((line=bReader.readLine())!=null)
{
lineNum++;
//Thread.sleep(200);
}
bReader.close();
}
catch(Exception ex)
{
}
}
}

另外, Runtime.getRuntime().exec() 還有一些局限性, 就是無法像cmd那樣執行較為復雜的命令. 比如, 輸出流的重定向, 如:
他會立即返回, 不會去執行. 但是我們可以這樣做, 能夠完成於cmd中一樣的工作:
其中 /c 就是"執行后面字符串的命令". 這樣就OK了,但同時還是要注意"錯誤輸出流"的問題,依然要單開一個線程讀取.否則一樣會阻塞的.

http://www.xuebuyuan.com/695058.html

3、Runtime.getRuntime().exec() 路基中含有空格,如下: 

Runtime.getRuntime().exec("cmd.exe /c D:\\Program  Files\\tece2.1\\tececode\\updateprogram\\updateProgram.exe");

這樣講無法執行,需要在空格的前后加上雙引號,而不是在整個路徑的前后加雙引號,如下: 

Runtime.getRuntime().exec("cmd.exe /c D:\\Program\" \"Files\\tece2.1\\tececode\\updateprogram\\updateProgram.exe");

或者使用替換方式:

String  commandStr="cmd.exe /c"+" " +realPath.realTomcatPath.replace(" ", "\" \"");  
Runtime.getRuntime().exec(commandStr);

http://flyeagle.iteye.com/blog/406487


cmd /c start dir 會打開一個新窗口后執行dir指令,原窗口會關閉.hi://apps;c dir 是執行完dir命令后關閉命令窗口,原窗口不會關閉;k start dir 會打開一個新窗口后執行dir指令://apps:

還可以設置工作目錄,對執行與工作目錄相關的批處理文件是有用的。
File dir = new File("E:\\Product");
Process process = Runtime.getRuntime().exec("E:\\Product\\copy.bat",null,dir);
http://blog.sina.com.cn/s/blog_3d731e9001000ajm.html

 

 

 

今天使用nio編寫一個類似ssh的網絡客戶端,在執行process的時候,出現了一個讓人很頭疼的bug,廢話不說,上代碼:

public static void main(String[] args)throws Exception {
        Process process=Runtime.getRuntime().exec("cmd /c tree");
        int status=process.exitValue();
        System.out.println(status);
        BufferedReader reader=new BufferedReader(new   InputStreamReader(process.getInputStream()));
        String line=null;
        while((line=reader.readLine())!=null) {
            System.out.println(line);
        }
        
        BufferedReader error=new BufferedReader(new InputStreamReader(process.getErrorStream()));
        while((line=error.readLine())!=null) {
            System.out.println(line);
        }
    }

在process后面立即調用后

 int status=process.exitValue();

出現了
java.lang.IllegalThreadStateException: process has not exited
at java.lang.Win32Process.exitValue(Native Method)

異常,后來一百度發現,jdk實現process時,調用外部命令不是同步的調用,而是異步執行。所以tree命令還沒有執行成功就返回,jdk拋出異常

后來想了一招,就是不管執行如何,先去讀取process的InputStream和ErrorInputStream,也就是說

不管外部命令執行的正確與否,都先去執行一次。

//讀取正確執行的返回流 
BufferedReader info=new BufferedReader(new InputStreamReader(executor.getInputStream()));
 while((line=info.readLine())!=null) {
            infoMsg.append(line).append("\n");
      }

//讀取錯誤執行的返回流
 BufferedReader error=new BufferedReader(new InputStreamReader(executor.getErrorStream()));
 while((line=error.readLine())!=null) {
            errorMsg.append(line).append("\n");
    }

//調用exitValue返回值
 responseCode=executor.exitValue();

這個時候,再調用exitValue()方法就不會出錯了

  這是一個具體的實例

        int responseCode=0;
        StringBuilder infoMsg=new StringBuilder();
        StringBuilder errorMsg=new StringBuilder();
        String line=null;
        
        String cmd=Util.isWindows()?("cmd /c "+command):(command);
        System.err.println("command is "+cmd);
        Process executor=Runtime.getRuntime().exec(cmd);
        
        BufferedReader info=new BufferedReader(new InputStreamReader(executor.getInputStream()));
        BufferedReader error=new BufferedReader(new InputStreamReader(executor.getErrorStream()));
        while((line=info.readLine())!=null) {
            infoMsg.append(line).append("\n");
        }
        
        while((line=error.readLine())!=null) {
            errorMsg.append(line).append("\n");
        }
        responseCode=executor.exitValue();

http://kingj.iteye.com/blog/1420586

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM