2014-01-08 29 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'}