@@ -36,11 +36,18 @@ export function spawnToResult(command: string, args: string[] = [], options = {}
36
36
} ) ;
37
37
} ;
38
38
39
+ export function spawnPowerShellToResult ( command : string ) {
40
+ return spawnToResult ( 'powershell.exe' , [
41
+ '-NoProfile' , '-NonInteractive' ,
42
+ '-Command' , command
43
+ ] ) ;
44
+ }
45
+
39
46
type Proc = {
40
47
pid : number ,
41
- command : string ,
42
- bin : string | undefined ,
43
- args : string | undefined
48
+ command : string , // Process name (often short binary name)
49
+ bin : string | undefined , // Full path to the binary, if available
50
+ args : string | undefined // Arguments as a single string, if available
44
51
} ;
45
52
46
53
const getOutputLines = ( stdout : string ) =>
@@ -122,36 +129,38 @@ export async function listRunningProcesses(): Promise<Array<Proc>> {
122
129
123
130
return processes ;
124
131
} else {
125
- const wmicOutput = await spawnToResult ( 'wmic' , [
126
- 'Process' , 'Get' , 'processid,commandline'
127
- ] ) ;
132
+ const pshResult = await spawnPowerShellToResult (
133
+ 'Get-CimInstance Win32_Process | ' +
134
+ 'ForEach-Object { "$($_.ProcessId)|$($_.Name)|$($_.CommandLine)|$($_.ExecutablePath)" }'
135
+ ) ;
128
136
129
- if ( wmicOutput . exitCode !== 0 ) {
130
- throw new Error ( `WMIC exited with unexpected error code ${ wmicOutput . exitCode } ` ) ;
137
+ if ( pshResult . exitCode !== 0 ) {
138
+ throw new Error ( `PowerShell process query exited with unexpected error code ${ pshResult . exitCode } ` ) ;
131
139
}
132
140
133
- return getOutputLines ( wmicOutput . stdout )
134
- . slice ( 1 ) // Skip the header line
135
- . filter ( ( line ) => line . includes ( ' ' ) ) // Skip lines where the command line isn't available (just pids)
136
- . map ( ( line ) => {
137
- const pidIndex = line . lastIndexOf ( ' ' ) + 1 ;
138
- const pid = parseInt ( line . substring ( pidIndex ) , 10 ) ;
139
-
140
- const command = line . substring ( 0 , pidIndex ) . trim ( ) ;
141
- const bin = command [ 0 ] === '"'
142
- ? command . substring ( 1 , command . substring ( 1 ) . indexOf ( '"' ) + 1 )
143
- : command . substring ( 0 , command . indexOf ( ' ' ) ) ;
144
- const args = command [ 0 ] === '"'
145
- ? command . substring ( bin . length + 3 )
146
- : command . substring ( bin . length + 1 ) ;
147
-
148
- return {
149
- pid,
150
- command,
151
- bin,
152
- args
153
- } ;
154
- } ) ;
141
+ return getOutputLines ( pshResult . stdout )
142
+ . map ( line => {
143
+ const [ pid , command , commandLine , bin ] = line . split ( '|' ) ;
144
+
145
+ let args : string | undefined ;
146
+ if ( commandLine . startsWith ( '"' ) ) {
147
+ // Command line might start with full path or bare binary name:
148
+ if ( commandLine . startsWith ( `"${ bin } "` ) ) {
149
+ args = commandLine . substring ( bin . length + 3 ) ;
150
+ } else if ( commandLine . startsWith ( `"${ command } "` ) ) {
151
+ args = commandLine . substring ( command . length + 3 ) ;
152
+ }
153
+ // There's probably other possibilities, but it's not critical enough that we
154
+ // need to bother trying to be much smarter here.
155
+ } else {
156
+ const firstSpace = commandLine . indexOf ( ' ' ) ;
157
+ if ( firstSpace !== - 1 ) {
158
+ args = commandLine . substring ( firstSpace + 1 ) ;
159
+ }
160
+ }
161
+
162
+ return { pid : parseInt ( pid , 10 ) , command, bin, args } as Proc ;
163
+ } ) ;
155
164
}
156
165
}
157
166
@@ -183,12 +192,11 @@ export async function windowsClose(pid: number) {
183
192
] ) ;
184
193
}
185
194
186
- // Harshly kill a windows process by some WMIC matching string e.g.
187
- // "processId=..." or "CommandLine Like '%...%'"
188
- export async function windowsKill ( processMatcher : string ) {
189
- await spawnToResult ( 'wmic' , [
190
- 'Path' , 'win32_process' ,
191
- 'Where' , processMatcher ,
192
- 'Call' , 'Terminate'
193
- ] , { } , true ) ;
195
+ // Harshly kill a windows process by command-line match:
196
+ export async function windowsKillByCliMatch ( globMatcher : string ) {
197
+ await spawnPowerShellToResult (
198
+ 'Get-CimInstance Win32_Process | ' +
199
+ `Where-Object { $_.CommandLine -like "${ globMatcher } " } | ` +
200
+ 'ForEach-Object { $_.Terminate() }'
201
+ ) ;
194
202
}
0 commit comments