Jump to content

Start Parallels app if not already started


Recommended Posts

Hi

I am currently using this workflow

http://www.alfredforum.com/topic/202-parallels-desktop-workflow/

 

It queries Parallels and can resume, start etc VMs. I am sorry I did download it from this forum but cannot get hold of the original author. Unfortunately unless Parallels is running, resuming a VM does not work. Does anyone know what code I need to change to start Parallels (if not already running) to resume a VM? The PHP code snippet is below:

 

<?php
 
 
// Main configuration
$inQuery = $argv[1] ?: '';
$reUUID = '(?<uuid>\{[\dA-Fa-f]{8}\-[\dA-Fa-f]{4}\-[\dA-Fa-f]{4}\-[\dA-Fa-f]{4}\-[\dA-Fa-f]{12}\})';
$reList = '/^\s*'.$reUUID.'\s*(?<status>[^\s]+)\s*(?<ip>[^\s]+)\s*(?<name>.*)$/';
if (($isUUID = preg_match('/'.$reUUID.'/', $inQuery, $tmpData) ? true : false) === true)
$inQuery = $tmpData['uuid'];
$supportedActions = array(
'start' => array('running', 'suspended'),
'stop' => array('stopped', 'suspended'),
'reset' => array('stopped', 'suspended'),
'suspend' => array('stopped', 'suspended'),
'resume' => array('running', 'stopped'));
$foundVM = array();
$results = array();
 
 
// Read VM lists
if (exec('prlctl list -a --no-header '.($isUUID ? $inQuery : ''), $output))
foreach ($output AS $row)
if (preg_match($reList, $row, $tmp))
$foundVM[] = $tmp;
 
 
if ($isUUID)
{
// Action lists per VM
foreach ($supportedActions AS $action => $currentStatus)
if (!in_array($foundVM[0]['status'], $currentStatus))
$results[] = array(
'uid' => $action,
'arg' => $action.' '.$inQuery,
'title' => ucfirst($action),
'subtitle' => $foundVM[0]['name'],
'icon' => 'icon.png',
'valid' => 'yes');
 
if ($foundVM[0]['status'] == 'running')
$results[] = array(
'uid' => 'capture',
'arg' => 'capture '.$inQuery.' --file ~/Desktop/'.str_replace(array(' ', '/'), array('-', '-'), $foundVM[0]['name']).'-'.@date('Ymd-his').'.jpg',
'title' => 'Capture a screenshot',
'subtitle' => $foundVM[0]['name'],
'icon' => 'icon.png',
'valid' => 'yes');
} else
{
// List of VM matched
$reRowQuery = '/'.preg_quote($inQuery).'/i';
foreach ($foundVM AS $vm)
if (preg_match($reRowQuery, $vm['name']))
$results[] = array(
'uid' => $vm['uuid'],
'arg' => $vm['uuid'],
'title' => $vm['name'],
'subtitle' => 'Status: '.ucfirst($vm['status']),
'icon' => 'icon.png',
'valid' => 'no',
'autocomplete' => $vm['name'].' '.$vm['uuid']);
}
 
 
// No VM matched
if (!count($results))
$results[] = array(
'uid' => 'none',
'arg' => 'none',
'title' => 'No VM found!',
'subtitle' => 'There aren\'t any VM...',
'icon' => 'icon.png',
'valid' => 'no');
 
 
// Preparing the XML output file
$xmlObject = new SimpleXMLElement("<items></items>");
$xmlAttributes = array('uid', 'arg', 'valid', 'autocomplete');
foreach($results AS $rows)
{
$nodeObject = $xmlObject->addChild('item');
$nodeKeys = array_keys($rows);
foreach ($nodeKeys AS $key)
$nodeObject->{ in_array($key, $xmlAttributes) ? 'addAttribute' : 'addChild' }($key, $rows[$key]);
}
 
// Print the XML output
echo $xmlObject->asXML();  
 
?>

 

Thanks

Edited by gr4z
Link to comment

Well, you could just check to see if Parallels is running first, and, if it's not, then launch it.

 

It looks like many of the commands are just regular bash commands executed through PHP, so you could add in something like:

if (! exec("ps aux|grep 'parallels'|grep -v grep")) {
  exec('open Parallels');
  sleep(5);
}

I haven't checked that code, so it might not be quite right. Basically, what it does is that it grabs all the running processes and checks if parallels is in there (you might need to capitalize that); then, if there is no matching processes, then it opens parallels and waits for 5 seconds before continuing.

 

So, you need to make sure that (1) there isn't something like a parallels "helper" or anything else that will be a false positive on the ps/grep command; (2) Make sure that Parallels actually opens when you type "open Parallels" into the terminal; and (3) that the sleep is neither too long nor short. Basically, the sleep command is there just to make sure that Parallels has enough time to open before the rest of the workflow tries to do anything to it.

Link to comment

OK to prevent the script from launching Parallels every time it executes, can I place the snippet only when you select what outcome you want? I.e. this workflow queries the status of all your VMs and then lists what you can do with them - resume, reboot etc. What would be ideal is the new snippet only be run if I select an outcome, otherwise it is ignored. 

 

Any suggestions?

Thanks again

Link to comment

It depends on whether or not prlctl can work without Parallels being open. Test to make sure that it can (close parallels, open a terminal, type 'prlctr list' or something like that). If it doesn't work without it, then there is no easy remedy. If it does, then alter the workflow file like this:

 

Open the workflow folder and create a file called "action.sh"

 

Drop this into it:

a=`ps aux|grep "Parallels Desktop"
if [[ -z $a ]]; then
  open "/Applications/Parallels Desktop.app"
  sleep 5
fi
prlctl $1

Now, open the workflow in Alfred and double-click on the script action (the second box). Currently, it reads "prlctl {query}"; change that to read "bash action.sh {query}"

 

That should do it.

 

You might have to tweak the above if that isn't the path to your Parallels.

Link to comment

OK confirmed that prlctl does indeed work when Parallels is not working. It just lists nothing which I assume is correct. However, I have used your script above and now nothing happens at all :) Suspending Parallels and trying to resume a VM all fail to do anything. So I assume the action.sh isn't working. Here is what I have used:

 

a=`ps aux|grep "Parallels Desktop"

if [[ -z $a ]]; then

  open "/Applications/Parallels Desktop.app"

  sleep 5

fi

prlctl $1

 

Does this look correct? Is the ` after the a= correct? Sorry I don't know these scripts very well. 

 

*EDIT* so added another ` after ps aux so have :

 

 

a=`ps aux`|grep "Parallels Desktop"

if [[ -z $a ]]; then

  open "/Applications/Parallels Desktop.app"

  sleep 5

fi

prlctl $1

 

And it now starts Parallels but doesn't do anything else. Assume this is because it cannot find prlctl?

Edited by gr4z
Link to comment

OK I have now changed the script action to run your action.sh script followed by the prlctl {query}. This works fine. 

 

I removed the prlcrl $1 from action.sh and reduced the sleep to 1 which seems to work well. Being very pedantic is there anyway I can start the app Parallels Desktop minimised?

 

Thank you so much for your help.

Edited by gr4z
Link to comment

Sleep 5 might have been overkill; you just want to make sure that Parallels has enough time to open before you start to ask it to do things.

 

Starting minimized? No way comes to mind off the top of my head, but you can start it behind other apps by changing

  open "/Applications/Parallels Desktop.app"

to

  open -g "/Applications/Parallels Desktop.app"

If that doesn't do it, then just look around on stackoverflow or other places about how to launch them minimized. You could look into using osascript to launch it and then minimize it, but then it'll have an annoying flicker as it steals focus for a minute and then disappears. You might be able to find a clever workaround though.

 

The $1 probably needed to be quoted or something, but moving it as a second line in the script action does the same thing.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...