有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

jna如何从Java获取Windows进程描述?

下面是获取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);
        }
    } 
}

但我无法在输出中获得流程/服务的描述。请提供解决方案,以获取每个运行过程的过程描述。提前谢谢


共 (3) 个答案

  1. # 1 楼答案

    (由OP在回复中回复。转换为社区wiki回复。请参见Question with no answers, but issue solved in the comments (or extended in chat)

    Actually I find out another way ie. Windows PowerShell commands:
    get-process notepad | select-object description.

    Therefore, I am using command line to get descriptions of currently running process. Similarly for Services:
    get-service | where {$_.status -eq 'running'}.

  2. # 2 楼答案

    不必加载和调用内核32,只需在windows中使用以下代码段,即可使用运行时执行本机进程:

    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的更多信息:

  3. # 3 楼答案

    当我今天偶然发现this post here展示了如何从可执行文件中提取版本信息时,我想起了你的帖子,于是我开始了一些调查

    This further post声明流程描述只能从可执行文件本身提取,因此我们需要着手JNA,而不是解析来自WMICTASKLIST的一些输出。这篇文章进一步链接了MSDN page for VerQueryValue函数,它提供了一种提取流程描述的C方式。在这里,第二个参数尤其值得关注,因为它定义了要返回的内容

    在第一篇文章中提到的代码中,现在需要将C struct typedef转换为Java等价物。我将在这里发布完整的代码,至少在^{上对我有效:

    马文·波姆。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"
    


    @Edit:更新了代码,使用结构的类表示来简化值的提取(处理字节确实需要它们按照接收到的字节的顺序进行转换——大端和小端问题)

    在一些人尝试使用一个应用程序后发现,该应用程序在其文件中使用多种语言和代码页,我可以在其中测试多个翻译的输出


    @Edit2:重构代码并将其放到github。如评论中所述,运行Logitech WingMan事件监视器github repo代码的输出返回多个语言和代码页段:

    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.