Ruby和微軟的Windows
Ruby 的實(shí)現(xiàn)是基于 POSIX環(huán)境的,也就是說(shuō)它可以利用unix程序員熟悉的所有的系統(tǒng)調(diào)用和系統(tǒng)庫(kù)。
同時(shí),系統(tǒng)設(shè)計(jì)的時(shí)候擴(kuò)展了對(duì)windows的支持,這章,我們將看看這方面的特性,并展示一些在windows下高效使用ruby的秘訣。
Ruby Ports
Windows does not provide a POSIX environment by itself, so some sort of emulation library is required in order to provide the necessary functions. There are several ports of Ruby for Windows: the most commonly used one relies on the GNU Win32 environment, and is called the ``cygwin32'' port. The cygwin32 port works well with extension libraries, and is available on the Web as a precompiled binary. Another port, ``mswin32,'' does not rely on cygwin. It is currently available as source code only. The remainder of this chapter will refer to the cygwin32 port.
在 Windows下運(yùn)行Ruby
cygwin32版本的ruby發(fā)布包括兩個(gè)可執(zhí)行文件:ruby.exe
,rubyw.exe
ruby.exe
用在命令提示符下(dos shell),就像unix版本中的一樣。對(duì)于需要從標(biāo)準(zhǔn)輸入輸出進(jìn)行讀寫(xiě)操作的應(yīng)用來(lái)說(shuō)比較適合,但是這樣的話我們運(yùn)行什么程序都需要額外多開(kāi)了一個(gè)窗口,而不管我們需不需要這個(gè)窗口,有時(shí)候這樣就顯得不合適了,比如我們雙擊一個(gè)ruby腳本運(yùn)行一個(gè)圖形接口(比如Tk),或者作為后臺(tái)程序運(yùn)行,或者在別的程序中被調(diào)用。
在這種情況下,我們可以用
rubyw.exe
,他和
ruby.exe
一樣,但是不提供標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出,或者標(biāo)準(zhǔn)錯(cuò)誤,并且不會(huì)打開(kāi)一個(gè)dos shell的窗口。
可以對(duì)ruby腳本(.rb結(jié)尾的文件)設(shè)定文件關(guān)聯(lián)[在用菜單 查看/選項(xiàng)/文件類型
],然后雙擊這個(gè)文件就可以調(diào)用rubyw.exe
來(lái)執(zhí)行這個(gè)程序了。
Win32API
如果你的ruby程序打算直接訪問(wèn)win32api,或者用一些DLL的入口點(diǎn),你將會(huì)用到
Win32API
擴(kuò)展。
你可以用要訪問(wèn)的DLL名字創(chuàng)建一個(gè)
Win32API
對(duì)象,表示對(duì)一個(gè)指定的DLL的入口點(diǎn)的調(diào)用,DLL的名字包括函數(shù),函數(shù)簽名(參數(shù)和返回值),建立的win32api對(duì)象就可以用來(lái)對(duì)指定的dll進(jìn)行調(diào)用。
DLL的很多參數(shù)都是一定形式的二進(jìn)制結(jié)構(gòu),
Win32API
用ruby的字符串對(duì)象處理這些參數(shù),進(jìn)行來(lái)回的傳遞。你需要對(duì)這些字符串進(jìn)行打包和解包(pack and unpack)
Windows Automation
如果你對(duì)使用低層次的windows API調(diào)用不感興趣,你可以使用windows utomation,ruby可以當(dāng)成Windows Automation 的客戶。感謝 Masaki Suketa寫(xiě)的 win32OLE擴(kuò)展。下面例子是WIN32OLE發(fā)布包中提供的。
Windows 自動(dòng)化允許自動(dòng)化控制器(客戶端)向自動(dòng)化服務(wù)器(Excel, Word, PowerPoint等)發(fā)送一個(gè)命令或者進(jìn)行查詢。
你可以向
WIN32OLE
發(fā)送一個(gè)命令,從而可以執(zhí)行自動(dòng)化服務(wù)器上具有相同名字的方法。例如,你可以創(chuàng)建一個(gè)
WIN32OLE
客戶,創(chuàng)建幾個(gè)全新的IE瀏覽器,并且顯示ie設(shè)置的主頁(yè):
ie?=?WIN32OLE.new('InternetExplorer.Application')
ie.visible?=?true
ie.gohome
|
WIN32OLE
并不知道這些方法(比如visible
和gohome
),它會(huì)把這些向它調(diào)用的方法傳到WIN32OLE#invoke
,在這個(gè)方法里向自動(dòng)化服務(wù)器發(fā)送正確的命令。
讀、寫(xiě)自動(dòng)化服務(wù)器的屬性
你可以用通常的哈希表示方法從自動(dòng)化服務(wù)器讀寫(xiě)服務(wù)器的屬性。比如,可以如下面一樣設(shè)定一個(gè)Excel chart的
Rotation
的值:
excel?=?WIN32OLE.new("excel.application")
excelchart?=?excel.Charts.Add()
...
excelchart['Rotation']?=?45
puts?excelchart['Rotation']
|
OLE對(duì)象的參數(shù)自動(dòng)都會(huì)被設(shè)成屬性,也就是說(shuō)你可以你可以通過(guò)給一個(gè)屬性賦值而設(shè)定一個(gè)參數(shù)。
excelchart.rotation?=?45
r?=?excelchart.rotation
|
因?yàn)檫@些屬性是常規(guī)的ruby訪問(wèn)方法,而屬性名不能以大寫(xiě)字母開(kāi)頭,所以你要用
rotation
而不是
Rotation
。
命名參數(shù)(Named Arguments)
其他的能實(shí)現(xiàn)自動(dòng)化客戶端的語(yǔ)言,比如VB,有一種叫做命名參數(shù)(named arguments)的概念,假設(shè)我們有這樣的一個(gè)VB方法:
Song(artist,?title,?length):????rem?Visual?Basic
|
要想調(diào)用這個(gè)方法,除了按順序?qū)懭@三個(gè)參數(shù)來(lái)調(diào)用之外,我們可以用命名參數(shù)的方法:
Song?title?:=?'Get?It?On':??????rem?Visual?Basic
|
這等同于
調(diào)用 Song(nil, 'Get It On', nil)
。
在Ruby中,可以在調(diào)用的時(shí)候用哈希結(jié)構(gòu)來(lái)指定參數(shù)名和它的值,比如:
Song.new(?'title'?=>?'Get?It?On'?)
|
for each方法
VB有一個(gè)方法 ``for each''語(yǔ)句,可以在服務(wù)端對(duì)一個(gè)集合進(jìn)行迭代,
WIN32OLE
對(duì)象也有一個(gè)方法完成相同的作用。
一個(gè)例子
下面這個(gè)例子,用到了微軟的Excel,覆蓋了上面說(shuō)的很多概念。首先,我們創(chuàng)建了一個(gè)新的基于Excel的WIN32OLE
對(duì)象,并增加了一些單元格,并給這些單元格賦值。然后,我們選中了一個(gè)區(qū)域,并創(chuàng)建了圖表(chart),我們通過(guò)給這個(gè)圖表的type屬性賦值,使它成為一個(gè)3D的圖表。然后,
The following example, using Microsoft Excel, illustrates most of these concepts. First, we create a new object attached to Excel and set some cell values. Next we select a range of cells and create a . We set the
Type
property in the
excelchart
object to make it a 3D chart. Next we'll loop through and change the chart rotation, 10?at a time. We'll add a few charts, and we'll use
each
to step through and print them out. Finally, we'll close down the Excel application and exit.
require?'win32ole'
#?-4100?is?the?value?for?the?Excel?constant?xl3DColumn.
ChartTypeVal?=?-4100;
#?Creates?OLE?object?to?Excel
excel?=?WIN32OLE.new("excel.application")
#?Create?and?rotate?the?chart
excel['Visible']?=?TRUE;
workbook?=?excel.Workbooks.Add();
excel.Range("a1")['Value']?=?3;
excel.Range("a2")['Value']?=?2;
excel.Range("a3")['Value']?=?1;
excel.Range("a1:a3").Select();
excelchart?=?workbook.Charts.Add();
excelchart['Type']?=?ChartTypeVal;
30.step(180,?10)?do?|rot|
????excelchart['Rotation']?=?rot
end
excelchart2?=?workbook.Charts.Add();
excelchart3?=?workbook.Charts.Add();
charts?=?workbook.Charts
charts.each?{?|i|?puts?i?}
excel.ActiveWorkbook.Close(0);
excel.Quit();
|
優(yōu)化
As with most (if not all) high-level languages, it can be all too easy to churn out code that is unbearably slow, but that can be easily fixed with a little thought.
對(duì)
WIN32OLE
來(lái)說(shuō), 我們要避免不必要的動(dòng)態(tài)查找(dynamic lookups)。如果可能,盡量把
WIN32OLE
對(duì)象 賦給一個(gè)變量,然后引用這個(gè)變量的元素,而不要使用一大串的"." 構(gòu)成的表達(dá)式。
比如,我們不應(yīng)該寫(xiě)出這樣的代碼:
workbook.Worksheets(1).Range("A1").value?=?1
workbook.Worksheets(1).Range("A2").value?=?2
workbook.Worksheets(1).Range("A3").value?=?4
workbook.Worksheets(1).Range("A4").value?=?8
|
我們可以通過(guò)把這些語(yǔ)句的前面部分放到一個(gè)臨時(shí)變量里,而使用臨時(shí)變量來(lái)執(zhí)行方法。
worksheet?=?workbook.Worksheets(1)
worksheet.Range("A1").value?=?1
worksheet.Range("A2").value?=?2
worksheet.Range("A3").value?=?4
worksheet.Range("A4").value?=?8
|
Extracted from the book "Programming Ruby - The Pragmatic Programmer's Guide" Copyright ? 2001 by Addison Wesley Longman, Inc. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub/)).
Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder.
Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.