php exec() responding differently from windows 8 metro app - php

I wanted to change the tile icons for desktop applications in the new windows 8 start menu.
So they would fit in with the other metro apps.
I made a simple metro app that calls a simple localhost php file
<?php
// check if the chrome is in the task list
exec('tasklist /FI "IMAGENAME eq chrome.exe" 2>NUL | find /I /N "chrome.exe">NUL');
// get a return value I can check
$runing = exec('if "%ERRORLEVEL%"=="0" echo Programm is running');
if ($runing === 'Programm is running'){
// the program is open already
echo $runing;
} else {
// the program is not running and should be opened
exec('C:\Users\Gerdy\AppData\Local\Google\Chrome\Application\chrome.exe');
}
?>
If I launch this file from chrome it echos "Programm is running".
That's great!
If I launch it from windows start and Chrome is not running, Chrome does not start.
If I exclude the if statement and just run.
exec('C:\Users\Gerdy\AppData\Local\Google\Chrome\Application\chrome.exe');
From the start menu.
It will open a new Chrome window regardless of if chrome is already open.
So I guess my question is :
What can I do that will allow my php file to check if chrome is open and if it is not , to open it?
This model actually works for any other program just not browsers.
My best guess is that it has do less with my commands and more to do with chrome itself.
It could be a target that I need to add, I don't know.

You can use Windows Management Instrumentation:
If you have not used wmic before you should install it by running wmic from cmd.exe.
It should then say something like:
WMIC Installing... please wait.
After that wmic is ready for use:
function getProcessId( $imagename ) {
ob_start();
passthru('wmic process where (name="'.$imagename.'") get ProcessId');
$wmic_output = ob_get_contents();
ob_end_clean();
// Remove everything but numbers and commas between numbers from output:
$wmic_output = preg_replace(
array('/[^0-9\n]*/','/[^0-9]+\n|\n$/','/\n/'),
array('','',','),
$wmic_output );
if ($wmic_output != '') {
// WMIC returned valid PId, should be safe to convert to int:
$wmic_output = explode(',', $pids);
foreach ($wmic_output as $k => $v) { $wmic_output[$k] = (int)$v; }
return $wmic_output;
} else {
// WMIC did not return valid PId
return false;
}
}
// Find out process id's:
if ($pids = getProcessId( "chrome.exe" )) {
foreach ($pids as $pid) {
echo "Chrome.exe is running with pid $pid";
}
} else {
echo "Chrone.exe is not running";
}
I have not tested this and just wrote it out of my head so there might be some fixing and you should check wmic's output by running it from commandline with same args to see if preg_replace() is doing it right (get pid from wmic's output).
UPDATE:
Tested and it seems that wmic does not return any status codes so updated my php function to reflect this bahavior.
UPDATE:
Now it handles multiple processes too and returns all pids as indexed array or false when no process running.
About WMI:
Windows Management Instrumentation is very powerful interface and so is wmic commandline tool. Here is listed some of WMI features

Related

How do I check if a Python script is running in PHP?

I'm trying to check if a Python script is running in PHP, but I've no idea how.
I've tried using a database: I added an entry "request" with value response "0" and the Python script had to change that value to "1" if it was online. I couldn't get that to work so now I'm asking here
Assuming tasklist is available, this could potentially work: (this example using Windows 10)
I first launched a test2.py script:
The test2.py code is simply running:
from time import sleep
while True:
print('running');
sleep(3);
Then using this bit of php code: (I named procCheck.php)
<?php
$tasks = [];
// Use -v to include the window title info:
exec('tasklist -v 2>NUL', $tasks);
// Check the tasks array for the script we seek:
$entry = preg_grep('/(test2\.py)/', $tasks);
if (!empty($entry)) {
foreach($entry as $value) {
echo $value . PHP_EOL;
}
}
Gives this output: (one wrapped line in my console window)
Know that if there are other windows open with same script name within the window title will be found too. For example, I had the test2.py open as the active tab in Notepad++ and that entry was found as well:
Changing to some other file tab in Notepad++ only found the first entry.

How to calculate number of processor cores in PHP script (linux)?

I'm trying to use pthreads for multithreading. I'm creating pool with constructor. First parameter is number of Workers.
$pool = new Pool(8, 'WebWorker');
I want to detect count of processor cores automatically. Something like this:
$pool = new Pool(get_processor_cores_number(), 'WebWorker');
How is it possible with PHP?
If the server is a Linux machine you can do it with the following snippet:
$ncpu = 1;
if(is_file('/proc/cpuinfo')) {
$cpuinfo = file_get_contents('/proc/cpuinfo');
preg_match_all('/^processor/m', $cpuinfo, $matches);
$ncpu = count($matches[0]);
}
You can do something like that, of course your server should be in linux:
function get_processor_cores_number() {
$command = "cat /proc/cpuinfo | grep processor | wc -l";
return (int) shell_exec($command);
}
You will execute a shell command then cast it to int.
In case anyone looking for a easy function to get total CPU cores for Windows and Linux both OS.
function get_processor_cores_number() {
if (PHP_OS_FAMILY == 'Windows') {
$cores = shell_exec('echo %NUMBER_OF_PROCESSORS%');
} else {
$cores = shell_exec('nproc');
}
return (int) $cores;
}
Here is an extension exposing sysconf: krakjoe/sysconf
<?php
$cpusConfigured = sysconf(SYSCONF_NPROCESSORS_CONF);
$cpusOnline = sysconf(SYSCONF_NPROCESSORS_ONLN);
?>
Most applications only care about the number configured.
In my own library, I have a function for this among other things. You can easily modify it where it uses nonstandard PHP functions.
For instance, I cache the result so you can ignore that. Then I have functions to check if we are running on Linux, Mac or Windows. You could insert a similar check of your own there. For executing the actual system specific check I use my own Process class which allows things such as reconnecting to running processes on subsequent requests to check status, output etc. But you can change that and just use exec.
public static function getNumberOfLogicalCPUCores() {
$numCores = CacheManager::getInstance()->fetch('System_NumberOfLogicalCPUCores');
if(!$numCores) {
if(System::isLinux() || System::isMac()) {
$getNumCoresProcess = new Process("grep -c ^processor /proc/cpuinfo");
$getNumCoresProcess->executeAndWait();
$numCores = (int)$getNumCoresProcess->getStdOut();
}
else if(System::isWindows()) {
// Extract system information
$getNumCoresProcess = new Process("wmic computersystem get NumberOfLogicalProcessors");
$getNumCoresProcess->executeAndWait();
$output = $getNumCoresProcess->getStdOut();
// Lazy way to avoid doing a regular expression since there is only one integer in the output on line 2.
// Since line 1 is only text "NumberOfLogicalProcessors" that will equal 0.
// Thus, 0 + CORE_COUNT, which equals CORE_COUNT, will be retrieved.
$numCores = array_sum($getNumCoresProcess->getStdOutAsArray());
}
else {
// Assume one core if this is some unkown OS
$numCores = 1;
}
CacheManager::getInstance()->store('System_NumberOfLogicalCPUCores', $numCores);
}
return $numCores;
}
Avoid spinning up a whole new shell to get simple information out of the OS when you can. This is extremely slow and is a memory hog as you're spawning an entire command interpreter for a single simple task.
Here is a quick function to do it on Linux or Windows that doesn't require spawning a whole new shell:
function get_total_cpu_cores() {
return (int) ((PHP_OS_FAMILY == 'Windows')?(getenv("NUMBER_OF_PROCESSORS")+0):substr_count(file_get_contents("/proc/cpuinfo"),"processor"));
}
This will work on any semi-modern windows installation (since at LEAST Windows 95) and will work on most, if not all, flavors of Linux assuming you have the rights to read /proc/cpuinfo. But most installations make that world readable... so shouldn't have any problems.
Further note to bear in mind technically this is showing you the CPU cores available as the OS sees it. Both Windows and Linux see hyperthreaded CPU threads as cores even though they aren't physical cores. That said, this should still work for what you're trying to do unless you REALLY need to know the number of physical cores on a machine. Then you're in for a more involved process.
Hope this helps!

Can 32-Bit PHP run a .vbs script on a 64-Bit IIS Server?

There is a vbscript that we must run to consolidate information gathered in a custom web application into our management software. The .vbs is in the same folder as the web application which is built in CodeIgniter 2.
Here is the controller code:
public function saveToPM( $budgetType ){
// run it
$obj = new COM( 'WScript.Shell' );
if ( is_object ( $obj ) ) {
$obj->Run( 'cmd /C wscript.exe D:\pamtest\myload.vbs', 0, true );
var_dump($obj->Run);
} else {
echo 'can not create wshell object';
} // end if
$obj = null;
//$this->load->view('goodPush');
} // end saveToPM function
We have enabled DCon in the php.ini file and used dcomcnfg to enable permissions for the user.
I borrowed the code from http://www.sitepoint.com/forums/showthread.php?505709-run-a-vbs-from-php.
The screen echos "Code executed" but the vbscript does not run.
We have been fighting with this for a while so any help is GREATLY appreciated.
It's a bit messy. PHP calls WScript.Shell.Run which will call cmd (with /c - i.e terminate cmd.exe when it's done its thing) which will call cscript.exe to run and interpret a .vbs. As you can see quite a few things that have to go right! :)
What if you 'wait' for the WScript.Shell.Run call to end (your $wait variable) before continuing execution of the wsh script which will in turn allow PHP to continue execution etc?
Since you're not waiting for the call to finish, PHP thinks its all good and continues onto the next line (interpreted language).
Also, maybe have the .vbs create an empty text file? Just so you have an indication that it has actually run.
Just take a step back, have a beer and it'll come to you! Gogo troubleshoot!
And - http://ss64.com/vb/run.html
If bWaitOnReturn is set to TRUE, the Run method returns any error code returned by the application.
I've tested your code with a stand-alone PHP script (without Codeigniter) on a Windows XP machine, with the PHP 5.4.4 built-in web server, and I've noticed that the vbscript gets executed, but PHP dies (the event viewer shows a generic "Application Error" with ID 1000).
However I've also discovered that removing the "cmd /C" from the command string solves the problem.
Here is the simple script that I've used for my test:
<?php
$obj = new COM('WScript.Shell');
if (is_object($obj)) {
//$obj->Run('cmd /C wscript.exe test.vbs', 0, true); // This does'nt work
$obj->Run('wscript.exe test.vbs', 0, true); // This works
var_dump($obj->Run);
} else {
echo 'can not create wshell object';
}
$obj = null;
?>
And this is my simple "test.vbs" script:
WScript.Echo "vbscript is running"
Another solution that seems to be working (at least on my platform) is the "system" call:
system('wscript.exe test.vbs');
Unfortunately I don't have a 64-bit IIS system to test with, so I can't really say if there are specific problems on this platform, but I hope this helps.

Background script on shared host with multiple PHP versions installed

I was needing a way to generate thumbnails (using PHP5) for an image management script and had a problem where my host has multiple versions of PHP installed (4 and 5), with PHP4 set as default. This meant that any calls to php from the CLI would run PHP4. I've come up with the following as what I hope to be a cross platform solution. I'm posting it here primarily as I had a lot of trouble finding any help using Google, so this might help someone in the future, I also have the following questions.
Do you see anything obviously wrong with it?
Are there any other paths to the php5 binary that you know of or know of a better order to have the array for optimisation?
If a host has exec or shell_exec disabled, will the EGalleryProcessQueue.php script be able to be run as a standalone cron job? I don't have access to cron to be able to test this yet. I'm not too worried about this question, as I'll get around to testing it eventually anyway.
Does anyone have any suggestions as to a way in which I can get some feedback as to how far through the images the processing is? See the TODO section of EGalleryProcessQueue.php I'd like to display a progress bar when it's in the admin section.
Main script
/**
* Writes the array to a text file in /path/to/gallery/needsThumbs.txt for batch processing.
* Runs the thumbnail generator script in the background.
*
* #param array $_needsThumbs the array of images needing thumbnails
*/
private function generateThumbnails($_needsThumbs)
{
file_put_contents($this->_realpath.DIRECTORY_SEPARATOR.'needsThumbs.txt',serialize($_needsThumbs));
$Command = realpath(dirname(__FILE__)).DIRECTORY_SEPARATOR.'EGalleryProcessQueue.php '.$this->_realpath.' '.$this->thumbnailWidth.' '.$this->thumbnailHeight;
if(PHP_SHLIB_SUFFIX == 'so')// *nix (aka NOT windows)
{
/*
* We need to make sure we are using the right PHP version
* (problems with shared hosts that have PHP4 and PHP5 installed,
* but PHP4 set as default).
*/
$phpPaths = array('php', '/usr/local/bin/php', '/usr/local/php5/bin/php', '/usr/bin/php', '/usr/bin/php5');
foreach($phpPaths as $path)
{
exec("echo '<?php echo version_compare(PHP_VERSION, \"5.0.0\", \">=\"); ?>' | $path", $result);
if($result)
{
shell_exec("nohup $path $Command 2> /dev/null > /dev/null &");
break;
}
}
}
else // Windows
{
$WshShell = new COM("WScript.Shell");
$WshShell->Run("php.exe $Command", 0, false);
}
}
EGalleryProcessQueue.php
#!/usr/bin/php
<?php
if ($argc === 4 && strstr($argv[0], basename(__FILE__))) {
// File is being called by the CLI and has not been included by another script
if(!file_exists($argv[1].DIRECTORY_SEPARATOR.'needsThumbs.txt'))
{
// Either no thumbnails need to be created or a wrong directory has been supplied
exit;
}
include(realpath(dirname(__FILE__)).DIRECTORY_SEPARATOR.'EGalleryThumbGenerator.php');
$generator = new EGalleryThumbGenerator;
$generator->directory = $argv[1];
$generator->thumbnailWidth = is_int($argv[2]) ? $argv[2] : 128;
$generator->thumbnailHeight = is_int($argv[3]) ? $argv[3] : 128;
// $generator->processImages() returns the number of images left to process (it does them in blocks of 10)
while (($i = $generator->processImages()) > 0)
{
/*
* TODO Can we get some sort of feedback to the user here?
* Possibly so that we can display a progress bar in the management section.
* Probably have to write $i to a file to be read by the main script.
*/
}
exit;
}
?>
Do you see anything obviously wrong with it?
Nope, the code looks good.
Are there any other paths to the php5 binary that you know of or know of a better order to have the array for optimization?
This is a hard question to answer, as PHP could be installed anywhere on a server. The paths you have seem to be very logical to me, but there could be any number of other places it could be installed.
Rather than providing a bunch of directories where PHP5 might be installed, what about having a parameter the user has to set to provide the path to the PHP5 executable if it's not in their $PATH?
If a host has exec or shell_exec disabled, will the EGalleryProcessQueue.php script be able to be run via a cron job?
I haven't tested it, but I would assume that would prevent the script from running.
Does anyone have any suggestions as to a way in which I can get some feedback as to how far through the images the processing is? See the TODO section of EGalleryProcessQueue.php I'd like to display a progress bar when it's in the admin section.
Store the number of images completed somewhere (file, db, maybe even session var) and have an AJAX call fire every second or so to a function that provides done vs total. Then use something like http://docs.jquery.com/UI/Progressbar

AJAX - Progress bar for a shell command that is executed

I am making use of AJAX on my site and I would like to show users progress of a file that is being downloaded by my server.
The download is done by script that outputs a percentage to the shell. I would like to pass this info back to the user using AJAX. How can I do this?
Thank you for any help and direction.
I hope your solutions do not involve writing to a text file and retrieving that percentage from the text file!! Too much over head I think.
EDIT - More Info
It is a Linux Shell command - Fedora Core 10.
Currently this is how the shell output looks like:
[download] 9.9% of 10.09M at 10.62M/s ETA 00:00
The percentage changes and I wish to capture that and send it back to the user as it changes.
To execute this, I make use of PHPs exec() function.
Instead of exec, you could use popen. This will give you a handle you use with fread to grab the output your command generates as it happens.
You'll need to parse out the updates it makes to the percentage indicator. Once you have that data, there are a few ways you could get it to a client, e.g. with a "comet" style push, or have an Ajax request poll for updates.
I haven't tried this, but I think this approach would work.
You need three pieces:
Have shell script output its stream to netcat connected to a port
Have a php script listening to stream coming from said port for incoming data, updating a record in memcache or some database w/ the percentage finished.
Have your web script periodically make ajax calls, to the server which checks this value in your backend store.
I'm working on a similar problem. I have to parse the output of my video conversion shell script. I use popen and parse the output of the returned resource. At first I used fgets but that didn't recognize the updated values as new lines. So I created a simple function to that takes an optional $arg_delimiter so you can check for other return types like the chr(13) cariage return. The example code is a bit modified and therefor untested because in my case these functions were methods on my parser object.
function get_line ($arg_handle, $arg_delimiter = NULL)
{
$delimiter = (NULL !== $arg_delimiter) ? $arg_delimiter : chr(10);
$result = array();
while ( ! feof($arg_handle))
{
$currentCharacter = fgetc($arg_handle);
if ($delimiter === $currentCharacter)
{
return implode('', $result);
}
$result[] = $currentCharacter;
}
return implode('', $result);
}
I simply loop over the results from the popen() resource like this:
$command = '/usr/bin/yourcommand';
$handle = popen($command . ' 2>&1', 'r');
while ( ! feof($handle))
{
$line = get_line($handle, chr(13));
preg_match($yourParserRegex, $line, $data);
if (count($data) > 0)
{
printf("<script type='text/javascript'>\n //<![CDATA[\n window.alert('Result: %s');\n // ]]>\n</script>"
,$data[1]
);
flush();
}
}
Now all you need to do is figure out the comet stuff.

Categories