Mail: Application isn't running - objective-c

I'm trying to execute simple AppleScript in Objective-C. The code is:
NSString *emailString = #"tell application \"Mail\" to activate";
NSAppleScript *emailScript = [[NSAppleScript alloc] initWithSource: emailString];
NSDictionary *errorDict = NULL;
[emailScript executeAndReturnError: &errorDict];
And got this annoying error:
NSAppleScriptErrorMessage: Mail got an error: Application isn’t
running. NSAppleScriptErrorRange: NSRange: {27, 8}
NSAppleScriptErrorBriefMessage: Application isn’t running.
NSAppleScriptErrorNumber: -600 NSAppleScriptErrorAppName: Mail
It's no problem if I execute the script from Script Editor. I need some help — Thanks!

Solved. My app using Sandbox. And if you want run AppleScript from it, you need edit entitlements file. In me case this help.

Related

Xcode: Getting the path for AppleScript file in Obj-C/Cocoa project with pathpathForResource

I have a plugin development project in X-code (10.2.1), and am trying to incorporate some AppleScript code (FatApple.applescript) into one of the methods in my implementation file.
On the AppleScript side: I have tried writing the code in Script Editor, saving to Desktop, dragging and dropping the FatApple.scptd in the "Resources", "Other Sources", etc. folders. I have tried the same steps after starting a new Xcode Project for AppleScript and dragging and dropping the FatApple.applescript file (tried with pathWithFormat type as both "scpt" and "applescript".
In Xcode I have added the FatApple.applescript to the Copy Bundle Resources, and removed from Compile Resources.
-(float) calcThing
{
NSAlert *alert=[[[NSAlert alloc] init] autorelease];
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForResource:#"FatApple" ofType:#"scpt"];
NSString *countstr=[NSString stringWithFormat:#"path=%#",path];
[alert setMessageText: countstr];
[alert runModal];
NSAppleScript *script = [[NSAppleScript alloc] initWithContentsOfURL:[NSURL fileURLWithPath: path] error:nil];
[script executeAndReturnError:nil];
}
I would expect to compile and run my plugin, call it in the program and receive a message with the path to my AppleScript, then ideally I could call the script and start doing stuff. Instead I receive "path=(null)".
I copied your code verbatim into a project and it worked for me, using a dummy AppleScript. The only difference I can see is that I dropped the AppleScript in the main file list rather than in the resources folder, but that shouldn't make any difference. The script shows up in the app resources folder like yours does.
The only questionable thing I see in your code is that you used NSBundle's - pathForResource:ofType: instead of - URLForResource:withExtension:. NSAppleScript wants an NSURL, so asking the bundle for a path and then converting it to a URL seems like an unnecessary step, and unnecessary steps are inherently suspicious. I can't see why that would make a difference (unless the plugin context does something funky to resource file paths), but, you know...

OSAKit.framework usage for executing scripts

I am on XCode 9.2, Objective-C, MacOS
i am looking for any example on using osakit.framework to execute a script file(applescript = .scpt or .applescript) or a method in that file with parameters and how to get the response.
My own implementation of applescript works but leaks too much memory so i want to try osakit.framework but its documentation is bad.
The simple implementation is like this
OSAScript *scriptNAME= [[OSAScript alloc] initWithSource:#"tell application \"Firefox\" to return name of window 1"];
NSDictionary * errorDict = nil;
NSAppleEventDescriptor * returnDescriptor = [scriptNAME executeAndReturnError: &errorDict];
NSLog(#"%#", returnDescriptor);
But instead of the script as source in text form i want to load my script file.
Edit:
I tried it with
OSAScript *scriptNAME= [[OSAScript alloc] initWithContentsOfURL:myScriptURL error:&error];
The script gets loaded but i can't call any method.
I Have two simple methods
on test()
display dialog "Hello World"
end
on testWithArguments:arg
display dialog (arg's item 1)
end
The call for the second method i tried:
[scriptNAME executeHandlerWithName:#"testWithArguments" arguments:#[#"Hello World"] error:&errorDict];
-- doesnt work
[scriptNAME executeHandlerWithName:#"testWithArguments:" arguments:#[#"Hello World"] error:&errorDict];
-- doesnt work
Bug found.
It was a wrong configured applescript file. Was declared as a script object from a former test. As simple applescript file it works great.

ScriptingBridge without sdef? (cocoa)

I'd like to get properties of the currently active app. I understand that this should be possible with ScriptingBridge, however, this seems to require you generate an sdef file and import this in your project for the app you are trying to target. Since I want to target all apps, is there another way to do this?
Example of accessing system preferences:
SystemPreferencesApplication *systemPreferences =
[SBApplication
applicationWithBundleIdentifier:#"com.apple.systempreferences"];
If there's another way to access properties of any active app, please do share. (For example; window title)
Thanks.
I assume you want to run an applescript. The scripting bridge is good if you have a lot of applescript code to run. However if you only have a small amount then a simpler way is with NSApplescript.
For example if you wanted to run this applescript...
tell application "System Events"
set theProcesses to processes
repeat with aProcess in theProcesses
tell aProcess to get properties
end repeat
end tell
Then you can write it this way...
NSString* cmd = #"tell application \"System Events\"\nset theProcesses to processes\nrepeat with aProcess in theProcesses\ntell aProcess to get properties\nend repeat\nend tell";
NSAppleScript* theScript = [[NSAppleScript alloc] initWithSource:cmd];
NSDictionary* errorDict = nil;
NSAppleEventDescriptor* result = [theScript executeAndReturnError:&errorDict];
[theScript release];
if (errorDict) {
NSLog(#"Error:%# %#", [errorDict valueForKey:#"NSAppleScriptErrorNumber"], [errorDict valueForKey:#"NSAppleScriptErrorMessage"]);
return;
}
// do something with result
NSLog(#"result: %#", result);
You can get a list of every currently running Application with
NSWorkSpace.sharedWorkspace.runningApplications;
Each object in that array should be an NSRunningApplication, which you can query and manipulate freely.

How to check whether app is running using [[NSAppleScript alloc] initWithSource:

This is my original script. It will return the current url of Safari
NSAppleScript *scriptURL= [[NSAppleScript alloc] initWithSource:#"tell application \"Safari\" to return URL of front document as string"];
What if I want to check whether the Safari browser is open or not before asking the script to return the URL?
Here is how I do in applescript editor.. So this script will check whether the Safari is running or not.. This works in applescript editor
tell application "Safari"
if it is running then
//return url code here
end if
end tell
What I need now is to straight away called the script from my cocoa app by using ' [[NSAppleScript alloc] initWithSource:'
I've tried this but its not working
NSAppleScript *scriptURL= [[NSAppleScript alloc] initWithSource:#"tell application \"Safari\" if it is running to return URL of front document as string"];
Why would that work? It's bad AppleScript grammar.
There are ways to do this without resorting to AppleScript, but it'll do for now. You can have multiple lines in an embedded script by using the C escape sequence \n to insert a newline:
NSString *source = #"tell application \"Safari\"\nif it is running then\nreturn URL of front document as string\nend if\nend tell";
You can also break up a string constant by placing one right after another, which makes it easier to read:
NSString *source =
#"tell application \"Safari\"\n"
"if it is running then\n"
"return URL of front document as string\n"
"end if\n"
"end tell";
The C compiler will glue these string constants together into a single NSString object.
The OP's AppleScript one liner code is wrong. The AppleScript text in this should work:
NSAppleScript *scriptURL= [[NSAppleScript alloc] initWithSource:#"tell application \"Safari\" to if it is running then return URL of front document as string"];
As dougscripts (+1) has pointed out but I wanted to make it little bit clearer of why the one liner Applescript syntax within the NSAppleScript the OP tried did not work.
And to be honest I did suggest an edit which lost out three to two
The OP's NSAppleScript code:
NSAppleScript *scriptURL= [[NSAppleScript alloc] initWithSource:#"tell application \"Safari\" if it is running to return URL of front document as string"];
Did not work because the syntax is wrong. 
The correct syntax should be:
NSAppleScript *scriptURL= [[NSAppleScript alloc] initWithSource:#"tell application \"Safari\" to if it is running then return URL of front document as string"];
There are two changes within part of the code shown in bold below.
\"Safari\" to if it is running then return URL

Is there a way to programmatically connect to a remote server from Cocoa?

Is there an Coca/obj-C API call to mimic the "Connect to Server" action in Finder? It's possible with Automater, so it seems like Finder has a hook somewhere.
Turns out there's an old Carbon function (can't find a Cocoa equivalent) called FSMountServerVolumeSync which does what I was looking for. You can supply and smb:// URL and login credentials.
File Manager Reference
OSStatus FSMountServerVolumeSync (
CFURLRef url,
CFURLRef mountDir,
CFStringRef user,
CFStringRef password,
FSVolumeRefNum *mountedVolumeRefNum,
OptionBits flags
);
An easy way is to just run some applescript code. I'll show you 2 choices. This first one is the standard way to show that Finder window from applescript.
NSString* cmd = #"choose URL";
The resulting window is bare-bones though, so you can actually open the Finder's window with this command...
NSString* cmd = #"tell application \"Finder\" to activate\ndelay 0.2\ntell application \"System Events\" to keystroke \"k\" using command down";
After choosing either of the "cmd" strings, you can execute that applescript code with this...
NSAppleScript* theScript = [[NSAppleScript alloc] initWithSource:cmd];
[theScript executeAndReturnError:nil];
[theScript release];
This might not be the best way, but can't you just use mount?