Getting process information on Windows

Last edited on

Overview

This example Squish test script demonstrates getting process information by invoking wmic.exe (which is only included in XP Professional or higher).

Python

import codecs
import os
import subprocess

def main():
    all_proc_info = get_proc_info('NAME="explorer.exe"')

    test.log("All names and values of first process found:");
    first_process = all_proc_info[0];
    for n, v in first_process.iteritems():
        test.log("  " + n + ": " + v);

    test.log("")

    test.log("Accessing a single value:")
    test.log("  CommandLine: " + first_process["CommandLine"])

def get_proc_info(search_expression=None):
    if search_expression is None:
        search_expression = ""
    else:        
        search_expression = " WHERE " + search_expression

    # Execute with wmic and capture output:
    s = 'pushd "' + os.getcwd() + '" && wmic PROCESS ' + search_expression + ' GET * /format:csv <nul'
    d = subprocess.Popen(s, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()[0];

    # Strip first empty line produced by wmic:
    d = d[3:]

    # Write to file (to later read via testData API):
    fn = "temp.csv"
    f = codecs.open(fn, "w", "utf8")
    f.write(d)
    f.close()

    # Read via testData API:
    dataset = testData.dataset(fn)
    all_proc_info = []
    for row in dataset:
        proc_info = {}
        field_names = testData.fieldNames(row)
        for n in field_names:
            v = testData.field(row, n)
            proc_info[n] = v
        all_proc_info.append(proc_info)
    os.remove(fn)
    return all_proc_info
test.py

JavaScript

function main()
{
    var all_proc_info = get_proc_info('NAME="explorer.exe"');

    var first_process = all_proc_info[0];
    test.log("All names and values of first process found:");
    for (n in first_process) {
        var v = first_process[n];
        test.log("  " + n + ": " + v);
    }

    test.log("");

    test.log("Accessing a single value:");
    test.log("  CommandLine: " + first_process["CommandLine"]);
}

function get_proc_info(search_expression)
{
    // If not provided search for all processes;
    // if provided add WHERE keyword to search_expression:
    if (search_expression == null) {
        search_expression = "";
    } else {
        search_expression = " WHERE " + search_expression;
    }

    // Execute with wmic and capture output:
    var s = 'pushd "' + OS.cwd() + '" && wmic PROCESS ' + search_expression + ' GET * /format:csv <nul';
    var d = OS.capture(s);

    // Strip first empty line produced by wmic:
    d = d.substring(2);

    // Write to file (to later read via testData API):
    File.encoding = "utf-8";
    var fn = "temp.csv";
    var f = File.open(fn, "w");
    f.write(d);
    f.close();

    // Read via testData API:
    dataset = testData.dataset(fn);
    all_procs_info = [];
    for (var i = 0; i < dataset.length; i++) {
        proc_info = {};
        var row = dataset[i];
        var field_names = testData.fieldNames(row);
        for (var j = 0; j < field_names.length; j++) {
            var n = field_names[j];
            var v = testData.field(row, n);
            proc_info[n] = v;
        }
        all_procs_info.push(proc_info);
    }
    File.remove(fn);
    return all_procs_info;
}
test.js

Example - Determining new processes

Note that this solution contains a little loophole because a process ID can be used again when a process quits and a new process gets started. So for a perfect solution one should compare the values of the ProcessId and CreationDate fields (see Win32_Process class ).

def main():
    # Fetch information for current processes:
    proc_info_old = get_proc_info()

    # Extract list of PIDs:
    pids_old = get_all(proc_info_old, "ProcessId")



    # Do something that starts one or more new processes:
    os.system('start notepad.exe')



    # Fetch information for current processes:
    proc_info_new = get_proc_info()

    # Extract list of PIDs:
    pids_new = get_pids(proc_info_new, "ProcessId")



    # Determine PIDs which are only in pids_new, not in pids_old:
    new_pids = list(set(pids_new) - set(pids_old))

    # Output new PIDs and the associated command line:
    for pid in new_pids:
        cmd = get_for(proc_info_new, "ProcessId", pid, "CommandLine")
        test.log("PID: %s" % pid)
        test.log("CMD: %s" % cmd)
        test.log("")

    os.system("taskkill /f /im notepad.exe")

def get_all(proc_info, get_name):
    res = []
    for pi in proc_info:
        res.append(pi[get_name])
    return res

def get_for(proc_info, look_for_name, look_for_value, get_name):
    for pi in proc_info:
        if pi[look_for_name] == look_for_value:
            return pi[get_name]
    return None

def get_proc_info(search_expression=None):
    if search_expression is None:
        search_expression = ""
    else:        
        search_expression = " WHERE " + search_expression

    # Execute with wmic and capture output:
    s = 'pushd "' + os.getcwd() + '" && wmic PROCESS ' + search_expression + ' GET * /format:csv <nul'
    d = subprocess.Popen(s, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()[0];

    # Strip first empty line produced by wmic:
    d = d[3:]

    # Write to file (to later read via testData API):
    fn = "temp.csv"
    f = codecs.open(fn, "w", "utf8")
    f.write(d)
    f.close()

    # Read via testData API:
    dataset = testData.dataset(fn)
    all_proc_info = []
    for row in dataset:
        proc_info = {}
        field_names = testData.fieldNames(row)
        for n in field_names:
            v = testData.field(row, n)
            proc_info[n] = v
        all_proc_info.append(proc_info)
    os.remove(fn)
    return all_proc_info
test.py