Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get list of processes on Windows in a charset-safe way

This post gives a solution to retrieve the list of running processes under Windows. In essence it does:

String cmd = System.getenv("windir") + "\\system32\\" + "tasklist.exe";
Process p = Runtime.getRuntime().exec(cmd);
InputStreamReader isr = new InputStreamReader(p.getInputStream());
BufferedReader input = new BufferedReader(isr);

then reads the input.

It looks and works great but I was wondering if there is a possibility that the charset used by tasklist might not be the default charset and that this call could fail?

For example this other question about a different executable shows that it could cause some issues.

If that is the case, is there a way to determine what the appropriate charset would be?

like image 561
assylias Avatar asked Nov 12 '12 17:11

assylias


People also ask

How to see all running processes in Windows?

Task Manager can be opened in a number of ways, but the simplest is to select Ctrl+Alt+Delete, and then select Task Manager. In Windows, first click More details to expand the information displayed. From the Processes tab, select Details to see the process ID listed in the PID column. Click on any column name to sort.

How do I find out what processes are running Windows from command line?

First of all open the Start Screen and type Cmd utility in search box then click on the search button. Click on the cmd utility icon; it opens a command-line window. Type Tasklist in it and press the enter key. This command shows all the running processes in your system.


1 Answers

Can break this into 2 parts:

  1. The windows part
    From java you're executing a Windows command - externally to the jvm in "Windows land". When java Runtime class executes a windows command, it uses the DLL for consoles & so appears to windows as if the command is running in a console
    Q: When I run C:\windows\system32\tasklist.exe in a console, what is the character encoding ("code page" in windows terminology) of the result?

    • windows "chcp" command with no argument gives the active code page number for the console (e.g. 850 for Multilingual-Latin-1, 1252 for Latin-1). See Windows Microsoft Code Pages, Windows OEM Code Pages, Windows ISO Code Pages
      The default system code page is originally setup according to your system locale (type systeminfo to see this or Control Panel-> Region and Language).
    • the windows OS/.NET function getACP() also gives this info

  2. The java part:
    How do I decode a java byte stream from the windows code page of "x" (e.g. 850 or 1252)?

    • the full mapping between windows code page numbers and equivalent java charset names can be derived from here - Code Page Identifiers (Windows)
    • However, in practice one of the following prefixes can be added to achieve the mapping:
      "" (none) for ISO, "IBM" or "x-IBM" for OEM, "windows-" OR "x-windows-" for Microsoft/Windows.
      E.g. ISO-8859-1 or IBM850 or windows-1252

Full Solution:

    String cmd = System.getenv("windir") + "\\system32\\" + "chcp.com";
    Process p = Runtime.getRuntime().exec(cmd);
    // Use default charset here - only want digits which are "core UTF8/UTF16"; 
    // ignore text preceding ":"
    String windowsCodePage = new Scanner(
        new InputStreamReader(p.getInputStream())).skip(".*:").next();

    Charset charset = null;
    String[] charsetPrefixes = 
        new String[] {"","windows-","x-windows-","IBM","x-IBM"};
    for (String charsetPrefix : charsetPrefixes) {
        try {
            charset = Charset.forName(charsetPrefix+windowsCodePage);
            break;
        } catch (Throwable t) {
        }
    }
    // If no match found, use default charset
    if (charset == null) charset = Charset.defaultCharset();

    cmd = System.getenv("windir") + "\\system32\\" + "tasklist.exe";
    p = Runtime.getRuntime().exec(cmd);
    InputStreamReader isr = new InputStreamReader(p.getInputStream(), charset);
    BufferedReader input = new BufferedReader(isr);

    // Debugging output
    System.out.println("matched codepage "+windowsCodePage+" to charset name:"+
            charset.name()+" displayName:"+charset.displayName());
    String line;
    while ((line = input.readLine()) != null) {
           System.out.println(line);
    }

Thanks for the Q! - was fun.

like image 181
Glen Best Avatar answered Oct 11 '22 21:10

Glen Best