How to know if a folder is a Package or not ?

The guy who helped me on the other forum did the test, no problem in volume not indexed with Spotloght.

Here the Method for those who want :
Function IsPackage_f(Extends CetElt as FolderItem) As Boolean

  Dim DrapPackage as Boolean ' Retourne Vrai si  CetElt  est un Package (.app .rtfd . pkg .mpkg etc.) et Faux sinon
  Dim CdeShell as New Shell ' Note : J'utilise  Extends  pour pouvoir crire  MonElt.CountVis_fSH  mais a fera une Nil Objection si  Nil
  ' Voir notes dans IsPackage_fcarbon
  
  #If DebugBuild Then ' Si  CetElt  n'existe pas a plantera, doit tre test avant
    If not CetElt.Directory Then MsgBox "Problme Tom, IsPackage , tu ne devrais (dois ?) y tester que des dossiers !"
  #EndIf
  
  #If TargetMacOS Then
    ' NE PAS utiliser  "'" + MonFolderItem.ShellPath_fAS + "'"
    ' NON : CdeShell.Execute "mdls -name kMDItemContentTypeTree '" + CetElt.ShellPath + "'"
    ' On n'utilise pas le Quotedform avec ' ' car s'il y a un ' dans le nom a merde
    ' CdeShell.Execute "mdls " + CetElt.ShellPath
    ' MsgBox CdeShell.Result
    ' Avant : CdeShell.Execute "mdls -name kMDItemContentType -raw " + CetElt.ShellPath
    CdeShell.Execute "mdls -name kMDItemContentTypeTree " + CetElt.ShellPath
    If CdeShell.ErrorCode = 0 Then
      ' MsgBox CdeShell.Result
      DrapPackage = not(Instr(1, CdeShell.Result, "com.apple.package") = 0)
      ' Avant : DrapPackage = not((CdeShell.Result = "public.folder") or (CdeShell.Result = "public.volume"))
    Else ' Dossier sur lequel on n'a pas les droits ou etc.
      DrapPackage = False
      ' MsgBox "Error code : " + Str(CdeShell.ErrorCode)
    End If
    
    ' Avant avec AppleScript mais c'est plus lent :
    ' DrapPackage = (IsPackage_s(CetElt.ShellPath_fAS) = "True") ' Mthode AppleScript plus lente que mthode avec Carbon
    
  #Else
    DrapPackage = False
    
  #EndIf
  
  Return DrapPackage

I would really prefer if people use a plugin or a declare to get it instead of running a shell tool a lot.
If you check /Applications with this you run hundreds of times the app which takes a long time. And it may fail if permissions don’t allow you the inspection.

[code]
If folderitem.Directory and folderitem.Child(“Contents”).child(“MacOS”)<>nil Then

//it’s a folder not a bundle
[/code]

What about just peaking into subfolders to see if there is MacOS folder or not…or would this cause some other problems?

But I don’t know the declare, the link give above is very hard to use.
If one day I find a Method using a Declare I’ll use it.
I can’t buy MBS pluggins only for this.

Just one of 40000 functions…

[quote=18458:@Kuzey Atici][code]
If folderitem.Directory and folderitem.Child(“Contents”).child(“MacOS”)<>nil Then
[/quote]

A bundle does not require to have a MacOS folder.

[quote=18459:@Thomas ROBISSON]But I don’t know the declare, the link give above is very hard to use.
If one day I find a Method using a Declare I’ll use it.
I can’t buy MBS pluggins only for this.[/quote]
Grab macoslib (it’s free) drag it into your project & use what you need (it’s free - did I mention that?)
Anything not required wont even be compiled into your application.
And you get all kinds of useful stuff for free (I think I mentioned that) and don’t have to learn the specific declare.

[quote=18459:@Thomas ROBISSON]But I don’t know the declare, the link give above is very hard to use.
If one day I find a Method using a Declare I’ll use it.
I can’t buy MBS pluggins only for this.[/quote]

Here’s a self-contained version of what you’re after:

Function IsPackage( f as FolderItem ) As Boolean
  Declare Function boolValue Lib "Foundation" selector "boolValue" ( obj As ptr ) As Boolean
  
  Dim isPackage As ptr
  If GetFileValue( f, "NSURLIsPackageKey", isPackage ) Then
    Return boolValue( isPackage )
  Else
    // At this point, isPackage isa NSError. Do something with it or just assume
    // that it's not a package.
    Return False
  End If
End Function
Protected Function GetFileValue(f as FolderItem, key as String, byref result as ptr) As Boolean
  // Gets an NSURL resource value for the given FolderItem.
  //
  // @param f The FolderItem to inspect (non-nil).
  // @param key The NSURL resource value key. See the documentation for NSURL.
  // @param result Upon return, the resource value or error.
  // @result Whether or not the function succeeded.
  
  Declare Function dlopen Lib "System" ( path As CString, mode As Integer ) As ptr
  Declare Function dlsym Lib "System" ( handle As PTr, name As CString ) As ptr
  Const RTLD_LAZY = 1
  Const RTLD_GLOBAL = 8
  
  Dim libPtr As ptr = dlopen( "/System/Library/Frameworks/Foundation.framework/Foundation", RTLD_LAZY Or RTLD_GLOBAL )
  If libPtr = Nil Then Return False
  
  Dim symPtr As ptr = dlsym( libPtr, key )
  If symPtr = Nil Then Return False
  
  // Now we can create the URL and get the value
  Declare Function NSClassFromString Lib "Foundation" ( name As CFStringRef ) As ptr
  Declare Function URLWithString Lib "Foundation" selector "URLWithString:" ( obj As ptr, Str As CFStringRef ) As ptr
  Declare Function getResourceValue Lib "Foundation" selector "getResourceValue:forKey:error:" _
  ( obj As ptr, ByRef Val As ptr, key As ptr, ByRef error As ptr ) As Boolean
  
  Dim fileURL As ptr = URLWithString( NSClassFromString( "NSURL" ), f.URLPath )
  Dim value, error As ptr
  If getResourceValue( fileURL, value, symPtr.ptr, error ) Then
    result = value
    Return True
  Else
    result = error
    Return False
  End If
End Function

Thank you very much, I will use this. I suppose it’s for System X 10.6 and newer. I’m on iPad and can’t verify, but I remember that the function using Declare for system earlier than 10.6 is different.

Xojo doesn’t support systems earlier than 10.6, so it’s a non-issue.

Yes, but I continue to write code with RealStudio, and then I do a build in Carbon with RealStudio, then open the source in Xojo, and I do a build in Carbon and another in Cocoa.
Pffff, it’s long. And I will build only in Cocoa Xojo soon.

I already have a Method to know if build with RealStudio or Xoko, I will use it to use the old Declare or your new one.

Hi, thank you very much for your help. I did a Method which use the old declare I had if Build with RealStudio (Carbon) and the Joe Ranieri’s Method if build with Xojo.
Fot those of you who search the code, I put it in a module I use in all my programs. Go on this page http://throb.pagesperso-orange.fr/site/Prg_AutresRB.html and then to the bottom of the page and download zz_External .