¿Es posible acceder al tablero de Mac OS X al iniciar sesión a través de SSH?

StackOverflow https://stackoverflow.com/questions/1224500

  •  22-07-2019
  •  | 
  •  

Pregunta

Tenemos el siguiente fragmento.

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

Esto compila bien, sin embargo, no se ejecuta cuando se llama desde SSH. Esto se debe a que no hay cartón disponible en el terminal SSH. Sin embargo, la idea aquí es compartir portapapeles entre computadoras.

Cuando se ejecuta desde la terminal de escritorio, esto funciona bien. Pero cuando se ejecuta desde SSH, PasteboardCreate devuelve -4960 (también conocido como coreFoundationUnknownErr). Supongo que la única forma de solucionar este problema es ejecutar la aplicación desde el mismo entorno que el tablero, pero ¿es esto posible?

¿Fue útil?

Solución

Acceder a la mesa de trabajo directamente parece ser un no-go. Primero, ejecute no registrará los procesos 1 con el puerto mach del servidor de cartón. Primero necesitará encontrar una manera de obtener el puerto mach del servidor de cartón ( mach_port_names ?). Además, la comunicación directa entre sesiones de usuario es prohibido 2 , y otras comunicaciones son limitadas. No estoy seguro de si su programa tendrá los derechos para conectarse al servidor de cartón.

Aquí hay una primera toma de un ejemplo ilustrativo sobre el uso de eventos de Apple para obtener & amp; configura el portapapeles como una cadena. El manejo de errores es mínimo o inexistente (no estoy seguro de cómo me siento acerca de require_noerr ). Si va a obtener / establecer datos del portapapeles varias veces durante una ejecución, puede guardar los eventos de Apple y, al copiarlos al portapapeles, usar AECreateDesc & amp; AEPutParamDesc o (quizás) AEBuildParameters . AEVTBuilder podría ser útil.

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;
}

Dejo el enfoque de la Fundación Core anterior, pero probablemente querrá usar NSAppleEventDescriptor para extraer el contenido del portapapeles de la respuesta de 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;
}

Un NSAppleEventDescriptor también es más fácil de examinar en un depurador que un AEDesc . Para examinar las respuestas, también puede establecer la variable de entorno AEDebugReceives al usar osascript o Script Editor.app:

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

Referencias:

  1. " Configuración de sesiones de usuario "
  2. " Comunicación a través de sesiones de inicio de sesión "
  3. Interfaz Mach Kernel , especialmente:
  4. CFMessagePort Reference ( envoltorio de puerto mach):

Otros consejos

Intenté hacerlo en AppleScript, y funcionó (incluso cuando se invocó a través de SSH). Mi script es el siguiente:

#!/usr/bin/osascript

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

Definitivamente, esta no es una solución ideal, pero tal vez si descubrió cómo lo hace AppleScript, entonces lo ayudaría a implementarlo usted mismo.

Puede acceder al cartón con PasteboardCreate a través de SSH en SnowLeopard pero no en Leopard o Tiger.

Probablemente no desee utilizar pbcopy y pbpaste para una sincronización completa del tablero, ya que solo se trata de texto sin formato, RTF y EPS. Si, por ejemplo, copia una imagen y luego intenta escribirla con pbpaste, no obtendrá ningún resultado.

Suponiendo que tiene una aplicación ejecutándose en la sesión del usuario en ambas computadoras, puede serializar los datos del tablero en un archivo, transferirlo a través de SSH, leerlo desde su aplicación en el lado remoto y luego colocar los datos del tablero. El tablero remoto. Sin embargo, obtener la serialización correcta del cartón puede ser complicado y no estoy seguro de qué tan portátiles son los datos del cartón entre sistemas operativos y arquitecturas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top