about 1 month ago - 2 comments
之前为了注册一个自定义协议,需要通过注册 AppleEvent 来实现,在 Objective-C 中,可以很方便的使用 NSAppleEventManager 来注册 AppleEvent 句柄,但是在 REALbaisc 中,是没有办法直接去调用 NSAppleEventManager 的,所以需要通过声明然后调用 C API 来实现相应的功能。
与 NSAppleEventManager 中功能相对应的 C API 有 AEInstallEventHandler, NewAEEventHandlerUPP 等,通过这些 API 我们也可以在 REALbasic 中来注册 AppleEvent 了,再配合 Info.plist 中的 URLScheme 声明,即可实现 URL 自定义协议处理句柄。
#if TargetCarbon
soft declare function AEInstallEventHandler Lib CarbonLib ( _
theAEEventClass as Integer, _
More >
about 3 months ago - No comments
在之前,我使用 ShellExecute 这个 API 来执行命令(《REALbasic 中使用 ShellExecute 执行命令》),然后通过这个方法来停止某个服务,但是今天想加服务运行状态检测,这样就可以在服务没有运行的情况下不再询问用户是否需要停止某个服务。
为了省事,我一开始决定同样使用 cmd 去执行一个命令,将服务状态输出到一个临时文件中,再通过读取这个临时文件,查找特征字符串来判断服务是否运行:
// 伪代码
ShellExecute("cmd.exe /c sc query service_name > tmpfile")
dim serviceStatus as string
serviceStatus = TextInputStream.Open(tmpfile).ReadAll()
if instr(serviceStatus, "STOPPED") < 1 then
// 提示用户是否停止服务
end if
但是这样做不太靠谱,因为 sc 这个命令执行是要时间的,而 ShellExecute 是异步的,这就导致了在调用 ShellExecute 执行完 sc query 之后,临时文件 tmpfile 里并不是马上就有服务状态的内容了。
为了防止这个情况,我再加了一个临时文件内容的检测,如果为空的话,sleep 100ms,再继续读取,如果超过 10 次仍没有内容,直接当作服务正在运行来对待。
// 伪代码
ShellExecute("cmd.exe /c sc query service_name > tmpfile")
dim serviceStatus as string
dim More >
about 4 months ago - No comments
为了随时更新到 Chromium 的最新 nightly build,又不想每次去 Chromium 的网站下,还有解压,移动,麻烦……为了省事,直接用 REALbasic 写了一个 Chromium Updater,专门用来更新 Chromium。目前只支持 Mac :)
详细说明
下载(使用右键下载):ChromiumUpdater (3.5M)
about 4 months ago - No comments
在 REALbasic 中,如果需要执行 cmd 命令,可以直接使用 Shell 类,但是这样的话,编译成 Windows 程序时会额外需要一个 Shell.dll 的动态链接库,这对于我这样的 1exe 爱好者是不能忍受的。但是对于 Mac OS X 和 Linux 的生成目标来说,是不存在这个问题的,因为 Mac OS X 的应用程序本身就是一个文件夹,而 Linux 的目标不会生成额外的链接库。因此,需要针对 Windows 进行特殊处理。于是在网上搜索解决方案,找到了 VB 中执行程序的几种方法:
1. 使用 CreateProcess
通过 CreateProcess 以及使用管道,可以执行外部程序并获取输出,但是这个方法过于烦琐,并且我也不需要外部进程执行完毕后的输出结果,因此不采用。
2. 使用 Shell 方法
VB 里有一个 Shell 方法,但是在 RB 中并没有,所以此路不通。
3. 使用 ShellExecute
这个方法同样是一个系统 API,可以直接通过 RB 的 declare 声明并调用它,在测试之后,使用 declare 来使用系统 API 不会生成额外的 dll,正是我需要的。
首先在 RB 的某个模块中添加一个方法 ShellExecute,用来封装对系统 API 的请求:
function ShellExecute(hWnd as Integer, lpOperation as String, _
lpFile as String, lpParameters as String, lpDirectory as String, nShowCmd as Integer)
注意,在 RB 中添加方法时,参数列表中的 _ 需要去掉,这里是为了排版的需要而加上的。
这个 API 是定义在 shell32.dll 中的,在 ShellExecute 方法中先需要声明:
soft declare function ShellExecuteA Lib ”shell32.dll” _
(ByVal hWnd As Integer, ByVal lpOperation As CString, _
ByVal lpFile As CString, ByVal lpParameters As CString, _
ByVal lpDirectory As CString, ByVal nShowCmd As Integer) As Integer
soft declare function ShellExecuteW Lib ”shell32.dll” _
(ByVal hWnd As Integer, ByVal lpOperation As CString, _
ByVal lpFile As CString, ByVal lpParameters As CString, _
ByVal lpDirectory As CString, ByVal nShowCmd As Integer) As Integer
然后来调用这个 API:
dim ret as Integer
Try
ret = ShellExecuteW(hWnd, ConvertEncoding(lpOperation, Encodings.UTF16), _
ConvertEncoding(lpFile, Encodings.UTF16), _
ConvertEncoding(lpParameters, Encodings.UTF16), _
ConvertEncoding(lpDirectory, Encodings.UTF16), nShowCmd)
Catch
More >