1 /////////////////////////////////////////////////////////////////////////////
2 // Name: mac/corefoundation/utilsexc_base.cpp
3 // Purpose: wxMacExecute
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"
34 #include <CoreFoundation/CoreFoundation.h>
35 #include <ApplicationServices/ApplicationServices.h>
38 #include "wx/filename.h"
39 #include "wx/mac/corefoundation/cfstring.h"
43 #define kDefaultPathStyle kCFURLPOSIXPathStyle
45 #define kDefaultPathStyle kCFURLHFSPathStyle
48 //===========================================================================
50 //===========================================================================
52 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
56 // argv is the command line split up, with the application path first
57 // flags are the flags from wxExecute
58 // process is the process passed from wxExecute for pipe streams etc.
59 // returns -1 on error for wxEXEC_SYNC and 0 on error for wxEXEC_ASYNC
60 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
61 long wxMacExecute(wxChar
**argv
,
65 // Semi-macros used for return value of wxMacExecute
66 const long errorCode
= ((flags
& wxEXEC_SYNC
) ? -1 : 0);
67 const long successCode
= ((flags
& wxEXEC_SYNC
) ? 0 : -1); // fake PID
69 // Obtains the number of arguments for determining the size of
70 // the CFArray used to hold them
72 for(wxChar
** argvcopy
= argv
; *argvcopy
!= NULL
; ++argvcopy
)
77 // If there is not a single argument then there is no application
81 wxLogDebug(wxT("wxMacExecute No file to launch!"));
86 wxString path
= *argv
++;
88 // Create a CFURL for the application path
89 // Created this way because we are opening a bundle which is a directory
91 CFURLCreateWithFileSystemPath(
93 wxMacCFStringHolder(path
,
94 wxLocale::GetSystemEncoding()),
96 true); //false == not a directory
98 // Check for error from the CFURL
101 wxLogDebug(wxT("wxMacExecute Can't open path: %s"), path
.c_str());
105 // Create a CFBundle from the CFURL created earlier
106 CFBundleRef cfbApp
= CFBundleCreate(kCFAllocatorDefault
, cfurlApp
);
108 // Check to see if CFBundleCreate returned an error,
109 // and if it did this was an invalid bundle or not a bundle
110 // at all (maybe a simple directory etc.)
113 wxLogDebug(wxT("wxMacExecute Bad bundle: %s"), path
.c_str());
118 // Get the bundle type and make sure its an 'APPL' bundle
119 // Otherwise we're dealing with something else here...
120 UInt32 dwBundleType
, dwBundleCreator
;
121 CFBundleGetPackageInfo(cfbApp
, &dwBundleType
, &dwBundleCreator
);
122 if(dwBundleType
!= 'APPL')
124 wxLogDebug(wxT("wxMacExecute Not an APPL bundle: %s"), path
.c_str());
130 // Create a CFArray for dealing with the command line
131 // arguments to the bundle
132 CFMutableArrayRef cfaFiles
= CFArrayCreateMutable(kCFAllocatorDefault
,
133 cfiCount
-1, &kCFTypeArrayCallBacks
);
134 if(!cfaFiles
) //This should never happen
136 wxLogDebug(wxT("wxMacExecute Could not create CFMutableArray"));
142 // Loop through command line arguments to the bundle,
143 // turn them into CFURLs and then put them in cfaFiles
144 // For use to launch services call
145 for( ; *argv
!= NULL
; ++argv
)
147 // Check for '<' as this will ring true for
148 // CFURLCreateWithString but is generally not considered
149 // typical on mac but is usually passed here from wxExecute
150 if (wxStrcmp(*argv
, wxT("<")) == 0)
154 CFURLRef cfurlCurrentFile
; // CFURL to hold file path
155 wxFileName
argfn(*argv
); // Filename for path
157 if(argfn
.DirExists())
159 // First, try creating as a directory
160 cfurlCurrentFile
= CFURLCreateWithFileSystemPath(
162 wxMacCFStringHolder(*argv
,
163 wxLocale::GetSystemEncoding()),
165 true); //true == directory
167 else if(argfn
.FileExists())
169 // And if it isn't a directory try creating it
171 cfurlCurrentFile
= CFURLCreateWithFileSystemPath(
173 wxMacCFStringHolder(*argv
,
174 wxLocale::GetSystemEncoding()),
176 false); //false == regular file
180 // Argument did not refer to
181 // an entry in the local filesystem,
182 // so try creating it through CFURLCreateWithString
183 cfurlCurrentFile
= CFURLCreateWithString(
185 wxMacCFStringHolder(*argv
, wxLocale::GetSystemEncoding()),
189 // Continue in the loop if the CFURL could not be created
190 if(!cfurlCurrentFile
)
193 wxT("wxMacExecute Could not create CFURL for argument:%s"),
198 // Add the valid CFURL to the argument array and then
199 // release it as the CFArray adds a ref count to it
204 CFRelease(cfurlCurrentFile
); // array has retained it
207 // Create a LSLaunchURLSpec for use with LSOpenFromURLSpec
208 // Note that there are several flag options (launchFlags) such
209 // as kLSLaunchDontSwitch etc. and maybe we could be more
210 // picky about the flags we choose
211 LSLaunchURLSpec launchspec
;
212 launchspec
.appURL
= cfurlApp
;
213 launchspec
.itemURLs
= cfaFiles
;
214 launchspec
.passThruParams
= NULL
; //AEDesc*
215 launchspec
.launchFlags
= kLSLaunchDefaults
;
216 launchspec
.asyncRefCon
= NULL
;
218 // Finally, call LSOpenFromURL spec with our arguments
219 // 2nd parameter is a pointer to a CFURL that gets
220 // the actual path launched by the function
221 OSStatus status
= LSOpenFromURLSpec(&launchspec
, NULL
);
223 // Cleanup corefoundation references
228 // Check for error from LSOpenFromURLSpec
231 wxLogDebug(wxT("wxMacExecute LSOpenFromURLSpec Error: %d"),
236 // No error from LSOpenFromURLSpec, so app was launched