ScriptingBridge Finder POSIX path - objective-c

is it possible to get the POSIX path or target to the frontmost window using the Scripting Bridge framework?
I'm using
FinderApplication *theFinder = [SBApplication aplicationWithBundleIdentifier:#"com.apple.Finder";
but I can't find anything in "Finder.h" that could work.

This might be what you are after using ScriptingBridge and NSURL
FinderApplication *finder = [SBApplication applicationWithBundleIdentifier:#"com.apple.finder"];
SBElementArray *windows = [finder windows ]; // array of finder windows
NSArray *targetArray = [windows arrayByApplyingSelector:#selector(target)];// array of targets of the windows
//gets the first object from the targetArray,gets its URL, and converts it to a posix path
NSString * newURLString = [[NSURL URLWithString: (id) [[targetArray objectAtIndex:0]URL]] path];
NSLog(#"newURLString %# ", newURLString);

Running drawnonward's code through appscript's ASTranslate tool gives me this:
#import "FNGlue/FNGlue.h"
FNApplication *finder = [FNApplication applicationWithName: #"Finder"];
FNReference *ref = [[[finder windows] at: 1] target];
FNGetCommand *cmd = [[ref get] requestedType: [ASConstant alias]];
id result = [cmd send];
The result will be an ASAlias instance; use -[ASAlias path] to get the POSIX path.
You can't do it in SB short of resorting to raw Apple event codes as that's one of the features the Apple engineers forgot/didn't bother to put into SB's less than stellar API.

I have not used ScriptingBridge. As part of an NSAppleScript it would be:
get POSIX path of (target of window 1 as alias)
Hopefully that helps. I think the POSIX part is from the StandardAdditions ScriptingAddition, not the Finder itself.

Related

iTunes Mp3 Add Returning Nil Via Scripting Bridge In ObjC and Swift And Doesn't Import

I'm trying to import a downloaded MP3 into iTunes. My app is for OSX using Swift, and I've tried doing this both in Swift code and in ObjC using interoperability. I've generated the iTunes.h using sdef and sdp. I'm importing it in my Bridging Header for the Swift attempt and in my .m file for the ObjC attempt. I've added Scripting Bridge to my build.
This is my first program in Swift or ObjC (my experience is in C#) so this may be something simple I don't have the experience to realize.
Here is my ObjC code:
NSString *filepath = "~/Music/test.mp3";
iTunesApplication *iTunes = [SBApplication applicationWithBundleIdentifier:#"com.apple.iTunes"];
iTunesPlaylist *pl;
for (iTunesSource *source in sources) {
if([source kind] == iTunesESrcLibrary) {
SBElementArray *libraries = [source libraryPlaylists];
pl = [libraries objectAtIndex:1];
break;
}
}
iTunesTrack *track = [iTunes add:[NSArray arrayWithObject:[NSURL fileURLWithPath:filepath]] to: pl];
Everything compiles and runs, but the iTunes add returns nil (and more importantly, doesn't add to iTunes). I've tried using different Playlists from the Library, and difference Sources as well. I've tried using a different MP3 file. And as I said, I've written it in Swift as well. All give me the same result.
So apparently I was fetching the path for MyMusic incorrectly. You can't just use the tilde, you have to resolve it:
NSString *musicDirectory = [NSSearchPathForDirectoriesInDomains(NSMusicDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filepath = [musicDirectory stringByAppendingPathComponent:#"test.mp3"];
Or with Swift:
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.MusicDirectory, inDomains: .UserDomainMask)
let musicDirectory: NSURL = urls.first as? NSURL
let filepath = musicDirectory.URLByAppendingPathComponent("test.mp3")
At this point, I no longer needed to mess with any of the source searching either, I could just pass nil as the playlist:
iTunesTrack *track = [iTunes add:[NSArray arrayWithObject:[NSURL fileURLWithPath:filepath], nil] to: nil];
I still need an Objective C wrapper around the actual add method, however, which is connected to the Swift programming via the Bridging Header. If I try to use the add method in Swift directly, I get linker errors which seem unrelated to the original issue, so I won't address.

'Show Package Contents' through objective C code

We can right click an .app file and see its package contents. To open a file programmatically, we can use NSWorkspace but how to open the app's package contents?
I have searched a lot but seems there is no solution. Please help if I am missing something.
Per the comment it seems the OP want to open the contents directory of an app in the finder from code. The following line will accomplish that:
Swift:
let appName = "Safari";
let command:NSString = String(format:"open '/Applications/%#.app/Contents'", appName);
system(command.cStringUsingEncoding(NSUTF8StringEncoding))
Objective-C:
NSString *appName = #"Safari";
NSString *command = [NSString stringWithFormat:#"open '/Applications/%#.app/Contents'", appName];
system([command cStringUsingEncoding:NSUTF8StringEncoding]);
Alternate:
NSString *appPath = #"/Applications/Safari";
NSString *command = [NSString stringWithFormat:#"open '/%#.app/Contents'", appPath];
system([command cStringUsingEncoding:NSUTF8StringEncoding]);
This seems to work:
NSString* contentsPath = [appPath stringByAppendingPathComponent:#"Contents"];
[[NSWorkspace sharedWorkspace] selectFile: contentsPath
inFileViewerRootedAtPath: appPath];
An application is just a directory, show package contents just allows you to access the application as a directory rather than executing it. So you can access a file within an application such as
/Applications/Safari.app/Contents/Info.plist

how to get version of default browser on my mac os x

I want to get system information in mac using objective C.
I am searching a lot but did not got single line of code for
my use.They provided solutions via javascript but i want them in
objective C.
Provide me some help to go ahead.
You can use launch services to get the path to the default browser as below
LSGetApplicationForURL((CFURLRef)[NSURL URLWithString: #"http:"],
kLSRolesAll, NULL, (CFURLRef *)&appURL);
NSString *infoPlistPath = [[appURL path] stringByAppendingPathComponent:#"Contents/info.plist"];
Now read the CFBundleShortVersionString from the info.plist.
Here you go :
NSString *userName=NSUserName();
NSLog(#"UserName: %#",userName);
NSArray *ipAddress=[[NSHost currentHost] addresses];
NSLog(#"IP Address=%#",ipAddress[0]);
Updating my answer
This is tested and works well
NSWorkspace *nsSharedWorkspace = [NSWorkspace sharedWorkspace];
NSString *nsAppPath = [nsSharedWorkspace fullPathForApplication:appName];
NSBundle *nsAppBundle = [NSBundle bundleWithPath: nsAppPath];
NSDictionary *nsAppInfo = [nsAppBundle infoDictionary];
//Now you can print all dictionary to view all its contents and pick which you want
NSLog(#"%#",nsAppInfo);
//or you can get directly using following methods
NSLog(#"%#",[nsAppInfo objectForKey:#"CFBundleShortVersionString"]);
NSLog(#"%#",[nsAppInfo objectForKey:#"CFBundleVersion"]);
Dont forget to add AppKit framework

LSCopyApplicationURLsForURL always returns null

When I try to log all available editors on my system for my temporary file (which is "toString" in this code) it always returns null, although I have many applications installed on my system.
NSArray *appUrls = (NSArray*)LSCopyApplicationURLsForURL((CFURLRef)[NSURL URLWithString:toString], kLSRolesViewer | kLSRolesEditor);
toString is containing the following file path:
/var/folders/pl/tcc5k3fd6tj2__9dprg9dm1m0000gp/T/tempFile
What should be the problem here?
[NSURL URLWithString:toString]
expects a complete URL string including scheme, such as "file://var/folders/...".
Use
[NSURL fileURLWithPath:toString]
instead to get a file URL with the specified path.
Another problem could be that your file name does not have any file extension (e.g. ".txt"), because Launch Services uses the extension (or file type/creator) to find a suitable application.
I was struggling with the this and I wanted to get all Bundles that could open a determined path/file extension.
If you have a file extension, you can get all bundles that can edit it by the following:
//All Bundle Ids
NSString *pathExtension = #"docx";
CFArrayRef utisRef = UTTypeCreateAllIdentifiersForTag(kUTTagClassFilenameExtension,(__bridge CFStringRef) pathExtension,nil);
NSLog( #"UTI: utisRef %#", utisRef);
NSArray *utis = CFBridgingRelease(utisRef);
NSMutableSet *mutableSet = [[NSMutableSet alloc] init];
for (NSString *uti in utis) {
CFArrayRef bundleIDsRef = LSCopyAllRoleHandlersForContentType((__bridge CFStringRef) uti,kLSRolesEditor);
[mutableSet addObjectsFromArray:CFBridgingRelease(bundleIDsRef)];
}
NSLog( #"bundleIDs: %#", mutableSet);
If you have a path of file and you want to get all apps location that can edit it, you can use the following:
//Location of apps
NSString *str = #"/Users/ricardoanjos/Library/Developer/Xcode/DerivedData/EgnyteDrive-hforbniifiojczefbnwanzxakvlr/Build/Products/Debug/1.pdf";
NSURL* url = [[NSURL alloc] initFileURLWithPath:str];
CFURLRef urlRef = (__bridge CFURLRef)url;
CFArrayRef appUrlsRef = LSCopyApplicationURLsForURL(urlRef, kLSRolesEditor);
NSArray *appUrls = CFBridgingRelease(appUrlsRef);
NSLog(#"appUrls: %#", appUrls);
I hope it will help.

How to use NSWorkspace launchApplicationAtURL?

I tried to run equivalent of "TextMate foo.txt" using launchApplicationAtURL. The name of binary is "TextMate", and I have one parameter.
I tried the following code, but it doesn't seem to work.
// find the textmate
NSURL * bURL = [[NSWorkspace sharedWorkspace] URLForApplicationWithBundleIdentifier:#"com.macromates.textmate"];
NSWorkspace * ws = [NSWorkspace sharedWorkspace];
// find the parameter
NSString * f = #"foo.txt";
NSArray * myArray2 = [NSArray arrayWithObjects:f,nil];
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
[dict setObject:myArray2 forKey:NSWorkspaceLaunchConfigurationArguments];
[ws launchApplicationAtURL:bURL options:NSWorkspaceLaunchDefault configuration:dict error:nil];
What's wrong with this?
Added
I checked this code actually works, I got something wrong with how 'TextMate.app' deals with the parameters.
Most apps don't use command line parameters. If you want to open a particular file with a particular app, use -[NSWorkspace openFile:withApplication:].