Need to get a file's application and type...

Hi,

I’ve searched for a while now, but I can’t seem to find a way to get from a given file both the application set to open it by default and it’s type (MIME or UTI, or even old style OS 9 kind would do). In the docs there is a method suggested to retrieve such info and as I believe the function is unaccessible from ASOC I tried to do an ObjC method, but my lack of knowledge has been the problem so far. Anyone could lend a hand? Or if anyone has a better suggestion, i’m happy to listen!

- (NSString *) returnApplicationOfFileAtURL: (NSURL *)theFileUrl {
		NSString *theApplication;
		NSString *theType;
		NSURL *fullPath = [self storeURLFromPath:[[self theFileUrl] path]];
    if (fullPath != nil) {
[[NSWorkspace sharedWorkspace] getInfoForFile:fullPath
								  application:&theApplication
										 type:&theType];
		[theApplication retain];
		[theType retain];
		return [theApplication autorelease]; }
	else {
		return nil;
	}
}

and in my app I call it like this:

tell current application's CSObjectiveCHelpers to set appFile to returnApplicationOfFileAtURL_(URLtoAdd)

in which the URLtoAdd argument is an NSURL object.

Thanks,
Fred

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

If you look at the docs for -getInfoForFile:application:type:, you’ll see the last two arguments have two asterisks (NSString **). So you need to use this form:

tell current application's NSWorkspace's sharedWorkspace() to set {didFindIt, appPath, theExtension} to getInfoForFile_application_type_("path/to/doc", reference, reference)
if didFindIt as boolean then
	display dialog appPath as text
end if

As usual, I missed a simple thing. Thanks for the push in the right direction Shane!

But i’m a bit surprised by the results. I was expecting something like the “Adobe InDesign CS5 document” for the type, not the extension, simply because. Any way I can get the same result as we have in the finder? Or i guess I can use the lastPathComponent method on the path to get the app name, remove the .app and add " document" at the end, although it could sometimes make no sense, like “Preview document” instead of a “JPEG file”…

And is it possible to ask the system to return which app is the default for a certain extension? Say I want to know what app opens .jpg files without having a file path.

Thanks,
Fred

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

Hmmm… NSWorkspaceManager’s localizedDescriptionForType: method perhaps?

But before that I need the UTI for a file I guess, the method seems to require only UTIs, not file extensions…

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

Alright, found the solution! Whenever the UTI is missing, i’ll create a string with the app’s name and “document”. Will be good enough. Used these:

tell theWorkspace to set {UTItypeOfFile, theError} to typeOfFile_error_(((URLtoAdd's |path|()) as string), reference)
set fileKindLocalized to (theWorkspace's localizedDescriptionForType_(UTItypeOfFile))

if fileKindLocalized returns as missing value then I create my custom file kind description with the app path provided by the first method.

Thanks again Shane!

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

Alright, everything is fine with UTI file types, but after a lot of thinking I need to retrieve the file type for HFS code only files (or with extension). One exemple is Adobe InDesign files which have no UTI but a creator code ( ‘IDd6’ ). I can make my own file type because I know both the application set to open the file and the extension, but i’d rather get the same file type (preferably localized) as can be seen in the Finder.

With UTIs I can use the localizedDescriptionForType: method, I guess i’m looking for the same thing either for HFS creator code or extension.

I successfully created an Objective C method that retrieves the creator code from a path:

+ (NSString *) returnHFSfileTypeForPath: (NSString *)fullFilePath
{
	NSString *fileTypeString = NSHFSTypeOfFile(fullFilePath);
	
    if ([fileTypeString isEqualToString:@"''"])
    {
			// No HFS type; get the extension instead.
        fileTypeString = [fullFilePath pathExtension];
    }
	
    return [fileTypeString autorelease];
}

In the same document I saw another C method (I assume) named NSFileTypeForHFSTypeCode that looks like what i’m looking for, but I can’t make it work for some reason.

Looks like I need to encode the code first, but this doesn’t work, it returns null:

+ (NSString *) returnFileDescriptionFromHFSCode: (NSString *)hfsCode
{
	OSType *hfsCodeOSType = hfsCode;
	NSString *hfsCodeEncoded = NSFileTypeForHFSTypeCode(hfsCodeOSType);
	NSString *fileDescription = NSHFSTypeCodeFromFileType(hfsCodeEncoded);
	return [fileDescription autorelease];
}

Someone has an idea? Looked for hours on the web for answers, nothing so far…

Grateful as always… :slight_smile:

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

What do you need to do with this information? Do you really need both the default app to open a particular file and the HFS code?

I think your first piece of objective C code in your last post gives you the same information you get from the getInfoForFile_application_type_ method – at least it gave me the same results for all the files I tried.

What do you expect to get from that method – I don’t quite understand what it is supposed to do.

Ric

Well, my app needs to display a list of files in a Table View, and I need to display the file type along with it’s name and size. For files that have a UTI it’s been fairly easy to get this information with the localizedDescriptionForType: method. But for old HFS code files (like Adobe InDesign’s), this has proven a lot more challenging.

I was able to get the creator code with a custom ObjC method I found in the docs, but this does not give me a string like “InDesign® CS5 document” like I would get with the info panel in the Finder.

The goal is that I won’t have to keep a database of all file type description (plus their locales) in existence and instead rely on what’s in the system.

Now I thought that the C method “NSFileTypeForHFSTypeCode” would give me that, but I haven’t been able to get any result so far.

How was it done before the arrival of UTIs? I guess that is my question…

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

You get no result because the type of OSType is not NSString, it is 32 bit unsigned integer.
Those four-letter codes within single quotes are in fact integers

I see. Then it is not what I wanted, I was expecting a string like “InDesign document” coming out of this method, not an HFS code.

Alright, i’ll have to do this some other way. If I use the mdls command in the terminal, there is an entry name kMDItemKind that has the info I need.

Is there access to spotlight through ASOC if I provide a path? I ask this without even looking, I’m lazy I know… :slight_smile:

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

Not with ASOC, but with C functions using the Spotlight API


	NSString *path = @"/path/to/file";
	MDItemRef itemRef = MDItemCreate(kCFAllocatorDefault, (CFStringRef)path);
	if (itemRef) {
		NSString *kind = (NSString *)MDItemCopyAttribute(itemRef, kMDItemKind);
		NSLog(@"%@", kind);
	}

Yes! That’s exactly it. Thank you so much!

It’s a bit strange though that spotlight functions are not accessible through ASOC… but still, this is a much better solution than using a shell script and parsing the results!

Regards,
Fred

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

Have you tried using NSURL?

-- make a URL
set theURL to current application's NSURL's fileURLWithPath_("/Users/shane/Desktop/Table sample.indd")
-- get value as array of single dictionary
set theResult to theURL's resourceValuesForKeys_error_({current application's NSURLLocalizedTypeDescriptionKey}, missing value)
-- extract string
set docType to (theResult's valueForKey_(current application's NSURLLocalizedTypeDescriptionKey)) as text

This gives me:

10:08:11.867 set theURL to current application's NSURL's fileURLWithPath_("/Users/shane/Desktop/Table sample.indd")
--> file://localhost/Users/shane/Desktop/Table%20sample.indd
10:08:11.877 set theResult to theURL's resourceValuesForKeys_error_({current application's NSURLLocalizedTypeDescriptionKey}, missing value)
--> {
    NSURLLocalizedTypeDescriptionKey = "InDesign\U00ae CS5 Document";
}
10:08:11.878 set docType to (theResult's valueForKey_(current application's NSURLLocalizedTypeDescriptionKey)) as text
--> InDesign® CS5 Document

Oooh, that’s also very interesting… and accessible from ASOC! I didn’t think there would be something in NSURL, I focused my efforts on NSFileManager thinking that it would have the solution.

Thank you so much to the both of you. I know have a fully working solution!

Fred

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

FWIW, NSURL is preferred over NSFileManager for this sort of thing these days. You can also get some of your other stuff like this, using NSURLLocalizedNameKey, NSURLTotalFileSizeKey, etc.

Really? May I ask why? Is NSURL the “future” ?

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

I suspect it’s at least partly to do with things like iCloud, but I don’t know really. NSFileManager is probably not going away, but NSURL can deal with more than just traditional files on a disk.