I have an OSX xcode project, which works perfectly until I turn the sandbox on.
Under Capabilities, I have turn on Sandbox, and File access: User Selected File - Read/Write
My project is like this, when user clicks on a button, the NSSavePanel will popup, user specifies the save directory and file name (ie. myfile.dmg), and once he or she clicks on save, the program will create dmg file using NSTask and hdiutil to the specific path. Here is my code:
__block NSSavePanel *saveDlg = [NSSavePanel savePanel];
// Enable options in the dialog.
[saveDlg setCanCreateDirectories:YES];
[saveDlg setAllowedFileTypes:[NSArray arrayWithObject:@"dmg"]];
[saveDlg setCanSelectHiddenExtension:YES];
[saveDlg beginSheetModalForWindow:self.view.window completionHandler:^ (NSInteger result) {
if (result == NSFileHandlingPanelOKButton) {
BOOL bSuccess = [self checkErrorHandler: saveDlg.URL optionToCheck: 8];
if (bSuccess) {
[self createDMG:saveDlg.URL];
}
}
saveDlg = nil;
}];
Here is my createDMG method:
- (void)createDMG:(NSURL *)myurl{
self.url = myurl;
self.createTask = [[NSTask alloc] init];
NSPipe *outputPipe = [NSPipe pipe];
NSPipe *errorPipe = [NSPipe pipe];
NSPipe *writePipe = [NSPipe pipe];
self.fhCreateOutput = [outputPipe fileHandleForReading];
self.fhCreateError = [errorPipe fileHandleForReading];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(createNotifiedForStdOutput:) name:NSFileHandleReadCompletionNotification object:self.fhCreateOutput];
[nc addObserver:self selector:@selector(createNotifiedForStdError:) name:NSFileHandleReadCompletionNotification object:self.fhCreateError];
[nc addObserver:self selector:@selector(createNotifiedForComplete:) name:NSTaskDidTerminateNotification object:self.createTask];
NSFileHandle *writeHandle = [writePipe fileHandleForWriting];
NSString *pw = [self getPlainTextPassword:nil];
[writeHandle writeData: [[NSString stringWithFormat:@"%@\0\n", pw] dataUsingEncoding:NSUTF8StringEncoding]];
[writeHandle closeFile];
[self.createTask setStandardInput:writePipe];
NSString *directoryPath = [self.url.path stringByDeletingLastPathComponent];
NSString *fileName = [[self.url absoluteString] lastPathComponent];
[self.createTask setLaunchPath: @"/usr/bin/hdiutil"];
[self.createTask setCurrentDirectoryPath:directoryPath];
[self.createTask setArguments:[NSArray arrayWithObjects:@"create", @"-puppetstrings", @"-encryption",@"AES-128", @"-size", @"100m", @"-verbose", @"-volname", @"test", fileName, @"-fs", @"HFS+J", @"-stdinpass", nil]];
[self.createTask setStandardOutput: outputPipe];
[self.createTask setStandardError:errorPipe];
[self.createTask launch];
[self.fhCreateOutput readInBackgroundAndNotify];
[self.fhCreateError readInBackgroundAndNotify];
}
and I got the following error:
2015-02-18 10:51:47.374 My DMG[41725:2016417] -[MyDMG
createNotifiedForStdError:] verbose: 2015-02-18 10:51:46.745 diskimages-helper[41741:2016793] ERROR: couldn't connect to framework.
2015-02-18 10:51:47.376 My DMG[41725:2016417] -[MyDMG createNotifiedForStdError:] verbose: 2015-02-18 10:51:46.745 diskimages-helper[41741:2016793] DIHelper: setupConnectionToFrameworkWithUUID: failed
2015-02-18 10:51:46.747 hdiutil[41739:2016783] helper died
DIHLDiskImageCreate() returned 10
(null)
2015-02-18 10:51:47.665 My DMG[41725:2016417] -[MyDMG createNotifiedForStdError:] verbose: hdiutil: create: returning 10
2015-02-18 10:51:47.682 My DMG[41725:2016417] -[MyDMG createNotifiedForStdError:] verbose: hdiutil: create failed - No child processes
2015-02-18 10:51:47.687 My DMG[41725:2016417] task completed or was stopped with exit code 1
Some people said that NSTask doesn't work well with sandbox, but I have a couple other project that runs NSTask in sandbox and they worked. Also if you look at the mac app store, there is a similar app which creates dmg (user drags a folder and dmg file created)
Any help is appreciated :)