2009-08-03 6 views
1

Nous avons l'extrait suivant.Est-il possible d'accéder à la table de montage Mac OS X lors de la connexion via SSH?

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

Ceci compile bien, cependant, il échoue à s'exécuter lorsqu'il est appelé à partir de SSH. C'est parce qu'il n'y a pas de table de montage disponible dans le terminal SSH. Cependant, l'idée ici est de partager des planchettes entre les ordinateurs.

Exécuté à partir du terminal de bureau, cela fonctionne très bien. Mais lorsqu'il est exécuté à partir de SSH, PasteboardCreate renvoie -4960 (aka, coreFoundationUnknownErr). Je suppose que le seul moyen de contourner ce problème est d'exécuter l'application à partir du même environnement que le carton, mais est-ce possible?

Répondre

3

Accès à la table de montage donne directement être un no-go. Tout d'abord, launchd won't register the processes1 avec le port mach du serveur. Vous devez d'abord trouver un moyen d'obtenir le port mach du serveur de la table de montage (mach_port_names?). En outre, la communication directe entre les sessions utilisateur est prohibited2 et les autres communications sont limitées. Je ne suis pas sûr si votre programme aura les droits de se connecter au serveur de carton.

Voici un premier exemple d'utilisation d'événements Apple pour obtenir & en tant que chaîne de caractères. La gestion des erreurs est minime ou inexistante (je ne suis pas certain de ce que je ressens à propos de require_noerr). Si vous souhaitez obtenir/définir des données de Presse-papiers plusieurs fois au cours d'une exécution, vous pouvez enregistrer les événements Apple et, lors de la copie dans le Presse-papiers, utiliser AECreateDesc & AEPutParamDesc ou (peut-être) AEBuildParameters. AEVTBuilder pourrait être utile.

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

Je quitte Core Foundation approche ci-dessus, mais vous voudrez probablement utiliser NSAppleEventDescriptor pour extraire le contenu du presse-papiers de l'Apple réponse de l'événement.

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 est également plus facile d'examiner dans un débogueur qu'un AEDesc. Pour examiner les réponses, vous pouvez également définir la variable d'environnement AEDebugReceives lors de l'utilisation d'osascript ou de Script Editor.app:

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

Références:

  1. "Configuring User Sessions"
  2. "Communicating Across Login Sessions"
  3. Mach Kernel Interface, en particulier:
  4. CFMessagePort Reference (mach enveloppe de port):
  5. Apple Events Programming Guide
  6. Apple Event Manager Reference
  7. AEBuild*, AEPrint* and Friends
  8. AEBuildAppleEvent sur CocoaDev
  9. Mac OS X Debugging Magic (pour AEDebugSends et autres AeDebug * variables d'environnement)
+0

N'avez pas encore essayé, mais il semble que la réponse la plus correcte - je préfère que la prime est allé à cette réponse plutôt que la sélection automatique. –

+0

Notez que cette approche doit prendre en charge les types autres que le texte.Vous pouvez utiliser 'AEPrintDescToHandle' après avoir obtenu quelque chose du presse-papiers pour examiner sa structure. 'NSAppleEventDescriptor' peut rendre les résultats d'analyse plus faciles. – outis

3

Je l'ai essayé de faire en AppleScript, et cela a fonctionné (même lorsqu'elle est invoquée via SSH). Mon script est la suivante:

#!/usr/bin/osascript 

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

Ceci est certainement pas une solution idéale, mais peut-être si vous avez travaillé comment AppleScript il fait alors cela vous aider à mettre en œuvre vous-même.

+0

Ah, bien. Cela pourrait valoir le coup d'oeil. –

+0

AppleScript utilise Apple Events. Ils sont en désordre et une partie de la documentation est mauvaise. – outis

1

Jetez un oeil à pbpaste (en obtenant le contenu du presse-papiers) et pbcopy (copier le contenu dans le presse-papiers). Fonctionne bien, également sur SSH. :)

Sous Mac OS X Snow Leopard:

pbcopy Mac http://www.hillrippers.ch/temp/pbcopy.png

sur Ubuntu 9.04:

pbpaste Ubuntu http://www.hillrippers.ch/temp/pbpaste.png

+0

Ils semblent avoir le même problème. Peut-être que tout ce qui n'est pas un descendant de WindowServer n'est pas considéré comme faisant partie d'une session de connexion et n'a donc pas accès au serveur de la table de montage, mais c'est une conjecture. Besoin de plus de recherche. – outis

+0

Hmmm, ça marche quand j'utilise SSH pour me connecter de ma machine Linux à mon Mac, donne le même résultat que lorsque je regarde mon Presse-papiers ou que j'utilise 'pbpaste' localement. Dans quel scénario avez-vous constaté que cela ne fonctionne pas? – Pascal

+0

'pbpaste' ne fonctionne pas lorsque je me connecte via SSH à mon Mac depuis n'importe où (boîte BSD, Windows, même' ssh localhost'). En cours d'exécution OS X 10.4.11 et OpenSSH 5.1p1. Hmmm .... devrait peut-être se pencher sur la mise à niveau. – outis

0

Vous pouvez accéder à la table de montage avec PasteboardCreate via SSH sur SnowLeopard mais pas sur Leopard ou Tiger.

Vous ne souhaitez probablement pas utiliser pbcopy et pbpaste pour une synchronisation de la table de montage complète, car ceux-ci ne traitent que du texte brut, RTF et EPS. Si, par exemple, vous copiez une image, puis essayez de l'écrire avec pbpaste, vous n'obtiendrez aucune sortie. En supposant qu'une application s'exécute dans la session de l'utilisateur sur les deux ordinateurs, vous pouvez sérialiser les données de la table de montage dans un fichier, les transférer sur SSH, les lire depuis votre application sur le côté distant, puis mettre les données du sur le carton à distance. Cependant, obtenir la sérialisation de la table de montage peut être difficile et je ne suis pas sûr de savoir comment les données de la table de montage sont entre les systèmes d'exploitation et les architectures.

+0

Sérialiser le carton ressemble à la solution la plus sûre pour moi. 'pbpaste' est correct pour le texte, si vous avez seulement besoin de synchroniser le texte, cela pourrait suffire. – Pascal

Questions connexes