I am getting the list of running applications in Cocoa with the following code:
for (NSRunningApplication *app in [[NSWorkspace sharedWorkspace] runningApplications]) {
MNSLog(#"%#",[app localizedName]);
}
However an application I started from a terminal session is not appearing in the list ('Terminal' is well appearing). The application was started from the same user which is executing the cocoa code.Is my launched application under Terminal ? And in such a case how can I find its name and arguments ?Running ps in another terminal session show my process properly.
Use an NSTask to execute the ps Shell command. You can check the ps man page to determine which arguments you want to pass it based on the information you want to get back. Use NSPipe and NSFileHandle to get the results from the task.
If you want to do some filtering you can pipe the ps output through grep before your app picks up the result.
For your first question, I think NSWorkspace can only see apps that use the window server so you will only see Terminal, not the executables that it is running internally.
You can use sysctl or ps command to get a list of all BSD processes. Have look at unable to detect application running with another user
Related
I'm trying to pass some arguments to an UI-based program (cocoa app) through terminal commands while the app is already in launch.
For example:
open appName.app -openUI // Shows App UI
open appName.app -forceQuit 5 // Force quit App after 5 seconds
open appName.app -sendMsg "Hello World." // Add "Hello World" to UNUserNotificationCenter
I will be very grateful if someone can guide me how to implement this, thank you.
If you specify the arguments in that way, they will be send to the open command - which does not recognize them.
You need to put a --args in front of them in order to tell open to pass all the follwing arguments to the app launched, e.g.
open appName.app --args -openUI
Update
If the app is already running, open will use the running app. If you want to create a new window, you need to provide the -n parameter:
open appName.app -n --args -openUI
I'm writing a script for Illustrator CS6 in ExtendScript. At the end of my script, I want to spawn a task (a second script, in Ruby) using File.execute(). However, it's not working. And I'm at a loss as how to debug the problem -- how can I figure out why this isn't working?
Here's the end of my ExtendScript file:
// Do a bunch of other work, then:
var rubyFile = new File(scriptFolder + 'BuildHtmlWalkthrough.rb');
alert(rubyFile.exists);
var result = rubyFile.execute();
alert(result);
Both rubyFile.exists and result are always true, indicating that the script launched OK. But the script does not appear to run, at all. I've tried the following diagnostics:
The Ruby script does successfully run from the command line. The script's permissions are -rwxr-xr-x
I added a call to system("touch /blah/blah/blah") as the very first line of the Ruby script. The file does not get touched.
I thought maybe the ExtendScript process was terminating before the Ruby script could run, so I added a long for loop after rubyFile.execute(). Spinning for > 30 seconds did not help.
What can I do to debug, or solve, this problem?
I'm on MacOS X v10.9.1. And for reference, this is the documentation for File.execute():
File.execute (): Boolean
Core JavaScript Classes
Executes or opens
this file using the appropriate application, as if it had been
double-clicked in a file browser. You can use this method to run
scripts, launch applications, and so on. Returns true immediately if
the application launch was successful.
It's probably doing the "opens this file using the appropriate application" instead of executing, and returns true because the file successfully opens (or is already open in its associated app). If I have a python script and do
f= new File("~/Documents/misc_scripts/getpixelrgb.py");
f.execute();
, it opens it in my script editor, even if the file's execute flags are set.
I'm on OSX, btw
In After Effects, there is system.callSystem() to execute command line commands, but I'm afraid that is absent in Illustrator (I'm assuming you're doing this for Illustrator because of the tag). Are you on OSX or Windows? There are ways around this, by making an executable .app (OSX) or .exe (Win) and calling that with execute(). If I were doing this, I'm on OSX and I'd make an AppleScript app that does 'do shell script' to make the ruby system call. On Windows, it's different. One solution you might like if you're on windows: ocra, which is ruby-specific (http://ocra.rubyforge.org/). It may be possible to run a .bat file on Windows that calls the ruby script, but I'm not sure.
[edit!]
Terribly sorry for the extraneous Windows info (for someone else, I guess). Just saw your note about being on OSX. So you might want to use the AppleScript solution.
[edit again]
So, if my ruby script ("test.rb") is:
#!/usr/bin/env ruby
print "Hello"
and my AppleScript is:
do shell script "cd /testing_folder/; ruby test.rb"
Then I get "Hello" returned in AppleScript, but ExtendScript will just return true.
My app uses NSTask to execute shell scripts, one of those scripts launches an X11 app (specifically meld).
I would have expected this to work:
#!/bin/bash
source ~/.profile # setup $PATH/etc
meld .
But it fails with:
gtk.icon_theme_get_default().append_search_path(meld.paths.icon_dir())
Traceback (most recent call last):
File "/usr/local/bin/meld", line 132, in <module>
gtk.icon_theme_get_default().append_search_path(meld.paths.icon_dir())
AttributeError: 'NoneType' object has no attribute 'append_search_path'
As a proof of concept I changed the script to this, which works perfectly:
#!/usr/bin/ruby
exec 'osascript -e \'tell app "Terminal" to do script "meld ' + Dir.pwd + '" in front window\''
Does anyone what is causing the problem? Here is my code for executing the shell script:
NSTask *task = [[NSTask alloc] init];
task.launchPath = self.scriptURL.path;
task.standardOutput = [NSPipe pipe];
task.currentDirectoryPath = workingDirectoryURL.path;
[task launch];
X11 apps learn the display server's address using the DISPLAY environment variable.
On OS X, the DISPLAY value is randomized for security reasons, so you can't hard-code it, as you noticed. Instead, there is a launchd agent that tells launchd to set DISPLAY when it starts a process.
Somewhere between launchd and meld, the value of DISPLAY is being dropped or overwritten. Your job is to find out where.
Make sure the launchd agent is running. Run launchctl list and look for org.macosforge.xquartz.startx. Since meld is working from Terminal.app this part is probably correct.
Make sure DISPLAY is set in your app. It should be listed in [NSProcessInfo processInfo].environment.
Make sure DISPLAY is set in the NSTask you launch. Try running /usr/bin/env with an NSTask, and make sure DISPLAY appears in its output.
Make sure DISPLAY is set inside the script you run. Try echo $DISPLAY before and after sourcing ~/.profile. (Sometimes the .profile itself overwrites DISPLAY to an incorrect value because that's sometimes the right thing to do on other operating systems.)
EDIT: this is the code I used to copy DISPLAY from my GUI app to the shell script:
NSTask *task = ...
task.environment = [NSProcessInfo processInfo].environment;
[task.launch];
Change your script to spew the environment variables and compare "working" to "not-working".
There are subtle differences between how shells are initialized across the different execution models. Almost assuredly, the environment is the source of your issues.
Take a look at man launchctl
launchctl submit ... -p /usr/local/bin/meld -- .
to have launchd launch the job; that will set certain environment variables for you that are part of the per-user session.
Currently I am working on developing a GUI to some command line tools for Jailbroken iOS devices. I am using NSTask and verified that I was able to capture both stdout and stderr error and print the output to a UITextField. How ever most of the commands that I wish to run are not outputting anything. I suspect that setting up a pseudo tty session would fix this but am unable to find how to set this up in obj-c. My question is
1) Does this sound reasonable that the commands (namely arp-scan and nmap) need a TTY session?
2) How would I go about setting up a fake TTY session in Obj-c?
On windows and such I used to use a trick to find out of a file is currently in use (written specifically).
I use to open the file for writing and if it failed most likey another process is busy accessing it.
Sadly these trick (using C OPEN with exclusive lock for writing) doesn't work on my Mac. While my curl in a terminal is still writing my -fileBusy() check fails.
fcnt call on the fd with F_GETLK doesn't reveal any locking as well.
Is there any chance for me to detect if a file is in use by another process?
Ps> listening for fsevents can't be done because my app launches after the is created by the other app / process.
Apple confirmed via email that the solution described in the link below is a valid one and not considered a private API.
More information:
http://lists.apple.com/archives/cocoa-dev/2010/May/msg01455.html
You could try running the following shell command using NSTask:
lsof -Fc path/to/thefile
That will give you the process ID and name of any process(es) that have thefile open.