2012-05-30 1 views
4

Я пытаюсь установить защитный вспомогательный инструмент с SMJobBless. Когда он терпит неудачу и перед вызовом SMJobBless, я вызываю SMJobRemove, потому что мне нужно удалить более старую версию инструмента, и это удастся. SMJobBless возвращает код ошибки 4098. Объект NSError сообщает мне, что «операция не может быть выполнена. В подсистеме CodeSigning произошла ошибка».Ошибка возврата SMJobBless 4098

Если я перезапущу свой код, функция SMJobBless будет работать. Я бы предположил, что это потому, что он был удален ранее, но почему он не работал в первый раз? Затем я могу связаться с инструментом, и все работает нормально. Наблюдая за тем, что все работает нормально, я уверен, что могу быть уверен, что я отвечаю пяти требованиям для SMJobBless, как описано в документации.

Если я увеличиваю версию своего инструмента и попробуйте еще раз, SMJobRemove будет работать, но, опять же, SMJobBless с кодом ошибки 4098.

Если это имеет значение, я использую OS X 10.7.3.

ответ

4

Возможно, вы звоните CFBundleCopyInfoDictionaryForURL по коду, подписанному вспомогательным инструментом?

Если это так, кажется, что эта функция, по-видимому, нарушает срок действия кода. (По-видимому, потому что CFBundle изменяет Info.plist данные в памяти, но это только мое предположение.)

Решение использовать SecCodeCopySigningInformation для чтения помощников инструмента с информацией о версии:

-(NSString *) bundleVersionForCodeSignedItemAtURL:(NSURL *)url { 
    OSStatus status; 

    // Sanity check -- nothing begets nothing 
    if (!url) { 
     return nil; 
    } 

    // Get the binary's static code 
    SecStaticCodeRef codeRef; 
    status = SecStaticCodeCreateWithPath((CFURLRef)url, kSecCSDefaultFlags, &codeRef); 
    if (status != noErr) { 
     NSLog(@"SecStatucCodeCreateWithPath() error for %@: %d", url, status); 
     return nil; 
    } 

    // Get the code signature info 
    CFDictionaryRef codeInfo; 
    status = SecCodeCopySigningInformation(codeRef, kSecCSDefaultFlags, &codeInfo); 
    if (status != noErr) { 
     NSLog(@"SecCodeCopySigningInformation() error for %@: %d", url, status); 
     CFRelease(codeRef); 
     return nil; 
    } 

    // The code signature info gives us the Info.plist that was signed, and 
    // from there we can retrieve the version 
    NSDictionary *bundleInfo = (NSDictionary *) CFDictionaryGetValue(codeInfo, kSecCodeInfoPList); 
    NSString *version = [bundleInfo objectForKey:@"CFBundleVersion"]; 

    // We have ownership of the code signature info, so we must release it. 
    // Before we do that, we need to hold onto the version otherwise we go 
    // crashing and burning. 
    [[version retain] autorelease]; 
    CFRelease(codeInfo); 
    CFRelease(codeRef); 

    return version; 
} 

Чтобы дать кредит, где это связано: жизненно важная информация относительно CFBundleCopyInfoDictionaryForURL получена от Ian MacLeod's SMJobKit.

+0

Этот код пропускает дескриптор файла в вспомогательный инструмент. 'codeRef' должен быть' CFRelease() 'd при возврате. Я попытался отредактировать сообщение сам, но он был отклонен как «слишком незначительный» вопрос. – LCC

+0

Спасибо @LCC, я только что обновил код. – Philipp

+0

Ничего себе! Это была именно та проблема, с которой я столкнулся, и это прекрасно зафиксировало ее. Спасибо за указатель и, тем не менее, реальный рабочий код! Я только хочу, чтобы документация Apple для SMJobBless и друзей была лучше. –

Смежные вопросы