Mac OS X では、アプリケーションを自動的に起動することはできません。これにはいくつかの安全上の理由があります。自動的に起動できるのは.pkg
ファイルだけで、これは Safari AFAIK 経由でのみ可能です。
アプリケーションが存在する DMG ファイルを特定することができます。これには IOKit を使用する必要があります。IORegistryExplorer をいじってみてください。
あなたを助けるかもしれないいくつかのコード
これらはIOKitを使用する私の最初の試みです。これは別の目的のためですが、それでもなお役立つはずです。
// hopefully all needed headers
#include <sys/stat.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOBSD.h>
#include <CoreFoundation/CoreFoundation.h>
/* First we want to get the major and minor BSD number
* of the DMG that our app is residing on.
*
* char *path is the path of a file that resides on the disk image.
* It is like this: /Volumes/Partition Name/SomeFile
* The simplest method to get such a path is to ask
* NSBundle for the path of the executable.
*/
// look up device number with stat
char *path = "path/to/app";
struct stat stats;
if (stat(path, &stats) != 0) {
return;
}
int bsd_major = major(stats.st_dev);
int bsd_minor = minor(stats.st_dev);
/* Now that we've got the BSD numbers we have to locate the
* IOService that has those numbers. IOKit works with
* CoreFoundation types.
*/
CFTypeRef keys[2] = { CFSTR(kIOBSDMajorKey), CFSTR(kIOBSDMinorKey) };
CFTypeRef values[2];
values[0] = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &bsd_major);
values[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &bsd_minor);
CFDictionaryRef matchingDictionary;
matchingDictionary = CFDictionaryCreate(kCFAllocatorDefault,
&keys, &values,
sizeof(keys) / sizeof(*keys),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFRelease(values[0]);
CFRelease(values[1]);
// IOServiceGetMatchingService uses up one reference to the dictionary
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault,
matchingDictionary);
if (!service) {
return;
}
/* Now this part is quite different from what I need
* for my application. I'm not sure how this works
* because I'm currently not at my Mac and cannot try it.
*
* You need to go up the IOService chain. It looks like this:
+-o IOHDIXHDDriveOutKernelUserClient
+-o IODiskImageBlockStorageDeviceOutKernel <---- You want to get up here
+-o IOBlockStorageDriver
+-o Apple UDIF read-only compressed (zlib) Media
+-o IOMediaBSDClient
+-o IOApplePartitionScheme
+-o Apple@1
| +-o IOMediaBSDClient
+-o disk image@2 <---- This is the matched IOService!
+-o IOMediaBSDClient
*
* IODiskImage... has a property "Protocol Characteristics" which is a
* dictionary that has the key "Virtual Interface Location Path" which is
* the path to the disk image. There are probably #defines somewhere in
* IOKit for those keys.
*
* This code is NOT tested. It's out of my head and the documentation.
* This goes up 4 times in the hierarchy. Hopefully there aren't more
* than 1 parents.
*/
for (int i = 0; i < 4; i++) {
io_service_t parent;
IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent);
IOObjectRelease(service);
service = parent;
}
/* Getting the property from the IOService is the last step:
*/
CFDictionaryRef characteristics;
characteristics = (CFDictionaryRef)IORegistryEntryCreateCFProperty(service,
CFSTR("Protocol Characteristics"),
kCFAllocatorDefault, 0)
CFStringRef *dmgPath = CFDictionaryGetValue(characteristics,
CFSTR("Virtual Interface Location Path"));
// clean up
IOObjectRelease(service);
CFRetain(dmgPath);
CFRelease(characteristics);
// Use the path
// later
CFRelease(dmgPath);
フリーダイヤルのブリッジ サポートにより、CoreFoundation クラスの代わりに Foundation クラスを使用して、これの多くを実行できます。これにより、少し簡単になり、読みやすくなります。
上記のサンプル コードは、IOBlockStorageDriver の親 IOService が IODiskImageBlockStorageDeviceOutKernel の場合に機能します。親 IOService の名前が「AppleDiskImageDevice」の場合、IOService チェーンは少し異なります。
+-o IOHDIXHDDriveOutKernelUserClient
+-o AppleDiskImageDevice <---- You want to get up here
+-o IOBlockStorageDriver
+-o Apple Disk Image Media <---- This is different
+-o IOMediaBSDClient
+-o IOApplePartitionScheme
+-o Apple@1
| +-o IOMediaBSDClient
+-o disk image@2 <---- This is the matched IOService!
+-o IOMediaBSDClient
上記の for ループの後、次のように画像ファイル パスの URL 文字列を取得できます。
CFMutableDictionaryRef properties = nil;
IORegistryEntryCreateCFProperties(service, &properties, kCFAllocatorDefault, kNilOptions);
if (properties) {
CFStringRef url = CFDictionaryGetValue(properties, CFSTR("DiskImageURL"));
CFRelease(properties);
}
IOObjectRelease(service);