Killing Tasks on Windows with R
On my Windows machine, I oftentimes want to kill a set of applications that are running. This is especially true when I don’t have full control of my machine and am unable to adjust the applications that launch on startup.
Below are two examples — both accomplish the same feat — that use R to call down to the OS and kill a list of tasks / applications. One example is more readable while the other is more terse. An alternative impetus for writing the short scripts below was to experiment with the processx package. A more portable way to accomplish would be to simply use PowerShell. But this was a fun exercise.
Taskkill — Readable, Annotated
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# install (if applicable) | |
# install.packages(c("dplyr", | |
# "processx", | |
# "purrr", | |
# "readr")) | |
# libraries | |
suppressWarnings(suppressMessages(library("dplyr"))) | |
suppressWarnings(suppressMessages(library("processx"))) | |
suppressWarnings(suppressMessages(library("purrr"))) | |
suppressWarnings(suppressMessages(library("readr"))) | |
# list of applications to kill | |
kill_list <- c( | |
"calc.exe", | |
"notepad.exe" | |
) | |
# the below calls out to the operating system and runs | |
# the command "tasklist /fo csv" on the Windows command line | |
# its standard output -- what is printed on the screen -- | |
# is captured and stored as a string within the list element named stdout | |
# stdout is then separated as a single character vector and piped into | |
# the read_csv function from readr | |
# the final result is a dataframe with the output from the tasklist command | |
# %>% and %$% are from either dplyr or purrr | |
task_list <- processx::run(commandline = "tasklist /fo csv") %$% | |
stdout %>% | |
readr::read_csv() | |
# filter the dataframe to just those tasks in the list above | |
# note the need for backquotes (``) for the column name as it contains | |
# and embedded space | |
tasks_to_kill <- task_list %>% | |
dplyr::filter(`Image Name` %in% kill_list) | |
# function for printing out the commands that will be run | |
print_task <- function(x) { | |
paste0("taskkill /f / pid ", x) %>% print() | |
} | |
# print out what is about to be performed | |
# extract out the PID column from the dataframe | |
# and pass each value of PID into the print_task function | |
# walk is used for iteratively applying a function that has | |
# side effects to each element in a list | |
tasks_to_kill %$% | |
PID %>% | |
purrr::walk(print_task) | |
# callback = simply echo the line back out | |
# using a callback is better than using the echo option within | |
# processx::run as it will not throw R errors but simply | |
# print out the standard error to the console | |
cb <- function(line, proc) { | |
cat(line, "\n") | |
} | |
# function to actually kill a task | |
kill_task <- function(x) { | |
processx::run(commandline = paste0("taskkill /f /pid ", x), | |
error_on_status = FALSE, | |
stdout_line_callback = cb, | |
stderr_line_callback = cb) | |
} | |
# iterate over all the tasks to kill, killing each one by one | |
tasks_to_kill %$% | |
PID %>% | |
purrr::walk(kill_task) |
Taskkill — Terse, Single Pipeline
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# for checking and installing packages | |
# extracted from CRAmisc package | |
# https://github.com/curtisalexander/CRAmisc/blob/master/R/install.R | |
check_install <- function(pkgs, repos = NULL, ...) { | |
installed_packages <- installed.packages()[ ,1] | |
for (i in seq_along(pkgs)) { | |
pkg <- pkgs[[i]] | |
if (!pkg %in% installed_packages) { | |
cat(paste0("Need to install: ", pkg, "\n")) | |
if(is.null(repos)) install.packages(pkg, repos = "https://cran.rstudio.com") | |
else install.packages(pkg, repos = repos, ...) | |
} else cat(paste0(pkg, " already installed\n")) | |
} | |
invisible(pkgs) | |
} | |
req_pkgs <- list( | |
"dplyr", | |
"processx", | |
"purrr", | |
"readr" | |
) | |
check_install(req_pkgs) | |
# list of applications to kill | |
kill_list <- c( | |
"calc.exe", | |
"notepad.exe" | |
) | |
# callback | |
cb <- function(line, proc) { | |
cat(line, "\n") | |
} | |
# kill tasks using a single pipeline | |
taskkill <- function(klist) { | |
processx::run(commandline = "tasklist /fo csv") %$% | |
stdout %>% | |
readr::read_csv() %>% | |
dplyr::filter(`Image Name` %in% klist) %$% | |
PID %>% | |
purrr::walk(~ processx::run(commandline = paste0("taskkill /f /pid ", .), | |
error_on_status = FALSE, | |
stdout_line_callback = cb, | |
stderr_line_callback = cb)) | |
} | |
taskkill(kill_list) |