直接访问粘贴板看起来是不行的。首先,launchd不会使用粘贴板服务器的 mach 端口注册进程1 。您首先需要找到一种方法来获取粘贴板服务器的 mach 端口(mach_port_names
?)。此外,禁止用户会话之间的直接通信2,并且限制其他通信。我不确定您的程序是否有权连接到粘贴板服务器。
这是使用 Apple 事件获取剪贴板并将剪贴板设置为字符串的说明性示例的第一个镜头。错误处理很少甚至不存在(我不确定我的感受require_noerr
)。如果您要在运行期间多次获取/设置剪贴板数据,您可以保存 Apple 事件,并在复制到剪贴板时使用AECreateDesc
&AEPutParamDesc
或 (maybe) 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,
©, &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(©, &reply, kAENoReply, kAEDefaultTimeout);
AEDisposeDesc(&reply);
AEDisposeDesc(©);
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;
}
AnNSAppleEventDescriptor
在调试器中也比 . 更容易检查AEDesc
。要检查回复,您还可以AEDebugReceives
在使用 osascript 或 Script Editor.app 时设置环境变量:
AEDebugReceives=1 osascript -e 'tell application "Finder" to get the clipboard'
参考:
- “配置用户会话”
- “跨登录会话进行通信”
- Mach 内核接口,尤其是:
- CFMessagePort 参考(mach 端口包装器):
- Apple 事件编程指南
- Apple 事件管理器参考
- AEBuild*、AEPrint* 和朋友
- CocoaDev上的 AEBuildAppleEvent
- Mac OS X Debugging Magic(用于 AEDebugSends 和其他 AEDebug* 环境变量)