For an auto-testing sceanrio on Windows, I needed to start a number of Eclipse instances, each one with a particular workspace of system tests. In case of problems, I wanted  to quickly(, i.e., automatically) stop all instances. For starting and for stopping the instances, I created two Powershell scripts.

Starting Eclipse

When starting Eclipse, all we have to do is store the process id of each instance. Thanks to PowerShell being object-oriented, this is relatively easy. The Start-Process cmdlet returns a process instance when called with the parameter -PassThru, which can be queried for its Id property. We cache the process ids in a line-by-line manner to stop each instance later on.

$ECLIPSE_HOME = "C:\Program Files\eclipse"
$WORKSPACES = "TestWorkspace1","TestWorkspace"
$OUTPUT_DIRECTORY="$HOME\autotest_tmp_dir"

foreach ($WORKSPACE in $WORKSPACES) {
  $eclipse = Start-Process 
     -FilePath $ECLIPSE_HOME\eclipse.exe 
     -ArgumentList '-data',$WORKSPACE,'-application','org.moflon.testapplication','-showLocation'   
     -PassThru
  echo "    [$($eclipse.Id)] Workspace '$WORKSPACE'"
  $eclipse.Id >> "$OUTPUT_DIRECTORY\pids.txt"
}

Stopping Eclipse

A plethora of methods for stopping processes using PowerShell exists. Basically, you need to get a process object (using Get-Process) and call the Kill or Terminate method on it.

Unfortunately, Eclipse kept running after killing its correspondent process: Get-Process eclipse | Stop-Process .

The reason is that Eclipse spawns a child process running javaw.exe. This is the process that needs to be stopped, but killing it leads to an ugly error message. So the method of choice is to call CloseMainWindow() on the javaw process, which triggers the same action as pressing on the ‘X’ in the top-right corner. The remaining challenge is to find out, which of the running javaw processes belong to which Eclipse instance. This can be achieved with the cmdlet Find-ChildProcess as described by Tobias Weltner. The complete scripts looks as follows:

# http://powershell.com/cs/blogs/tobias/archive/2012/05/09/managing-child-processes.aspx
function Find-ChildProcess {
  param($ID=$PID)

  $CustomColumnID = @{
    Name = 'Id'
    Expression = { [Int[]]$_.ProcessID }
  }

  $result = Get-WmiObject -Class Win32_Process -Filter "ParentProcessID=$ID" |
  Select-Object -Property ProcessName, $CustomColumnID, CommandLine
  
  $result
  $result | Where-Object { $_.ID -ne $null } | ForEach-Object {
    Find-ChildProcess -id $_.Id
  }
}


$outputDirectory="$HOME\autotest_tmp_dir"
$filename = "$outputDirectory\pids.txt"
foreach ($id in [System.IO.File]::ReadLines($filename)) {
   $child = Find-ChildProcess $id
	(Get-Process -Id $child.Id).CloseMainWindow()
}