-
Move and click the mouse via code使用代码移动和点击鼠标
2008-07-09 19:53:45
Most OS X apps can have their interface elements accessed by AppleScript, and so anything can be scripted. Unfortunately, not all apps use an Aqua interface, especially games with game-engine-rendered interface elements. This means AppleScript. can't find buttons, etc., to click on, and you're out of luck trying to automate actions.
Recently, I was given the unpleasant task of automating actions in such unfriendly apps. I just about went crazy trying to find a way to write a simple script. with coordinates for mouse click events.There's nothing available within AppleScript. for pushing the mouse around, and I couldn't find any command-line utilities either. Out of necessity, I wrote my own.
This is my first time writing anything that even resembles Cocoa, and my first time writing code that compiles in nearly 10 years. I'm a scripting guy, and I just wanted to be able to write a script. What I wrote is a little command-line app called click that invokes CGPostMouseEvent from the CGRemoteOperation.h header file. It takes coordinates as command line arguments, moves the mouse to that position, then clicks and releases the mouse button. I think this could even be modified to click, hold, and drag, but I haven't taken it that far because I don't need to. Here's the source: Save the above code as click.m, open Terminal, and switch to the folder where you saved the source. Then compile the program by typing gcc -o click click.m -framework ApplicationServices -framework Foundation. Don't be intimidated by needing to compile this as there are more comments than code. It is a very short program that does one simple task.
I'm sure I'm not the only one out there who needs to script. mouse events, so hopefully this will brighten somebody's day. The only gotcha here is that scripts that invoke this will likely break if they are then used on a machine with a different screen size. Such is life when scripting the unscriptable.
[robg adds: You'll need Xcode installed to compile this code, but I've already done that, so here's a pre-built binary for those who want the program but don't have Xcode. Usage is as noted in the comments in the code: click -x 100 -y 200 would move the mouse horizontally 100 pixels and vertically 200 pixels, and then send a mouse click event. I tested it, and it works as described. -
Create aliases to icons via a Perl script用脚本获得系统里的icon
2008-07-09 18:48:37
以下是代码
存储为findOSXicons,在执行chmod 755 findOSXicons把它转换可执行
By default, this script. will copy a link (kind of an alias) to each and every icon in the system into a folder on the desktop in a nice hierarchy.
Each icon belonging to an Application will be linked from a folder:
Desktop » OSX-Icons » Applications » application_name » icon_name
Each icon not belonging to an application wil be linked from a folder:
Desktop » OSX-Icons » letter » iconname
where letter is the first character of the icon's name. But you can do more with it! Instead of just starting findOSXicons from the Terminal, you can also tell it to:- search for other file extensions
- store the results elsewhere
- don't search the whole system
用以下代码看帮助
Just enter findOSXicons -help or findOSXicons -man for instructions.看到统计列表才执行结束
All icons known: 5952
Application icons: 2747
Non-application icons: 3205New icons found: 5952
Application icons: 2747
Non-application icons: 3205Old icons: 0
Application icons: 0
Non-application icons: 0Icons removed since last run: none
logout -
在Dock中加入应用程序快捷图标的方法和当前应用程序列表
2008-07-09 14:32:33
在terminal中输入如下代码,
~ defaults write com.apple.dock persistent-apps -array-add "<dict><key>tile-data</key><dict><key>file-data</key><dict><key>_CFURLString</key><string>/Applications/Calculator.app/</string><key>_CFURLStringType</key><integer>0</integer></dict></dict></dict>"
红色部分是要添加的应用程序
~ killall Dock
重启Dock~ defaults write com.apple.dock persistent-others -array-add '{ "tile-data" = { "list-type" = 1; }; "tile-type" = "recents-tile"; }'
在Dock中添加当前应用程序列表The com.apple.dock.plist can only be written via the user (ie. $USER). So even when you use 'sudo' you are still trying to write as ROOT. I fixed this with the following 2 changes:
1. Use 'sudo -u $USER' to write your changes as the user
2. Use the direct path '$HOME/Library/Preferences/com.apple.dock' to ensure that you are writing to the correct plist.
-
MAC process list
2008-06-02 13:29:04
http://developer.apple.com/qa/qa2001/qa1123.html
- (NSDictionary *) getProcessList {
NSMutableDictionary *ProcList = [[NSMutableDictionary alloc] init];
kinfo_proc *mylist;
size_t mycount = 0;
mylist = (kinfo_proc *)malloc(sizeof(kinfo_proc));
GetBSDProcessList(&mylist, &mycount);
//printf("There are %d processes.\n", (int)mycount);
int k;
for(k = 0; k < mycount; k++) {
kinfo_proc *proc = NULL;
proc = &mylist[k];
NSString *processName = [NSString stringWithFormat: @"%s",proc->kp_proc.p_comm];[ ProcList setObject: processName forKey: processName ];
// [ ProcList setObject: proc->kp_proc.p_pid forKey: processName
];
printf("ID: %d - NAME: %s\n", proc->kp_proc.p_pid, proc->kp_proc.p_comm);}
free(mylist);
return [ProcList autorelease];
}
static int GetBSDProcessList(kinfo_proc **procList, size_t *procCount)
// Returns a list of all BSD processes on the system. This routine
// allocates the list and puts it in *procList and a count of the
// number of entries in *procCount. You are responsible for freeing
// this list (use "free" from System framework).
// On success, the function returns 0.
// On error, the function returns a BSD errno value.
{
int err;
kinfo_proc * result;
bool done;
static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0
};
// Declaring name as const requires us to cast it when passing it to
// sysctl because the prototype doesn't include the const modifier.
size_t length;assert( procList != NULL);
// assert(*procList == NULL);
assert(procCount != NULL);*procCount = 0;
// We start by calling sysctl with result == NULL and length == 0.
// That will succeed, and set length to the appropriate length.
// We then allocate a buffer of that size and call sysctl again
// with that buffer. If that succeeds, we're done. If that fails
// with ENOMEM, we have to throw away our buffer and loop. Note
// that the loop causes use to call sysctl with NULL again; this
// is necessary because the ENOMEM failure case sets length to
// the amount of data returned, not the amount of data that
// could have been returned.result = NULL;
done = false;
do {
assert(result == NULL);// Call sysctl with a NULL buffer.
length = 0;
err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
NULL, &length,
NULL, 0);
if (err == -1) {
err = errno;
}// Allocate an appropriately sized buffer based on the results
// from the previous call.if (err == 0) {
result = malloc(length);
if (result == NULL) {
err = ENOMEM;
}
}// Call sysctl again with the new buffer. If we get an ENOMEM
// error, toss away our buffer and start again.if (err == 0) {
err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) -
1,
result, &length,
NULL, 0);
if (err == -1) {
err = errno;
}
if (err == 0) {
done = true;
} else if (err == ENOMEM) {
assert(result != NULL);
free(result);
result = NULL;
err = 0;
}
}
} while (err == 0 && ! done);// Clean up and establish post conditions.
if (err != 0 && result != NULL) {
free(result);
result = NULL;
}
*procList = result;
if (err == 0) {
*procCount = length / sizeof(kinfo_proc);
}assert( (err == 0) == (*procList != NULL) );
return err;
} -
Mac OS线程开发包介绍
2008-03-28 09:01:08
Mac OS线程开发包介绍
Mac OS X提供了到几套API用于创建程序级别的线程。从行为上来看,这些API创建的线程的本质是一样的。
你可以根据你的程序(Carbon, Cocoa, Darwin)选择一套API函数, 同时也要考虑它的性能和复杂度。
举个例子,Cocoa线程使用比较简单,但是它比POSIX线程少了一些弹性和性能。
在接下来的文章我将给你介绍这些不同的线程API,比较每种实现的优点和缺点。所有的线程(除了注明)都是根据当前运行的状态和优先级抢先式运行。
注意:在下面的文章中,线程的介绍从实现的级别由低到高的方式介绍,展示了每层上线程的实现是如何建立在上一层的技术之上。这个顺序并不能作为你应用程序使用的建议指导。你选择必须是根据当前的具体功能和性能要求作出分析。
分类:
Mach Threads
POSIX Threads
Cocoa Threads
Carbon Multiprocessing Services
Carbon Thread ManagerMach Threads
Mach threads (有时候指内核线程)提供了系统级别的线程的实现方法。所有其它的线程函数都是建立在Mach线程之上。应用程序开发者很少需要直接使用Mach线程。Mach线程一般用于内核级别程序的开发,像内核的扩展程序。应用程序如果需要调用的线程的话,应该是使用POSIX或其它更高层次的API。
注意: 虽然I/O Kit运行在内核级别,但是它们没有直接使用Mach线程,相反,I/O Kit 定义自己的类和函数来实现线程。如想了解更多的信息,请参照Device Drivers (Kernel/IOKit) Reference.
一个POSIX 线程(通常指一个“pthread”)是一个基于Mach线程封装的较量级的API,它提供了用户级别的处理。POSIX线程是所有应用程序级别线程的基础,包括Cocoa线程, Carbon线程, POSIX线程是基于C语言的API函数,提供了全面的创建控制和信息读取的功能。全面也意味着你的程序必须比其它线程API需要更多的设置和管理。(举个例子,不像其它的线程包,一个POSIX线程是不会自动同程序的主线程发生联系。) 因为程序对于线程的行为需要更多的控制,可是,POSIX 线程比其它API提供了更高的性能。
另一个好处就是POSIX 线程API已经在多个平台上实现,因此,你用POSIX 线程实现的代码能够运行在大多数的Unix和Windows操作系统。
如想了解更多的信息,请参照pthread主页。
Cocoa threads (用NSThread类实现)提供了一个创建和管理线程的高级类。NSThread内部是采用POSIX线程来实现,但是NSThread也提供了更多自动管理POSIX线程的数据和行为的能力。它同时也会派发Cocoa通知消息给应用程序,通知应用程序当前的线程状态。
这个NSThread类应该在Cocoa应用程序或其它使用Foundation framework的程序优先使用。NSThread对象的性能非常好,虽然一些额外的开销使得它比POSIX线程慢。但在大部分的情况下,这些开销是可以忽略不计的。
更多关于创建Cocoa线程和使用NSThread类,请参照“Creating Threads in Cocoa”。
在Carbon 应用程序中,Carbon Multiprocessing Services 是作为抢先式线程的管理API。这个模型是建立在Mac OS 9的MP Task API之上,创建MP Task API只是 Carbon线程管理的折中模型。使用Multiprocessing Services API,一个应用程序可以在多处理机器上运行抢先式的线程,同时具有并行运行能力。
对于Carbon应用程序,Multiprocessing Services是创建线程的首选。这些API创建抢先式线程与POSIX线程和NSThread类是差不多的。而且,这个API也提供了一些更强的功能,如线程的同步,通知,定时,远程调用,异常处理,semaphores和临界标记。
更多关于使用Multiprocessing Services API信息,请参照Multiprocessing Services Programming Guide. 和 Multiprocessing Services Reference。
Carbon Thread Manager是一个历史遗留的API,主要作用是为了Carbon应用程序管理一系列辅助线程。不像抢先式线程,这里的每个线程的运行依赖与其它线程,指定的时间内只有一个应用程序的辅助线程可以在运行。线程由一个叫round-robin manner选择,当它们收到内核的通知运行的时候,你可以把这些辅助线程看成是一个组。收到内核通知的时候这个组中只能有一个被激活的线程可以运行,其它线程进入休眠状态一直要等到运行线程进入到休眠。
注意: 我们不建议现在还用Carbon线程管理来进行线程开发。这些API只要为了那些把他们的应用程序转到Mac OS X,同时那些代码还需要辅助线程。假如你现在正在写一个新的Carbon应用程序,必须要用POSIX线程或Multiprocessing Services API来替换。
-
cocoa 启动其他应用的方法
2008-01-31 09:55:16
NSWorkspace *workspacce = [NSWorkspace sharedWorkspace];
NSString * appPath = [[workspacce activeApplication] objectForKey:@"NSApplicationPath"];
NSLog(@"%@", appPath);
appPath = [appPath stringByDeletingLastPathComponent];
appPath = [appPath stringByAppendingPathComponent:@"/CSVEdit.app"];
[workspacce launchApplication:appPath]; -
Accessing Other AppsDefaults
2008-01-28 11:15:54
Well, it does...just not in a nice, neat format yet (see below). You can take your pick without worrying, though; Apple says that you can even mix CFPreferences and NSUserDefaults without harm. Also, you don't have to include the whole Carbon framework for this, just CoreFoundation (which may even already be included in the Cocoa framework).
NSDictionary *safariPrefs = [[NSUserDefaults standardUserDefaults] persistentDomainForName:@"com.apple.Safari"];
BOOL tabbedBrowsingEnabled = [safariPrefs objectForKey:@"TabbedBrowsing"];
// ...
// If you want to set something, you have to do it like this, unfortunately,
// instead of modifying a specific value
[[NSUserDefaults standardUserDefaults] setPersistentDomain:safariPrefs forName:@"com.apple.Safari"];浏览方法
NSString *s;
NSEnumerator *e = [myDict keyEnumerator];
while (s = [e nextObject]) {
NSLog(@"key is %@, value is %@", s, [myDict objectForKey:s]);
}

