AppleScript и вылетает - PullRequest
       4

AppleScript и вылетает

1 голос
/ 27 мая 2011

Я пытаюсь выполнить скрипт Apple из своего приложения C ++, но у меня все еще нет успеха, чтобы сделать его стабильным. Мой первый подход был с Carbon API:

  1. ::OSACompileExecute(Component, &ScriptTextDesc, kOSANullScript, kOSAModeNull, &ResultID); Где я создал компонент при каждом выполнении скрипта и выпустил его в той же области видимости. Но я застрял с проблемой: иногда происходит сбой при попытке освободить компонент. Таким образом, кажется, что какая-то проблема возникает в скриптовом движке, и это как-то портит Компонент. Я не нашел ни одной души, поэтому я переключился на другой, но похожий подход:
  2. ::OSACompileExecute(m_Component, &ScriptTextDesc, kOSANullScript, kOSAModeNull, &ResultID); Где m_Component - это ComponentInstance, который создается в ctor и живет во время выполнения приложения. Таким образом, сбои при выпуске Компонента исчезли из-за отсутствия шага освобождения во время работы приложения. Но есть еще одна проблема: когда пользователь пытается выйти из системы, появляется всплывающее окно с надписью «MyApp предотвращает выход из системы» (что-то в этом роде) и MyApp закрывается. Поэтому, когда я закрываю это всплывающее окно, я могу выйти из системы. Таким образом, кажется, что проблема с выпуском Компонента делает что-то, что говорит Системе, что это не может быть закрыто. Я не нашел здесь никакого решения, поэтому решил перейти к третьему подходу:
  3. Какао - NSAppleScript Решение очень простое и маленькое:

    QString ExecuteAppleScript(const QString& strScriptText)
    {
    QString strResult;
    
    NSAutoreleasePool* Pool = [[NSAutoreleasePool alloc] init];
    NSString* ScriptText = [[NSString alloc] initWithBytes:strScriptText.toUtf8().data() length:strScriptText.size() 
        encoding:NSUTF8StringEncoding];
    NSAppleScript* Script = [[NSAppleScript alloc] initWithSource:ScriptText];
    if (Script)
    {
        NSDictionary* ErrorInfo = nil;
        NSAppleEventDescriptor* Result = [Script executeAndReturnError:&ErrorInfo];
        if (Result)
        {
           strResult = QString::fromUtf8([[Result stringValue] UTF8String]);
        }
        else if (ErrorInfo)
        {
           QString strErrorInfo = QString::fromUtf8([[ErrorInfo description] UTF8String]);
        }
    }
    [ScriptText release];
    [Pool release];
    
    return strResult;
    

    }

Здесь есть немного классов Qt, но они не актуальны. Так что это работает, но он падает в разных местах внутри кишок NSAppleScript, один из журналов:

Thread 5 Crashed:
0   com.apple.applescript           0x000000010ff0a4c9 ASCoerceToDesc(unsigned int, unsigned int, int, AEDesc*) + 84
1   ...ple.CoreServices.CarbonCore  0x00007fff86545e48 CallComponentFunction + 28
2   com.apple.applescript           0x000000010ff05cb1 AppleScriptComponent + 1728
3   com.apple.applescript           0x000000010ff1ebd0 AGenericCall::Delegate(ComponentInstanceRecord*) + 46
4   com.apple.applescript           0x000000010ff1e524 AGenericManager::HandleOSACall(ComponentParameters*) + 54
5   com.apple.applescript           0x000000010ff1e4b4 GenericComponent + 219
6   com.apple.openscripting         0x00007fff8716ae34 OSACoerceToDesc + 65
7   com.apple.Foundation            0x00007fff87c61a83 -[NSAppleScript(NSPrivate) _executeWithMode:andReturnError:] + 170

Так что пока я не знаю, что еще я могу сделать, чтобы преодолеть эти сбои AppleScript ...

Дополнительная информация:

  1. AppleScript выполняется очень часто, по крайней мере, 1 скрипт в секунду.
  2. Сценарий (только что взят из кода C ++):

    сделать сценарий оболочки \ "ioreg -c IOHIDSystem" "| perl -ane 'if (/ Idle /) {$ idle = (pop @F) / 1000000000; напечатать $ idle, \\" \\ "; last}' \"

  3. AppleScipt выполняется не из основного потока. Я слышал о проблемах с NSAppleScript в версиях MacOS X до 10.6.6, но я тестировал его на 10.6.7. В любом случае подходы 1 и 2 не должны беспокоить потоки.
  4. Аварии случайны. Таким образом, он может работать весь день или сразу после запуска.

Может ли кто-нибудь помочь мне с этим? Заранее спасибо!

1 Ответ

1 голос
/ 27 мая 2011

Вы упоминаете, что запускаете NSApplescript из другого потока. Если вы посмотрите в документации по NSApplescript, справа вверху написано:

Important:  You should access NSAppleScript only from the main thread.

Так что просто знайте, что это не потокобезопасно, и это, вероятно, причина ваших проблем.

РЕДАКТИРОВАТЬ : Я вижу несколько других проблем в вашем коде. Во-первых, вы не выпускаете «Скрипт», который вы создали с помощью alloc / init. Далее, и это главная проблема ... ваш "ErrorInfo" - это словарь с парами ключ / значение. Вы не используете ключи, чтобы получить значения, и именно здесь, похоже, происходит ваш сбой. Возникают проблемы с возвратом «описания» словаря. Вот пример кода, который я использую для создания строки NSS этого словаря ошибок, поэтому сделайте что-то вроде этого.

NSString* errorInfo = [NSString stringWithFormat:@"Error:%@ %@", [errorDict valueForKey:@"NSAppleScriptErrorNumber"], [errorDict valueForKey:@"NSAppleScriptErrorMessage"]];

Наконец, вы используете какой-то метод, например "executeSelectorOnMainThread", чтобы обеспечить его запуск в основном потоке?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...