1 /////////////////////////////////////////////////////////////////////////////
2 // Name: mac/corefoundation/utilsexc_base.cpp
3 // Purpose: wxMacLaunch
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 // Notes: Source was originally in utilsexc_cf.cpp,1.6 then moved
11 // to totally unrelated hid.cpp,1.8.
12 /////////////////////////////////////////////////////////////////////////////
14 //===========================================================================
16 //===========================================================================
18 //---------------------------------------------------------------------------
19 // Pre-compiled header stuff
20 //---------------------------------------------------------------------------
22 // For compilers that support precompilation, includes "wx.h".
23 #include "wx/wxprec.h"
27 #include "wx/string.h"
35 #include <CoreFoundation/CoreFoundation.h>
36 #ifndef __WXOSX_IPHONE__
37 #include <ApplicationServices/ApplicationServices.h>
41 #include "wx/filename.h"
42 #include "wx/mac/corefoundation/cfstring.h"
45 #define kDefaultPathStyle kCFURLPOSIXPathStyle
47 //===========================================================================
49 //===========================================================================
51 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
55 // argv is the command line split up, with the application path first
56 // flags are the flags from wxExecute
57 // process is the process passed from wxExecute for pipe streams etc.
58 // returns -1 on error for wxEXEC_SYNC and 0 on error for wxEXEC_ASYNC
59 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
60 bool wxMacLaunch(char **argv
)
62 // Obtains the number of arguments for determining the size of
63 // the CFArray used to hold them
65 for(char** argvcopy
= argv
; *argvcopy
!= NULL
; ++argvcopy
)
70 // If there is not a single argument then there is no application
74 wxLogDebug(wxT("wxMacLaunch No file to launch!"));
79 wxString path
= *argv
++;
81 // Create a CFURL for the application path
82 // Created this way because we are opening a bundle which is a directory
84 CFURLCreateWithFileSystemPath(
88 true); //false == not a directory
90 // Check for error from the CFURL
93 wxLogDebug(wxT("wxMacLaunch Can't open path: %s"), path
.c_str());
97 // Create a CFBundle from the CFURL created earlier
98 CFBundleRef cfbApp
= CFBundleCreate(kCFAllocatorDefault
, cfurlApp
);
100 // Check to see if CFBundleCreate returned an error,
101 // and if it did this was an invalid bundle or not a bundle
102 // at all (maybe a simple directory etc.)
105 wxLogDebug(wxT("wxMacLaunch Bad bundle: %s"), path
.c_str());
110 // Get the bundle type and make sure its an 'APPL' bundle
111 // Otherwise we're dealing with something else here...
112 UInt32 dwBundleType
, dwBundleCreator
;
113 CFBundleGetPackageInfo(cfbApp
, &dwBundleType
, &dwBundleCreator
);
114 if(dwBundleType
!= 'APPL')
116 wxLogDebug(wxT("wxMacLaunch Not an APPL bundle: %s"), path
.c_str());
122 // Create a CFArray for dealing with the command line
123 // arguments to the bundle
124 CFMutableArrayRef cfaFiles
= CFArrayCreateMutable(kCFAllocatorDefault
,
125 cfiCount
-1, &kCFTypeArrayCallBacks
);
126 if(!cfaFiles
) //This should never happen
128 wxLogDebug(wxT("wxMacLaunch Could not create CFMutableArray"));
134 // Loop through command line arguments to the bundle,
135 // turn them into CFURLs and then put them in cfaFiles
136 // For use to launch services call
137 for( ; *argv
!= NULL
; ++argv
)
139 // Check for '<' as this will ring true for
140 // CFURLCreateWithString but is generally not considered
141 // typical on mac but is usually passed here from wxExecute
142 if (wxStrcmp(*argv
, wxT("<")) == 0)
146 CFURLRef cfurlCurrentFile
; // CFURL to hold file path
147 wxFileName
argfn(*argv
); // Filename for path
149 if(argfn
.DirExists())
151 // First, try creating as a directory
152 cfurlCurrentFile
= CFURLCreateWithFileSystemPath(
154 wxCFStringRef(*argv
),
156 true); //true == directory
158 else if(argfn
.FileExists())
160 // And if it isn't a directory try creating it
162 cfurlCurrentFile
= CFURLCreateWithFileSystemPath(
164 wxCFStringRef(*argv
),
166 false); //false == regular file
170 // Argument did not refer to
171 // an entry in the local filesystem,
172 // so try creating it through CFURLCreateWithString
173 cfurlCurrentFile
= CFURLCreateWithString(
175 wxCFStringRef(*argv
),
179 // Continue in the loop if the CFURL could not be created
180 if(!cfurlCurrentFile
)
183 wxT("wxMacLaunch Could not create CFURL for argument:%s"),
188 // Add the valid CFURL to the argument array and then
189 // release it as the CFArray adds a ref count to it
194 CFRelease(cfurlCurrentFile
); // array has retained it
197 // Create a LSLaunchURLSpec for use with LSOpenFromURLSpec
198 // Note that there are several flag options (launchFlags) such
199 // as kLSLaunchDontSwitch etc. and maybe we could be more
200 // picky about the flags we choose
201 LSLaunchURLSpec launchspec
;
202 launchspec
.appURL
= cfurlApp
;
203 launchspec
.itemURLs
= cfaFiles
;
204 launchspec
.passThruParams
= NULL
; //AEDesc*
205 launchspec
.launchFlags
= kLSLaunchDefaults
;
206 launchspec
.asyncRefCon
= NULL
;
208 // Finally, call LSOpenFromURL spec with our arguments
209 // 2nd parameter is a pointer to a CFURL that gets
210 // the actual path launched by the function
211 OSStatus status
= LSOpenFromURLSpec(&launchspec
, NULL
);
213 // Cleanup corefoundation references
218 // Check for error from LSOpenFromURLSpec
221 wxLogDebug(wxT("wxMacLaunch LSOpenFromURLSpec Error: %d"),
226 // No error from LSOpenFromURLSpec, so app was launched