Можно ли получить доступ к плате Mac OS X при входе через SSH? - PullRequest
1 голос
/ 04 августа 2009

У нас есть следующий фрагмент.

OSStatus createErr = PasteboardCreate(kPasteboardClipboard, &m_pboard);
if (createErr != noErr) {
    LOG((CLOG_DEBUG "failed to create clipboard reference: error %i" createErr));
}

Это прекрасно компилируется, однако не запускается при вызове из SSH. Это потому, что в терминале SSH нет доступного монтажного стола. Тем не менее, идея заключается в том, чтобы обмениваться буферами обмена между компьютерами.

При запуске с настольного терминала это работает просто отлично. Но при запуске из SSH PasteboardCreate возвращает -4960 (он же, coreFoundationUnknownErr). Я предполагаю, что единственный способ обойти эту проблему - запустить приложение из той же среды, что и монтажная панель, но возможно ли это?

Ответы [ 4 ]

3 голосов
/ 28 октября 2009

Прямой доступ к монтажному картону выглядит бесполезным. Во-первых, launchd не зарегистрирует процессы 1 с помощью порта Маха сервера монтажа. Сначала вам нужно найти способ получить порт Маха сервера монтажа (mach_port_names?). Кроме того, прямая связь между сеансами пользователя запрещена 2 , а другая связь ограничена. Я не уверен, будут ли у вашей программы права на подключение к серверу монтажа.

Вот первый пример иллюстративного примера использования событий Apple для получения и установки буфера обмена в виде строки. Обработка ошибок минимальна или отсутствует (я не уверен, что я чувствую по поводу require_noerr). Если вы собираетесь получать / устанавливать данные буфера обмена несколько раз во время выполнения, вы можете сохранить события Apple и при копировании в буфер обмена использовать AECreateDesc & AEPutParamDesc или (возможно) AEBuildParameters. AEVTBuilder может быть полезным.

NSString* paste() {
    NSString *content;

    AppleEvent paste, reply = { typeNull, 0L };
    AEBuildError buildError = { typeNull, 0L };
    AEDesc clipDesc = { typeNull, 0L };

    OSErr err;

    err = AEBuildAppleEvent(kAEJons, kAEGetClipboard, 
                            typeApplicationBundleID, "com.apple.finder", strlen("com.apple.finder"), 
                            kAutoGenerateReturnID, kAnyTransactionID,
                            &paste, &buildError,
                            ""
        );
    require_noerr(err, paste_end);
    err = AESendMessage(&paste, &reply, kAEWaitReply, kAEDefaultTimeout);
    err = AEGetParamDesc(&reply, keyDirectObject, typeUTF8Text, &clipDesc);
    require_noerr(err, pastErr_getReply);

    Size dataSize = AEGetDescDataSize(&clipDesc);
    char* clipData = malloc(dataSize);
    if (clipData) {
        err = AEGetDescData(&clipDesc, clipData, dataSize);
        if (noErr == err) {
            content = [NSString stringWithCString:clipData encoding:NSUTF8StringEncoding];
        } else {}
        free(clipData);
    }

    AEDisposeDesc(&clipDesc);
pastErr_getReply:
    AEDisposeDesc(&reply);
pasteErr_sending:
    AEDisposeDesc(&paste);
paste_end:
    return content;
}

OSStatus copy(NSString* clip) {
    AppleEvent copy, reply = { typeNull, 0L };
    AEBuildError buildError = { typeNull, 0L };

    OSErr err = AEBuildAppleEvent(kAEJons, kAESetClipboard, 
                                  typeApplicationBundleID, "com.apple.finder", strlen("com.apple.finder"), 
                                  kAutoGenerateReturnID, kAnyTransactionID,
                                  &copy, &buildError,
                                  "'----':utf8(@)",
                                  AEPARAMSTR([clip UTF8String])
                                  /*
                                    "'----':obj {form: enum(prop), want: type(@), seld: type(@), from: null()}"
                                    "data:utf8(@)",
                                    AEPARAM(typeUTF8Text),
                                    AEPARAM(pClipboard),
                                    AEPARAMSTR([clip UTF8String])
                                  */
        );
    if (aeBuildSyntaxNoErr != buildError.fError) {
        return err;
    }
    AESendMessage(&copy, &reply, kAENoReply, kAEDefaultTimeout);
    AEDisposeDesc(&reply);
    AEDisposeDesc(&copy);
    return noErr;
}

Я оставляю подход Core Foundation выше, но вы, вероятно, захотите использовать NSAppleEventDescriptor для извлечения содержимого буфера обмена из ответа Apple Event.

    err = AESendMessage(&paste, &reply, kAEWaitReply, kAEDefaultTimeout);
require_noerr(err, pasteErr_sending);
    // nsReply takes ownership of reply
    NSAppleEventDescriptor *nsReply = [[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&reply];
    content = [[nsReply descriptorAtIndex:1] stringValue];
    [nsReply release];

pasteErr_sending:
    AEDisposeDesc(&paste);
paste_end:
    return content;
}

NSAppleEventDescriptor также легче исследовать в отладчике, чем AEDesc. Чтобы проверить ответы, вы также можете установить переменную окружения AEDebugReceives при использовании osascript или Script Editor.app:

AEDebugReceives=1 osascript -e 'tell application "Finder" to get the clipboard'

Ссылки

  1. «Настройка пользовательских сеансов»
  2. "Общение между сеансами входа в систему"
  3. Интерфейс ядра Маха , особенно:
  4. Справочник CFMessagePort (упаковщик порта Маха):
  5. Руководство по программированию событий Apple
  6. Справочник по Apple Event Manager
  7. AEBuild *, AEPrint * и Friends
  8. AEBuildAppleEvent на CocoaDev
  9. Магия отладки Mac OS X (для AEDebugSends и других переменных среды AEDebug *)
3 голосов
/ 25 октября 2009

Я попытался сделать это в AppleScript, и это сработало (даже при вызове через SSH). Мой сценарий выглядит следующим образом:

#!/usr/bin/osascript

on run
    tell application "Finder"
        display dialog (get the clipboard)
    end tell
end run

Это определенно не идеальное решение, но, возможно, если бы вы поработали над тем, как это делает AppleScript, это помогло бы вам реализовать его самостоятельно.

1 голос
/ 27 октября 2009

Взгляните на pbpaste (получение содержимого буфера обмена) и pbcopy (копирование содержимого в буфер обмена). Работает нормально, также над SSH. :)

В Mac OS X Snow Leopard:

pbcopy Mac
(источник: hillrippers.ch )

В Ubuntu 9.04:

pbpaste Ubuntu
(источник: hillrippers.ch )

0 голосов
/ 28 октября 2009

Вы можете получить доступ к монтажной панели с помощью PasteboardCreate через SSH на SnowLeopard, но не на Leopard или Tiger.

Возможно, вы не хотите использовать pbcopy и pbpaste для полной синхронизации картона, поскольку они имеют дело только с обычным текстом, RTF и EPS. Например, если вы скопируете изображение, а затем попытаетесь записать его с помощью pbpaste, вы не получите никакого вывода.

Предполагая, что у вас есть приложение, запущенное в сеансе пользователя на обоих компьютерах, вы можете сериализовать данные из монтажной панели в файл, передать их по SSH, прочитать их из приложения на удаленной стороне, а затем поместить данные из монтажной панели в удаленный картон. Однако получить правильную сериализацию из картона может быть сложно, и я не уверен, насколько переносимы данные из картона между операционными системами и архитектурами.

...