2014-01-08 84 views
0

以下是在Windows中獲取當前正在運行的進程列表的代碼。如何從Java獲取Windows進程描述?

import com.sun.jna.platform.win32.Kernel32; 
import com.sun.jna.platform.win32.Tlhelp32; 
import com.sun.jna.platform.win32.WinDef; 
import com.sun.jna.platform.win32.WinNT; 
import com.sun.jna.win32.W32APIOptions; 
import com.sun.jna.Native; 

public class ListProcesses { 
    public static void main(String[] args) { 
     Kernel32 kernel32 = (Kernel32) Native.loadLibrary(Kernel32.class, W32APIOptions.UNICODE_OPTIONS); 

     Tlhelp32.PROCESSENTRY32.ByReference processEntry = new Tlhelp32.PROCESSENTRY32.ByReference();   
     WinNT.HANDLE snapshot = kernel32.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPPROCESS, new WinDef.DWORD(0)); 
     try { 
      while (kernel32.Process32Next(snapshot, processEntry)) {    
       System.out.println(processEntry.th32ProcessID + "\t" + Native.toString(processEntry.szExeFile)+"\t"+processEntry.readField("")); 
      } 

     } 

     finally { 
      kernel32.CloseHandle(snapshot); 
     } 
    } 
} 

但我無法得到output.Kindly過程/服務的描述提供解決方案,使每個運行proceess的過程描述。提前致謝。

回答

2

而是加載並調用的Kernel32你可以簡單地使用下面的代碼片段在窗戶使用運行時執行本機進程:

public List<String> execCommand(String ... command) 
{ 
    try 
    { 
     // execute the desired command 
     Process proc = null; 
     if (command.length > 1) 
      proc = Runtime.getRuntime().exec(command); 
     else 
      proc = Runtime.getRuntime().exec(command[0]); 

     // process the response 
     String line = ""; 
     List<String> output = new ArrayList<>(); 
     try (BufferedReader input = new BufferedReader(new InputStreamReader(proc.getInputStream()))) 
     { 
      while ((line = input.readLine()) != null) 
      { 
       output.add(line); 
      } 
     } 
     return output; 
    } 
    catch (IOException e) 
    { 
     e.printStackTrace(); 
    } 
    return Collections.<String>emptyList(); 
} 

,然後執行命令,調用Windows Management Information Command-line

List<String> output = execCommand("wmic.exe PROCESS where name='"+processName+"'"); 

processName應該包含您嘗試從中獲取信息的正在運行的應用程序或exe的名稱。

返回的列表將包含正在運行的應用程序的狀態信息的行輸出。第一個條目將包含各個字段的標題信息,而以下條目將包含有關所有匹配過程名稱的信息。

上WMIC進一步的相關信息:

HTH

+0

謝謝它真的爲我工作。其實我要運行它作爲一個java web開始阻止一些在遠程操作系統上運行的下載服務。它適用於所有版本的Windows操作系統? –

+0

WMIC的最低要求是在客戶端Windows XP和服務器端Windows Server 2003([Source](http://msdn.microsoft.com/en-us/library/aa394531%28v=vs.85%29)。 aspx)) - 所以如果你需要支持Windows 3.1,95,ME或NT(儘管我懷疑它是今天常用的),你將需要其他解決方案。 –

+0

謝謝。我正在嘗試wmic.exe PROCESS WHERE(name =「dap.exe」)獲取Processid,Caption,Command line,Description給出的說明與說明相同,即DAP.exe它的作用,t給出process/exe的實際描述。下載加速器Plus(DAP)的實際描述在哪裏。 –

1

正如我今天偶然發現this post here,展示瞭如何提取版本信息一個可執行文件,你的後回到我的腦海,所以我開始了一些調查。

This further post指出只能從可執行文件本身提取進程描述,因此我們需要將手放在JNA上,而不是解析WMICTASKLIST的某些輸出。這篇文章進一步鏈接了提供C方法提取流程描述的MSDN page for VerQueryValue函數。這裏尤其是第二個參數應該是有趣的,因爲它定義了要返回的內容。

使用第一篇文章中提到的代碼,它現在將C struct typedefs轉換爲Java等價物。我將張貼在這裏的完整代碼,至少對我的作品上Windows 7 64bit

的Maven的pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>at.rovo.test</groupId> 
    <artifactId>JNI_Test</artifactId> 
    <version>1.0-SNAPSHOT</version> 
    <packaging>jar</packaging> 

    <name>JNI_Test</name> 
    <url>http://maven.apache.org</url> 
    <build> 
     <plugins> 
      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-compiler-plugin</artifactId> 
       <version>2.3.2</version> 
       <configuration> 
        <source>1.7</source> 
        <target>1.7</target> 
       </configuration> 
      </plugin> 
     </plugins> 
    </build> 
    <properties> 
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
    </properties> 

    <dependencies> 
    <dependency> 
     <groupId>junit</groupId> 
     <artifactId>junit</artifactId> 
     <version>3.8.1</version> 
     <scope>test</scope> 
    </dependency>  
    <!-- JNA 3.4 
    <dependency> 
     <groupId>net.java.dev.jna</groupId> 
     <artifactId>jna</artifactId> 
     <version>3.4.0</version> 
    </dependency> 
    <dependency> 
    <groupId>net.java.dev.jna</groupId> 
    <artifactId>platform</artifactId> 
    <version>3.4.0</version> 
    </dependency> 
    --> 
    <!-- JNA 4.0.0 --> 
    <dependency> 
     <groupId>net.java.dev.jna</groupId> 
     <artifactId>jna</artifactId> 
     <version>4.0.0</version> 
    </dependency> 
    <dependency> 
     <groupId>net.java.dev.jna</groupId> 
     <artifactId>jna-platform</artifactId> 
     <version>4.0.0</version> 
    </dependency> 
    <!-- --> 
    </dependencies> 
</project> 

LangAndCodePage.java - 一個輔助類,其中提取的十六進制值映射到人類可讀的輸出包含在翻譯表中的語言和代碼頁信息。值因此從this page here採取:

package at.rovo.test.jni_test; 

import java.util.HashMap; 
import java.util.Map; 

public final class LangAndCodePage 
{ 
    private final static Map<String, String> languages = new HashMap<>(); 
    private final static Map<String, String> codePage = new HashMap<>(); 

    static 
    { 
     languages.put("0000", "Language Neutral"); 
     languages.put("0401", "Arabic"); 
     languages.put("0402", "Bulgarian"); 
     languages.put("0403", "Catalan"); 
     languages.put("0404", "Traditional Chinese"); 
     languages.put("0405", "Czech"); 
     languages.put("0406", "Danish"); 
     languages.put("0407", "German"); 
     languages.put("0408", "Greek"); 
     languages.put("0409", "U.S. English"); 
     languages.put("040A", "Castilian Spanish"); 
     languages.put("040B", "Finnish"); 
     languages.put("040C", "French"); 
     languages.put("040D", "Hebrew"); 
     languages.put("040E", "Hungarian"); 
     languages.put("040F", "Icelandic"); 
     languages.put("0410", "Italian"); 
     languages.put("0411", "Japanese"); 
     languages.put("0412", "Korean"); 
     languages.put("0413", "Dutch");  
     languages.put("0414", "Norwegian ? Bokmal");  
     languages.put("0810", "Swiss Italian");  
     languages.put("0813", "Belgian Dutch");  
     languages.put("0814", "Norwegian ? Nynorsk"); 
     languages.put("0415", "Polish"); 
     languages.put("0416", "Portuguese (Brazil)"); 
     languages.put("0417", "Rhaeto-Romanic"); 
     languages.put("0418", "Romanian"); 
     languages.put("0419", "Russian"); 
     languages.put("041A", "Croato-Serbian (Latin)"); 
     languages.put("041B", "Slovak"); 
     languages.put("041C", "Albanian"); 
     languages.put("041D", "Swedish"); 
     languages.put("041E", "Thai"); 
     languages.put("041F", "Turkish"); 
     languages.put("0420", "Urdu"); 
     languages.put("0421", "Bahasa"); 
     languages.put("0804", "Simplified Chinese"); 
     languages.put("0807", "Swiss German"); 
     languages.put("0809", "U.K. English"); 
     languages.put("080A", "Spanish (Mexico)"); 
     languages.put("080C", "Belgian French"); 
     languages.put("0C0C", "Canadian French"); 
     languages.put("100C", "Swiss French"); 
     languages.put("0816", "Portuguese (Portugal)"); 
     languages.put("081A", "Serbo-Croatian (Cyrillic)"); 

     codePage.put("0000", "7-bit ASCII"); 
     codePage.put("03A4", "Japan (Shift ? JIS X-0208)"); 
     codePage.put("03B5", "Korea (Shift ? KSC 5601)"); 
     codePage.put("03B6", "Taiwan (Big5)"); 
     codePage.put("04B0", "Unicode"); 
     codePage.put("04E2", "Latin-2 (Eastern European)"); 
     codePage.put("04E3", "Cyrillic"); 
     codePage.put("04E4", "Multilingual"); 
     codePage.put("04E5", "Greek"); 
     codePage.put("04E6", "Turkish"); 
     codePage.put("04E7", "Hebrew"); 
     codePage.put("04E8", "Arabic"); 
    } 

    // prohibit instantiation 
    private LangAndCodePage() 
    { 

    } 

    public static void printTranslationInfo(String lang, String cp) 
    { 
     StringBuilder builder = new StringBuilder(); 
     builder.append("Language: "); 
     builder.append(languages.get(lang)); 
     builder.append(" ("); 
     builder.append(lang); 
     builder.append("); "); 

     builder.append("CodePage: "); 
     builder.append(codePage.get(cp)); 
     builder.append(" ("); 
     builder.append(cp); 
     builder.append(");"); 

     System.out.println(builder.toString()); 
    } 
} 

最後但並非最不重要,提取文件的版本和Windows資源管理器的文件描述的代碼。該代碼包含大量的文檔,我用它來學習的東西,我自己;)

package at.rovo.test.jni_test; 

import java.io.IOException; 

import com.sun.jna.Memory; 
import com.sun.jna.Pointer; 
import com.sun.jna.platform.win32.VerRsrc.VS_FIXEDFILEINFO; 
import com.sun.jna.platform.win32.Version; 
import com.sun.jna.ptr.IntByReference; 
import com.sun.jna.ptr.PointerByReference; 
import java.math.BigInteger; 
import java.nio.charset.StandardCharsets; 
import java.util.ArrayList; 
import java.util.List; 

public class FileVersion 
{ 
    // The structure as implemented by the MSDN article 
    public static class LANGANDCODEPAGE extends Structure 
    { 
     /** The language contained in the translation table **/ 
     public short wLanguage; 
     /** The code page contained in the translation table **/ 
     public short wCodePage; 

     public LANGANDCODEPAGE(Pointer p) 
     { 
      useMemory(p); 
     } 

     public LANGANDCODEPAGE(Pointer p, int offset) 
     { 
      useMemory(p, offset); 
     } 

     public static int sizeOf() 
     { 
      return 4; 
     } 

     // newer versions of JNA require a field order to be set 
     @Override 
     protected List getFieldOrder() 
     { 
      List fieldOrder = new ArrayList(); 
      fieldOrder.add("wLanguage"); 
      fieldOrder.add("wCodePage"); 
      return fieldOrder; 
     } 
    } 

    public static void main(String[] args) throws IOException 
    { 
     // http://msdn.microsoft.com/en-us/library/ms647464%28v=vs.85%29.aspx 
     // 
     // VerQueryValue will take two input and two output parameters 
     // 1. parameter: is a pointer to the version-information returned 
     //    by GetFileVersionInfo 
     // 2. parameter: will take a string and return an output depending on 
     //    the string: 
     //  "\\" 
     //   Is the root block and retrieves a VS_FIXEDFILEINFO struct 
     //  "\\VarFileInfo\Translation" 
     //   will return an array of Var variable information structure 
     //   holding the language and code page identifier 
     //  "\\StringFileInfo\\{lang-codepage}\\string-name" 
     //   will return a string value of the language and code page 
     //   requested. {lang-codepage} is a concatenation of a language 
     //   and the codepage identifier pair found within the translation 
     //   array in a hexadecimal string! string-name must be one of the 
     //   following values: 
     //    Comments, InternalName, ProductName, CompanyName, 
     //    LegalCopyright, ProductVersion, FileDescription, 
     //    LegalTrademarks, PrivateBuild, FileVersion, 
     //    OriginalFilename, SpecialBuild 
     // 3. parameter: contains the address of a pointer to the requested 
     //    version information in the buffer of the 1st parameter. 
     // 4. parameter: contains a pointer to the size of the requested data 
     //    pointed to by the 3rd parameter. The length depends on 
     //    the input of the 2nd parameter: 
     //    *) For root block, the size in bytes of the structure 
     //    *) For translation array values, the size in bytes of 
     //     the array stored at lplpBuffer; 
     //    *) For version information values, the length in 
     //     character of the string stored at lplpBuffer; 

     String filePath = "C:\\Windows\\explorer.exe"; 

     IntByReference dwDummy = new IntByReference(); 
     dwDummy.setValue(0); 

     int versionlength = 
       Version.INSTANCE.GetFileVersionInfoSize(filePath, dwDummy); 

     if (versionlength > 0) 
     { 
      // will hold the bytes of the FileVersionInfo struct 
      byte[] bufferarray = new byte[versionlength]; 
      // allocates space on the heap (== malloc in C/C++) 
      Pointer lpData = new Memory(bufferarray.length); 
      // will contain the address of a pointer to the requested version 
      // information 
      PointerByReference lplpBuffer = new PointerByReference(); 
      // will contain a pointer to the size of the requested data pointed 
      // to by lplpBuffer. 
      IntByReference puLen = new IntByReference(); 

      // reads versionLength bytes from the executable file into the FileVersionInfo struct buffer 
      boolean fileInfoResult = 
        Version.INSTANCE.GetFileVersionInfo(
          filePath, 0, versionlength, lpData); 

      // retrieve file description for language and code page "i" 
      boolean verQueryVal = 
        Version.INSTANCE.VerQueryValue(
          lpData, "\\", lplpBuffer, puLen); 

      // contains version information for a file. This information is 
      // language and code page independent 
      VS_FIXEDFILEINFO lplpBufStructure = 
       new VS_FIXEDFILEINFO(lplpBuffer.getValue()); 
      lplpBufStructure.read(); 

      int v1 = (lplpBufStructure.dwFileVersionMS).intValue() >> 16; 
      int v2 = (lplpBufStructure.dwFileVersionMS).intValue() & 0xffff; 
      int v3 = (lplpBufStructure.dwFileVersionLS).intValue() >> 16; 
      int v4 = (lplpBufStructure.dwFileVersionLS).intValue() & 0xffff; 

      System.out.println(
        String.valueOf(v1) + "." + 
          String.valueOf(v2) + "." + 
          String.valueOf(v3) + "." + 
          String.valueOf(v4)); 

      // creates a (reference) pointer 
      PointerByReference lpTranslate = new PointerByReference(); 
      IntByReference cbTranslate = new IntByReference(); 
      // Read the list of languages and code pages 
      verQueryVal = Version.INSTANCE.VerQueryValue(
         lpData, "\\VarFileInfo\\Translation", lpTranslate, cbTranslate); 

      if (cbTranslate.getValue() > 0) 
      { 
       System.out.println("Found "+(cbTranslate.getValue()/4) 
        + " translation(s) (length of cbTranslate: " 
        + cbTranslate.getValue()+" bytes)"); 
      } 
      else 
      { 
       System.err.println("No translation found!"); 
       return; 
      } 

      // Read the file description 
      // msdn has this example here: 
      // for(i=0; i < (cbTranslate/sizeof(struct LANGANDCODEPAGE)); i++) 
      // where LANGANDCODEPAGE is a struct holding two WORDS. A word is 
      // 16 bits (2x 8 bit = 2 bytes) long and as the struct contains two 
      // words the length of the struct should be 4 bytes long 
      for (int i=0; i < (cbTranslate.getValue()/LANGANDCODEPAGE.sizeOf()); i++)) 
      { 
       // writes formatted data to the specified string 
       // out: pszDest - destination buffer which receives the formatted, null-terminated string created from pszFormat 
       // in: ccDest - the size of the destination buffer, in characters. This value must be sufficiently large to accomodate the final formatted string plus 1 to account for the terminating null character. 
       // in: pszFormat - the format string. This string must be null-terminated 
       // in: ... The arguments to be inserted into the pszFormat string 
       // hr = StringCchPrintf(SubBlock, 50, 
       //      TEXT("\\StringFileInfo\\%04x%04x\\FileDescription"), 
       //      lpTranslate[i].wLanguage, 
       //      lpTranslate[i].wCodePage); 

       // fill the structure with the appropriate values 
       LANGANDCODEPAGE langCodePage = 
        new LANGANDCODEPAGE(lpTranslate.getValue(), i*LANGANDCODEPAGE.sizeOf()); 
       langCodePage.read(); 

       // convert short values to hex-string: 
       // https://stackoverflow.com/questions/923863/converting-a-string-to-hexadecimal-in-java 
       String lang = String.format("%04x", langCodePage.wLanguage); 
       String codePage = String.format("%04x",langCodePage.wCodePage); 

       // see http://msdn.microsoft.com/en-us/library/windows/desktop/aa381058.aspx 
       // for proper values for lang and codePage 

       LangAndCodePage.printTranslationInfo(lang.toUpperCase(), codePage.toUpperCase()); 

       // build the string for querying the file description stored in 
       // the executable file 
       StringBuilder subBlock = new StringBuilder(); 
       subBlock.append("\\StringFileInfo\\"); 
       subBlock.append(lang); 
       subBlock.append(codePage); 
       subBlock.append("\\FileDescription"); 

       printDescription(lpData, subBlock.toString()); 
      } 
     } 
     else 
      System.out.println("No version info available"); 
    } 

    private static void printDescription(Pointer lpData, String subBlock) 
    { 
     PointerByReference lpBuffer = new PointerByReference(); 
     IntByReference dwBytes = new IntByReference(); 

     // Retrieve file description for language and code page "i" 
     boolean verQueryVal = Version.INSTANCE.VerQueryValue(
      lpData, subBlock, lpBuffer, dwBytes); 

     // a single character is represented by 2 bytes! 
     // the last character is the terminating "\n" 
     byte[] description = 
      lpBuffer.getValue().getByteArray(0, (dwBytes.getValue()-1)*2); 
     System.out.println("File-Description: \"" 
      + new String(description, StandardCharsets.UTF_16LE)+"\""); 
    } 
} 

最後,我收到我的德國的Windows 7 64位輸出:

[exec:exec] 
Version: 6.1.7601.17567 
Found 1 translation(s) (length of cbTranslate: 4 bytes) 
Language: German (0407); CodePage: Unicode (04B0); 
File-Description: "Windows-Explorer" 

HTH


@編輯:更新代碼以使用結構的類表示來簡化值的提取(處理字節確實需要它們交換接收到的字節的順序 - big和littl e endian issue)

在一些嘗試使用多種語言和代碼頁的應用程序之後發現它們的文件,我可以測試多個翻譯的輸出。


@ Edit2:重構代碼並將其放在github上。正如在評論中提到,從github上回購了羅技僚機事件監視器運行代碼的輸出返回多個語言和代碼頁段:

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 
XXX Information contained in: C:\Program Files\Logitech\Gaming Software\LWEMon.exe 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 
File: C:\Program Files\Logitech\Gaming Software\LWEMon.exe 
Version: 5.10.127.0 
Language: U.S. English 
CodePage: Multilingual 
Original-Filename: LWEMon.exe 
Company-Name: Logitech Inc. 
File-Description: Logitech WingMan Event Monitor 
File-Version: 5.10.127 
Product-Version: 5.10.127 
Product-Name: Logitech Gaming Software 
Internal-Name: LWEMon 
Private-Build: 
Special-Build: 
Legal-Copyright: © 1999-2010 Logitech. All rights reserved. 
Legal-Trademark: Logitech, the Logitech logo, and other Logitech marks are owned by Logitech and may be registered. All other trademarks are the property of their respective owners. 
Comment: Created by the WingMan Team. 

File: C:\Program Files\Logitech\Gaming Software\LWEMon.exe 
Version: 5.10.127.0 
Language: Japanese 
CodePage: Multilingual 
Original-Filename: LWEMon.exe 
Company-Name: Logicool Co. Ltd. 
File-Description: Logicool WingMan Event Monitor 
File-Version: 5.10.127 
Product-Version: 5.10.127 
Product-Name: Logicool Gaming Software 
Internal-Name: LWEMon 
Private-Build: 
Special-Build: 
Legal-Copyright: © 1999-2010 Logicool Co. Ltd. All rights reserved. 
Legal-Trademark: Logicool, the Logicool logo, and other Logicool marks are owned by Logicool and may be registered. All other trademarks are the property of their respective owners. 
Comment: Created by the WingMan Team. 
+0

謝謝先生。其實我找到另一種方式,即。 Windows PowerShell命令** get-process notepad |選擇對象描述**。因此,我使用命令行來獲取當前正在運行的進程的描述。類似於服務** get-service |其中{$ _。status -eq'running'} **。請提供您的建議。 –

+0

你是否真的需要爲(int i = 0; i <(cbTranslate.getValue()/ LANGANDCODEPAGE.sizeOf()); i ++))使用循環來提取文件描述? – ANTARA

+1

如果您只有一個具有單一語言和代碼頁條目的.exe文件,則不需要循環。如果你有一個包含多種語言和codePages的可執行文件,並且你想列出它們,你最好使用循環。即使您只有一種語言和代碼頁段,循環本身也不會受到影響 –

0

(在回答響應的OP回答轉換爲一個社區。維基答案見Question with no answers, but issue solved in the comments (or extended in chat)

其實我找到另一種方式,即。 Windows PowerShell命令:
get-process notepad | select-object description

因此,我使用命令行來獲取當前正在運行的進程的描述。對於服務類似:
get-service | where {$_.status -eq 'running'}