Here is what I have tried:
Get-Process | Where-Object {$_.Path -eq "C:\path\stream1.bat"} | Stop-Process -Force
Start-Sleep -Seconds 5
Start-Process -FilePath "cmd.exe" -ArgumentList "/c `"C:\path\stream1.bat`""
The Start-Process
command works perfectly, however the Stop-Process
command does nothing.
One issue with your current code is that .Path
(in reality this property is .MainModule.FileName
) will be the path to cmd.exe
not the .bat
file itself. What you can do in this case is query Win32_Process
and filter by the CommandLine
property where it contains the path of your .bat
. This solves one of the problems.
The next problem will be to find all sub processes that your .bat
file could've started, these need to be terminated first before terminating cmd.exe
itself. For this, again, you can query Win32_Process
to find all processes having the ParentProcessId
equal to the process id of your cmd.exe
process.
$bat = 'C:\path\stream1.bat'
# WQL requires escaping of `\`
$cmdline = $bat.Replace('\', '\\')
$getCimInstanceSplat = @{
Filter = "Name = 'cmd.exe' AND CommandLine LIKE '%$cmdline%'"
ClassName = 'Win32_Process'
}
# Find the cmd process containing the path of the `.bat` file
$proc = Get-CimInstance @getCimInstanceSplat
$getCimInstanceSplat = @{
Filter = "ParentProcessId = '$($proc.ProcessId)'"
ClassName = 'Win32_Process'
}
# Find all processes started by that bat file
Get-CimInstance @getCimInstanceSplat |
# and terminate all of them
Invoke-CimMethod -MethodName Terminate
# In case the parent process didn't terminate after that
# attempt to terminate it as well
$proc | Invoke-CimMethod -MethodName Terminate -EA 0