diff --git a/gpii/node_modules/processHandling/processHandling.js b/gpii/node_modules/processHandling/processHandling.js index 8e518e796..4bae2b60c 100644 --- a/gpii/node_modules/processHandling/processHandling.js +++ b/gpii/node_modules/processHandling/processHandling.js @@ -24,94 +24,29 @@ var gpii = fluid.registerNamespace("gpii"); var windows = fluid.registerNamespace("gpii.windows"); require("../WindowsUtilities/WindowsUtilities.js"); +require("../processReporter/processReporter.js"); var c = windows.API_constants; +var processesBridge = gpii.processes.windows(); /** * Kills any windows processes with a given application filename. * http://stackoverflow.com/questions/7956519/how-to-kill-processes-by-name-win32-api * - * @param {String} The filename of the application. For example, the Windows on + * @param filename {String} The filename of the application. For example, the Windows on * screen keyboard is "osk.exe". Other examples include "Magnify.exe" and * "firefox.exe". */ gpii.windows.killProcessByName = function (filename) { - var pids = gpii.windows.findProcessByName(filename, true); - if (pids) { - for (var n = 0, len = pids.length; n < len; n++) { - var hProcess = windows.kernel32.OpenProcess(c.PROCESS_TERMINATE, 0, pids[n]); - if (hProcess !== ref.NULL) { - windows.kernel32.TerminateProcess(hProcess, 9); - windows.kernel32.CloseHandle(hProcess); - } - } - } -}; - -/** - * Finds a running process with the given name. - * - * The CreateToolhelp32Snapshot Windows API call captures the running processes, and the Process32First/Next - * functions are used to enumerate them. - * - * @param filename The exe file name to search for, null to match any. - * @param all {boolean?} Set to true to return an array containing all matching processes. - * @param fullInfo {boolean?} Set to true to return the pid, ppid, and exe name of matching processes. - * @returns {?number|number[]} The Process ID of the matching processes, otherwise null. - */ -gpii.windows.findProcessByName = function (filename, all, fullInfo) { - - // Get a snapshot of the processes. - var hSnapShot = windows.kernel32.CreateToolhelp32Snapshot(windows.API_constants.TH32CS_SNAPPROCESS, null); - if (hSnapShot === windows.API_constants.INVALID_HANDLE_VALUE) { - console.error("CreateToolhelp32Snapshot failed. Win32 error: " + windows.GetLastError()); - return null; - } + var procs = processesBridge.findProcessesByCommand(filename); - var matches = []; - var filenameLower = filename && filename.toLowerCase(); - - try { - // Create the structure for the return parameter of Process32First/Next. - var pEntry = new windows.PROCESSENTRY32(); - pEntry.dwSize = windows.PROCESSENTRY32.size; - - // Enumerate the processes. - var hRes = windows.kernel32.Process32First(hSnapShot, pEntry.ref()); - while (hRes) { - var buf = new Buffer(pEntry.szExeFile); - var processName = ref.readCString(buf, 0); - - if (!filename || processName.toLowerCase() === filenameLower) { - var proc; - if (fullInfo) { - proc = { - pid: pEntry.th32ProcessID, - ppid: pEntry.th32ParentProcessID, - exeFile: processName - }; - } else { - proc = pEntry.th32ProcessID; - } - if (all) { - // Add it to the array of matches. - matches.push(proc); - } else { - // Only want the first one - return it. - return proc; - } - } - - hRes = windows.kernel32.Process32Next(hSnapShot, pEntry.ref()); - } - } finally { - // Make sure the snapshot is closed. - if (hSnapShot) { - windows.kernel32.CloseHandle(hSnapShot); + for (var n = 0, len = procs.length; n < len; n++) { + var hProcess = windows.kernel32.OpenProcess(c.PROCESS_TERMINATE, 0, procs[n].pid); + if (hProcess !== ref.NULL) { + windows.kernel32.TerminateProcess(hProcess, 9); + windows.kernel32.CloseHandle(hProcess); } } - - return all ? matches : null; }; /** @@ -123,7 +58,7 @@ gpii.windows.findProcessByName = function (filename, all, fullInfo) { gpii.windows.isProcessRunning = function (proc) { var togo = false; if (isNaN(proc)) { - togo = gpii.windows.findProcessByName(proc) !== null; + togo = gpii.processReporter.find(proc); } else { try { process.kill(proc, 0); @@ -234,7 +169,9 @@ gpii.windows.closeProcessByName = function (filename, options) { options = fluid.extend(defaultOptions, options); - var pids = gpii.windows.findProcessByName(filename, true); + var pids = fluid.transform(processesBridge.findProcessesByCommand(filename), function (proc) { + return proc.pid; + }); if (!pids) { // Process is not running. return fluid.toPromise(true); @@ -296,60 +233,6 @@ gpii.windows.closeProcessByName = function (filename, options) { return promiseTogo; }; -/** - * Gets the path to the executable of a running process. - * - * Provide the processHandle if it's available when calling, otherwise provide the pid. - * - * @param pid {Number} [Optional] The process ID. - * @param processHandle [Optional] The process handle. - * @return {String} The path to the executable. - */ -gpii.windows.getProcessPath = function (pid, processHandle) { - var hProcess; - var togo = null; - - if (processHandle) { - hProcess = processHandle; - } else if (pid) { - hProcess = - gpii.windows.kernel32.OpenProcess(gpii.windows.API_constants.PROCESS_QUERY_LIMITED_INFORMATION, 0, pid); - } else { - fluid.fail("Either pid or processHandle needs to be given."); - } - - if (hProcess) { - try { - var size = ref.alloc(gpii.windows.types.DWORD); - size.writeUInt32LE(gpii.windows.API_constants.MAX_PATH, 0); - var path = new Buffer(gpii.windows.API_constants.MAX_PATH); - - var success = gpii.windows.kernel32.QueryFullProcessImageNameW(hProcess, 0, path, size); - if (success) { - togo = gpii.windows.fromWideChar(path); - } - } finally { - if (hProcess !== processHandle) { - gpii.windows.kernel32.CloseHandle(hProcess); - } - } - } - - if (!togo) { - // OpenProcess or QueryFullProcessImageName failed (usually due to permissions). Get the file name from the - // process list instead. - var all = gpii.windows.findProcessByName(null, true, true); - var process = all.find(function (p) { - return p.pid === pid; - }); - if (process) { - togo = process.exeFile; - } - } - return togo; - -}; - /** * Determines the current state of a service, which can be one of paused, running, or stopped: * @@ -404,7 +287,6 @@ gpii.windows.getServiceState = function (serviceName) { return state; }; - fluid.defaults("gpii.windows.killProcessByName", { gradeNames: "fluid.function", argumentMap: { diff --git a/gpii/node_modules/processHandling/test/testProcessHandling.js b/gpii/node_modules/processHandling/test/testProcessHandling.js index d24147f6a..7f9ed792a 100644 --- a/gpii/node_modules/processHandling/test/testProcessHandling.js +++ b/gpii/node_modules/processHandling/test/testProcessHandling.js @@ -46,27 +46,6 @@ jqUnit.module("gpii.tests.windows.processHandling", { } }); -jqUnit.test("Testing findProcessByName", function () { - // Find a process that isn't running. - var pid = gpii.windows.findProcessByName("a non-matching process.exe"); - jqUnit.assertEquals("Process should not have been found running", null, pid); - - // Find a process that is running. - pid = gpii.windows.findProcessByName("node.exe"); - jqUnit.assertNotEquals("Process should have been found running", null, pid); - - // Find a process that is running, full details - var details = gpii.windows.findProcessByName("node.exe", false, true); - jqUnit.assertNotEquals("Process should have been found running (fullInfo)", null, details); - jqUnit.assertTrue("pid should be a number", typeof(details.pid) === "number"); - jqUnit.assertTrue("ppid should be a number", typeof(details.ppid) === "number"); - jqUnit.assertEquals("exeFile should be node.exe", "node.exe", details.exeFile.toLowerCase()); - - // Find multiple processes. There's always more than one svchost.exe running on Windows. - var pids = gpii.windows.findProcessByName("svchost.exe", true); - jqUnit.assertTrue("Should have found several matching process.", pids.length > 1); -}); - jqUnit.test("Testing isProcessRunning", function () { // Check a PID that isn't running. var running = gpii.windows.isProcessRunning(-1); @@ -118,8 +97,8 @@ jqUnit.asyncTest("Testing timeout waiting for processes termination", function ( jqUnit.asyncTest("Testing waiting for processes start and end", function () { jqUnit.expect(3); - var pid = gpii.windows.findProcessByName(waitExe); - jqUnit.assertEquals("The process should not already be running.", null, pid); + var running = gpii.processReporter.find(waitExe); + jqUnit.assertFalse("The process should not already be running.", running); // Timeout waiting for the process start/end after 10 seconds. var options = { timeout: 10000 }; @@ -151,8 +130,8 @@ jqUnit.asyncTest("Testing waiting for processes start and end", function () { jqUnit.asyncTest("Testing Killing Processes", function () { jqUnit.expect(3); - var pid = gpii.windows.findProcessByName(waitExe); - jqUnit.assertEquals("The process should not already be running.", null, pid); + var running = gpii.processReporter.find(waitExe); + jqUnit.assertFalse("The process should not already be running.", running); // On the call below, async is true because if it is false shelljs will // wait around until it is manually killed before continuing with the @@ -237,39 +216,6 @@ jqUnit.asyncTest("Testing closeProcessByName (window-less process)", function () child_process.exec(command); }); -jqUnit.asyncTest("Testing getProcessPath", function () { - jqUnit.expect(3); - - var exeName = waitExe; - var exePath = waitExePath; - var args = [ "getProcessPathTest", "/T", "30"]; - - fluid.log("Executing " + exePath); - var child = child_process.spawn(exePath, args); - - gpii.windows.waitForProcessStart(exeName) - .then(function () { - jqUnit.assert("Process started"); - - // Test with the PID. - var result1 = gpii.windows.getProcessPath(child.pid); - jqUnit.assertEquals("The exe path should be correct (pid)", exePath, result1); - - // Test with the process handle. - var hProcess = gpii.windows.kernel32.OpenProcess( - gpii.windows.API_constants.PROCESS_QUERY_LIMITED_INFORMATION, 0, child.pid); - - try { - var result2 = gpii.windows.getProcessPath(null, hProcess); - jqUnit.assertEquals("The exe path should be correct (processHandle)", exePath, result2); - } finally { - gpii.windows.kernel32.CloseHandle(hProcess); - } - - child.kill(); - }); - child.on("close", jqUnit.start); -}); jqUnit.test("Testing getServiceState", function () { // Local Session Manager will always be running. diff --git a/gpii/node_modules/processReporter/dotNetProcesses.csx b/gpii/node_modules/processReporter/dotNetProcesses.csx index 6eeec6232..da64d4a1b 100644 --- a/gpii/node_modules/processReporter/dotNetProcesses.csx +++ b/gpii/node_modules/processReporter/dotNetProcesses.csx @@ -51,7 +51,8 @@ public class Startup } } else { ManagementObject[] someProcesses = Array.FindAll( - processes, p => p.GetPropertyValue("Name").ToString() == input + processes, + p => string.Equals(p.GetPropertyValue("Name").ToString(), input, StringComparison.OrdinalIgnoreCase) ); foreach (ManagementObject p in someProcesses) { makeAndAppendProcInfo(p, result); diff --git a/gpii/node_modules/processReporter/processesBridge.js b/gpii/node_modules/processReporter/processesBridge.js index e461d5377..30d2db198 100644 --- a/gpii/node_modules/processReporter/processesBridge.js +++ b/gpii/node_modules/processReporter/processesBridge.js @@ -36,7 +36,8 @@ fluid.defaults("gpii.processes.windows", { args: ["{arguments}.0"] // process name or id, optional. } - } + }, + ignoreCase: true }); /** diff --git a/gpii/node_modules/processReporter/test/processesBridge_tests.js b/gpii/node_modules/processReporter/test/processesBridge_tests.js index 914364904..24d498bb6 100644 --- a/gpii/node_modules/processReporter/test/processesBridge_tests.js +++ b/gpii/node_modules/processReporter/test/processesBridge_tests.js @@ -129,6 +129,25 @@ jqUnit.test( } ); +jqUnit.test( + "Test findProcessesByCmd()/findFirstProcessByCmd() with nodejs itself - ignoring case", + function () { + var nodeProcInfos = processesBridge.findProcessesByCommand("NoDE.eXe"); + jqUnit.assertNotEquals( + "Getting all 'NoDE.eXe' processes", 0, nodeProcInfos.length + ); + nodeProcInfos.forEach(function (aProcInfo) { + jqUnit.assertEquals( + "Node commmand name", "node.exe", aProcInfo.command + ); + }); + var procInfo = processesBridge.findFirstProcessByCommand("NoDE.eXe"); + jqUnit.assertNotNull( + "Looking for first 'NoDE.eXe' processes", procInfo); + jqUnit.assertEquals("Node commmand name", "node.exe", procInfo.command); + } +); + jqUnit.test( "Test initProcInfoNotRunning()", function () { diff --git a/gpii/node_modules/registeredAT/test/testRegisteredAT.js b/gpii/node_modules/registeredAT/test/testRegisteredAT.js index 134d1765b..326d2bc07 100644 --- a/gpii/node_modules/registeredAT/test/testRegisteredAT.js +++ b/gpii/node_modules/registeredAT/test/testRegisteredAT.js @@ -140,8 +140,8 @@ jqUnit.asyncTest("Testing AT start and stop", function () { }); }); - var pid = gpii.windows.findProcessByName(testData.ATExe); - jqUnit.assertEquals("The process should not already be running.", null, pid); + var running = gpii.processReporter.find(testData.ATExe); + jqUnit.assertFalse("The process should not already be running.", running); gpii.windows.startRegisteredAT(testData.appName, {atInfo: testData}); diff --git a/gpii/node_modules/windowsMetrics/src/windowsMetrics.js b/gpii/node_modules/windowsMetrics/src/windowsMetrics.js index 1a7aca1b2..e37be3499 100644 --- a/gpii/node_modules/windowsMetrics/src/windowsMetrics.js +++ b/gpii/node_modules/windowsMetrics/src/windowsMetrics.js @@ -22,7 +22,10 @@ var ffi = require("ffi"); var fluid = require("gpii-universal"); -var windows = fluid.registerNamespace("gpii.windows"); +var gpii = fluid.registerNamespace("gpii"), + windows = fluid.registerNamespace("gpii.windows"); + +var processesBridge = gpii.processes.windows(); fluid.require("%gpii-windows/gpii/node_modules/WindowsUtilities/WindowsUtilities.js"); @@ -253,7 +256,7 @@ windows.checkActiveWindow = function (that) { // Log how long the last window was active. windows.logAppActivate(that); - var exePath = windows.getProcessPath(activePid); + var exePath = processesBridge.getProcessPath(activePid); that.state.application.currentProcess.pid = activePid; that.state.application.currentProcess.exe = exePath; diff --git a/gpii/node_modules/windowsMetrics/test/WindowsMetricsTests.js b/gpii/node_modules/windowsMetrics/test/WindowsMetricsTests.js index 03b3218d4..ba2cccd56 100644 --- a/gpii/node_modules/windowsMetrics/test/WindowsMetricsTests.js +++ b/gpii/node_modules/windowsMetrics/test/WindowsMetricsTests.js @@ -692,13 +692,16 @@ jqUnit.asyncTest("Testing application metrics", function () { windowsMetrics.config.application.precision = 1; + var processesBridge = gpii.processes.windows(); + // Pick three windows (owned by different processes) that already exist, and pretend they've became active by // mocking GetForegroundWindow. var windows = []; var exes = {}; gpii.windows.enumerateWindows(function (hwnd) { if (windows.length < 3) { - var exe = gpii.windows.getProcessPath(gpii.windows.getWindowProcessId(hwnd)); + + var exe = processesBridge.getProcessPath(gpii.windows.getWindowProcessId(hwnd)); if (!exes[exe]) { exes[exe] = true; windows.push({ diff --git a/package.json b/package.json index 0eb848ea5..b6c527c31 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "edge-js": "8.8.1", "string-argv": "0.0.2", "@pokusew/pcsclite": "0.4.18", - "gpii-universal": "0.3.0-dev.20180314T153442Z.bcc35970" + "gpii-universal": "stegru/universal#GPII-2578" }, "devDependencies": { "grunt": "1.0.2",