Skip to content

Commit dde634d

Browse files
authored
Due to wmic has been deprecated. Use @vscode/windows-process-tree for Windows process listing with WMIC fallback (#991)
* Use windows-process-tree on Windows for process listing Add @vscode/windows-process-tree as a dependency and use it on Windows to enumerate processes (via promisified getAllProcesses). Fall back to the existing WMIC parser when windows-process-tree is unavailable. Update provider logic to return parsed process items from the native API on Windows and keep PS-based listing for macOS/Linux. Update unit tests to stub and exercise the new getAllProcesses flow and the WMIC fallback, and add webpack externals entry for the new native module. * Update tests for getAllProcesses signature Adjust Windows process provider unit tests to match the updated getAllProcesses API that accepts a flag parameter and uses an error-first callback. Stubs now use signatures like (_flag, callback) and call callback(null, processList); throwing stubs were updated to accept two arguments. These are test-only updates to align with the new function signature. * Wrap wpc.getAllProcesses in a Promise Replace use of util.promisify with an explicit Promise wrapper around wpc.getAllProcesses, removing the promisify import and adapting the call site to resolve with the process list. Update unit tests to match the changed callback shape (stubs now call callback(processList) and throw without an error-first parameter). This keeps Windows process enumeration working while aligning with the windows-process-tree callback behavior. * Switch windows-process-tree from static import to dynamic require Static imports can cause the entire module to fail if the native plugin's ABI doesn't match the running Node version. Using dynamic `require()` within a `try-catch` statement allows for a fallback to WMIC if the module is unavailable or incompatible. To ensure compile-time type safety, only type imports are retained. Add a comment to webpack externals explaining why the native addon must be excluded from bundling. * Use block eslint-disable for naming-convention in tests Replace single-line eslint-disable-next-line comments with explicit block disables/enables around the assertions in src/test/unittest/common/environment.unit.test.ts. This silences @typescript-eslint/naming-convention for the expected object literals (e.g. VAR1/VAR2) while keeping the rule enabled elsewhere. * Format process-related calls for readability Reformat long function calls in AttachProcessProvider for improved readability. Split arguments for wpc.getAllProcesses and logProcess into multiple lines (with trailing commas); no functional changes.
1 parent 421eabb commit dde634d

6 files changed

Lines changed: 286 additions & 36 deletions

File tree

package-lock.json

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@
687687
"@vscode/debugprotocol": "^1.65.0",
688688
"@vscode/extension-telemetry": "^0.8.4",
689689
"@vscode/python-extension": "^1.0.6",
690+
"@vscode/windows-process-tree": "^0.7.0",
690691
"fs-extra": "^11.2.0",
691692
"iconv-lite": "^0.6.3",
692693
"jsonc-parser": "^3.0.0",

src/extension/debugger/attachQuickPick/provider.ts

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
'use strict';
55

66
import { l10n } from 'vscode';
7+
import type { IProcessInfo } from '@vscode/windows-process-tree';
78
import { getOSType, OSType } from '../../common/platform';
89
import { PsProcessParser } from './psProcessParser';
910
import { IAttachItem, IAttachProcessProvider, ProcessListCommand } from './types';
@@ -58,24 +59,52 @@ export class AttachProcessProvider implements IAttachProcessProvider {
5859
}
5960

6061
public async _getInternalProcessEntries(): Promise<IAttachItem[]> {
61-
let processCmd: ProcessListCommand;
6262
const osType = getOSType();
63+
64+
if (osType === OSType.Windows) {
65+
try {
66+
const wpc = require('@vscode/windows-process-tree');
67+
const processList = await new Promise<IProcessInfo[]>((resolve) => {
68+
wpc.getAllProcesses(
69+
(processes: IProcessInfo[]) => resolve(processes),
70+
wpc.ProcessDataFlag.CommandLine,
71+
);
72+
});
73+
return processList.map((p) => ({
74+
label: p.name,
75+
description: String(p.pid),
76+
detail: p.commandLine || '',
77+
id: String(p.pid),
78+
processName: p.name,
79+
commandLine: p.commandLine || '',
80+
}));
81+
} catch {
82+
const customEnvVars = await getEnvironmentVariables();
83+
const output = await plainExec(
84+
WmicProcessParser.wmicCommand.command,
85+
WmicProcessParser.wmicCommand.args,
86+
{ throwOnStdErr: true },
87+
customEnvVars,
88+
);
89+
logProcess(WmicProcessParser.wmicCommand.command, WmicProcessParser.wmicCommand.args, {
90+
throwOnStdErr: true,
91+
});
92+
return WmicProcessParser.parseProcesses(output.stdout);
93+
}
94+
}
95+
96+
let processCmd: ProcessListCommand;
6397
if (osType === OSType.OSX) {
6498
processCmd = PsProcessParser.psDarwinCommand;
6599
} else if (osType === OSType.Linux) {
66100
processCmd = PsProcessParser.psLinuxCommand;
67-
} else if (osType === OSType.Windows) {
68-
processCmd = WmicProcessParser.wmicCommand;
69101
} else {
70102
throw new Error(l10n.t("Operating system '{0}' not supported.", osType));
71103
}
72104

73105
const customEnvVars = await getEnvironmentVariables();
74106
const output = await plainExec(processCmd.command, processCmd.args, { throwOnStdErr: true }, customEnvVars);
75107
logProcess(processCmd.command, processCmd.args, { throwOnStdErr: true });
76-
77-
return osType === OSType.Windows
78-
? WmicProcessParser.parseProcesses(output.stdout)
79-
: PsProcessParser.parseProcesses(output.stdout);
108+
return PsProcessParser.parseProcesses(output.stdout);
80109
}
81110
}

0 commit comments

Comments
 (0)