溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java中怎么調(diào)用WMIC命令

發(fā)布時間:2021-06-24 16:57:11 來源:億速云 閱讀:376 作者:Leah 欄目:編程語言

本篇文章為大家展示了Java中怎么調(diào)用WMIC命令,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

今天要寫個遠(yuǎn)程重啟服務(wù)的功能,為了開發(fā)速度,暫時定為Java代碼+WMIC命令的方法,簡單的說,就是利用Java調(diào)用本機(jī)應(yīng)用程序的方法。涉及到的Java類有java.lang包里面的Runtime、Process、ProcessBuilder三個類,以及wmic中重啟服務(wù)的命令。因為之前也寫過這方面的東西,所以很習(xí)慣性的寫出了代碼:

Process p = Runtime.getRuntime().exec("wmic ...");  BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));  String tmp = null;   while ((tmp = br.readline()) != null) {      System.out.println(tmp);  }  int exitValue = p.waitfor();

運行,結(jié)果發(fā)現(xiàn)程序不能退出,Debug發(fā)現(xiàn)程序阻塞在br.readline()中了,強(qiáng)制結(jié)束程序,發(fā)現(xiàn)重啟服務(wù)的命令正常下下去了,去掉程序中獲得標(biāo)準(zhǔn)輸出的地方和獲得返回結(jié)果的地方,命令也能正常下去,而且正常退出。

為什么程序會阻塞呢?Google了一下,發(fā)現(xiàn)了大家的解釋,應(yīng)該也是比較權(quán)威的解釋吧:每個進(jìn)程都有自己的標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)錯誤輸出,對于某些依賴于OS的進(jìn)程,可能其輸出緩沖區(qū)很小,如果不能及時的讀出(標(biāo)準(zhǔn)輸出、標(biāo)注錯誤輸出),將導(dǎo)致進(jìn)程不能正常退出。我的程序中標(biāo)準(zhǔn)輸出已經(jīng)讀了,顯然原因不是這個,難道是錯誤輸出緩沖區(qū)中的數(shù)據(jù)沒有讀出導(dǎo)致的?帶著這個疑問,對程序作了一些更改:

ProcessBuilder pb = new ProcessBuilder("wmic",...);  pb.redirectErrorStream(true);  Process p = pb.start();  BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));  String tmp = null;   while ((tmp = br.readline()) != null) {      System.out.println(tmp);  }  int exitValue = p.waitfor();

編譯運行,發(fā)現(xiàn)還是有問題,依然還是阻塞。又google了一下,大家的評論大多還是關(guān)于標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤輸出,那這程序應(yīng)該是沒有問題了。后來在cmd中敲入wmic的命令,發(fā)現(xiàn)wmic命令敲入以后會進(jìn)入一個自有的提示符中,難道是因為標(biāo)準(zhǔn)輸入的問題。后來又google了一下,驗證了我的猜想,果然是因為wmic進(jìn)程會等待標(biāo)準(zhǔn)輸入,而程序中沒有處理標(biāo)準(zhǔn)輸入的地方,是標(biāo)準(zhǔn)輸入阻塞了進(jìn)程的退出,修改代碼:

ProcessBuilder pb = new ProcessBuilder("wmic",...);  pb.redirectErrorStream(true);  Process p = pb.start();  p.getOutputStream().close();  BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));  String tmp = null;   while ((tmp = br.readline()) != null) {      System.out.println(tmp);  }  int exitValue = p.waitfor();

編譯運行,程序成功執(zhí)行。果然是標(biāo)準(zhǔn)輸入的原因。

后來執(zhí)行的過程中換了一個服務(wù)的名稱,發(fā)現(xiàn)執(zhí)行失?。軌蛘M顺?,但是返回的結(jié)果是“無效動作”),但是同樣的命令,在命令行中執(zhí)行成功,而且直接適用Runtime.exec()方法中寫入整個命令也能夠執(zhí)行成功,難道是ProcessBuilder的錯誤,ProcessBuilder構(gòu)造函數(shù)有兩個:

ProcessBuilder(List<String> command)

利用指定的操作系統(tǒng)程序和參數(shù)構(gòu)造一個進(jìn)程生成器。

ProcessBuilder(String... command)

利用指定的操作系統(tǒng)程序和參數(shù)構(gòu)造一個進(jìn)程生成器。

找到ProcessBuilder的源代碼,發(fā)現(xiàn)了對List<String>的解析方法:JDK將List中的所有字符串用空格連接,對list中的每個字符串JDK先判斷串中是否包含空格,如果包含空格,用雙引號將該字符串引起來,再拼到前面字符串的后面(應(yīng)該是為了解決路徑中包含空格的問題),可恰好Wmic命令的參數(shù)中有一段是name="ServiceName",如果ServiceName中包換空格,JDK就會把name="service name"的外層加一個雙引號,導(dǎo)致wmic不能解析該命令了。

問題終于全都解決了,耗費了多半天的時間,不過收獲總是有的,這里總結(jié)一下,在使用Java調(diào)用外部命令的時候,一定要注意對標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)輸入和錯誤輸出的處理。對于一般的命令,只需要將標(biāo)準(zhǔn)輸出和錯誤輸出合并,一起讀出來或者在另外的線程中讀出來,而對于一些特殊的命令,還有處理標(biāo)準(zhǔn)輸入。建議即使不使用標(biāo)準(zhǔn)輸入,先close了,總是不會出錯了。另外,使用ProcessBuilder時要注意它的空格處理方式是否是你想要的,如果不是,就不能用ProcessBuilder了,直接使用Runtime.exec()就好了。

上述內(nèi)容就是Java中怎么調(diào)用WMIC命令,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI