16. 系統登錄

在 32位元的Windows 95和Windows NT作業系統中,應用程式執行時所需要的初始化資料檔(INI檔),現在已被登錄(Registry)所取代,什麼是登錄呢﹖登錄是一個系統資料庫,它記載了所有32位元應用程式前一次執行結束時的狀態,最典型的狀態資訊包括顏色、字形、視窗位置...... 等。從應用INI檔的經驗移轉到使用登錄並不困難,因為Visual Basic提供了相當豐富的相關函式,這些函式簡化了讀寫登錄的工作。本章的重點就在介紹討論這些函式。

如何讀寫登錄中的資料?
 

Visual Basic對於讀寫登錄中的資料提供了四個函式:GetSetting、SaveSetting、DeleteSetting和GetAllSettings,依筆者個人的意見,前面三個函式當屬最重要的函式。

正如同這些函式名稱所代表的意義,它們可以讀、寫以及刪除系統登錄的設定值。GetAllSettings是一個較特殊的函式,它讓你從登錄中的某一個區段(section)一次讀取所有的設定資料,這是GetSetting函式的延伸,因此我們讓你自行從線上說明中作進一步的研究,在本章中我們不作討論。

為了要介紹前面三個函式,我們建立了一個Registry物件類別以及一個測試用的程式,以便操作系統登錄設定的讀寫動作。

我們的Registry物件有四個屬性和三個物件方法,屬性Appname、Section、Key和Setting是為了配合讀寫系統登錄設定值的函式而設計的,以下就是這些屬性和方法的詳細內容:

`REGISTRY.CLS
Option Explicit

Private mstrAppname As String
Private mstrSection As String
Private mstrKey As String
Private mstrSetting As String

`~~~AppName
Public Property Get Appname() As String
    Appname = mstrAppname
End Property
Public Property Let Appname(ByVal strAppName As String)
    mstrAppname = strAppName
End Property

`~~~Section
Public Property Get Section() As String
    Section = mstrSection
End Property
Public Property Let Section(ByVal strSection As String)
    mstrSection = strSection
End Property

`~~~Key
Public Property Get Key() As String
    Key = mstrKey
End Property

Public Property Let Key(ByVal strKey As String)
    mstrKey = strKey
End Property

`~~~Setting
Public Property Get Setting() As String
    Setting = mstrSetting
End Property
Public Property Let Setting(ByVal strSetting As String)
    mstrSetting = strSetting
End Property

`~~~RegGet
Public Sub RegGet()
    mstrSetting = GetSetting(mstrAppname, mstrSection, mstrKey)
End Sub
 `~~~RegSave
Public Sub RegSave()
    SaveSetting mstrAppname, mstrSection, mstrKey, mstrSetting
End Sub

`~~~RegDel
Public Sub RegDel()
    DeleteSetting mstrAppname, mstrSection, mstrKey
End Sub

如果要測試Registry物件,請建立一個標準執行檔並且加入一個物件類別模組,把物件類別的Name屬性值改為Registry,加入以上的程式碼,然後把物件類別模組存成REGISTRY.CLS。接下來,把表單的Name屬性設定為Registry_Form1,以同樣的名稱將表單存檔。表單中加入兩個文字方塊txtKey和txtSetting;三個指令按鈕cmdSave、cmdGet和cmdDel;以及兩個標籤,如圖16-1。最後,加入以下這段程式碼到表單裡:

Option Explicit

Dim mregTest As New Registry

Private Sub cmdSave_Click()
    mregTest.Key = txtKey.Text
    mregTest.Setting = txtSetting.Text
    mregTest.RegSave
End Sub

Private Sub cmdGet_Click()
    mregTest.Key = txtKey.Text
    mregTest.RegGet
    txtSetting.Text = mregTest.Setting
End Sub

Private Sub cmdDel_Click()
    mregTest.Key = txtKey.Text
    mregTest.RegDel
End Sub

Private Sub Form_Load()
    mregTest.Appname = App.Title
    mregTest.Section = "Testing"
End Sub

圖16-1顯示的是設計階段中的Registry Test表單。


 

 圖16-1 設計階段中的Registry Test表單

在Form_Load事件程序中,我們把測試程式中App物件的Title屬性值指定給regTest物件的Appname屬性,而Section屬性值則是一個由程式直接指定的字串"Testing"。你可以自行改變這樣的設計。

在程式執行時,如果要針對某個數值名稱作內容設定,那麼請在Key文字方塊中鍵入數值名稱,在Setting文字方塊中鍵入設定值,然後點選RegSave按鈕;如果要讀取某個名稱設定值,請在Key文字方塊中鍵入一個已經存在的數值,然後按下RegGet指令按鈕;最後,如果要刪除某個已存在的數值名稱,則在輸入數值名稱之後按下RegDel按鈕。

圖16-2所顯示的是程式執行的情形。


 

 圖16-2 執行階段中的Registry Test表單

在RegGet方法中,我們呼叫GetSetting函式以讀取設定值,GetSetting本來有一個可省略的defaut參數,我們並未使用它。如果你傳了一個字串給這個參數,那麼當GetSetting在系統登錄中找不到指定的值名稱時,這個字串就會被當作搜尋的結果而傳回;如果不指定任何資料給這個參數,那麼函式就會傳回一個空字串。要了解系統登錄在程式執行時被改變的實際的情況,你可以用Windows 95或Windows NT 4.0裡的「登錄編輯程式」(Registry Editor)來觀察。要啟動「登錄編輯程式」,請點選Windows 95工作列的「開始」按鈕,再點選「執行」,在「執行」對話方塊中輸入Regedit,然後按「確定」。如圖16-3所示,Visual Basic的函式所能存取的設定資料是存放在HKEY_CURRENT_USER\Software\VB and VBA Program Settings這個區段中,因此,範例程式所能讀寫的範圍被限制在這裡,不會在它處。在這個區段中,你可以藉由Appname和Section的屬性值找到Key與Setting。在我們的範例中,Appname的屬性值是Registry_Test,而Section的屬性值是Testing。這兩部份會出現在登錄編輯程式左邊顯示區的機碼樹狀結構裡,而在右邊的顯示區中你可以看到Key和Setting的屬性值(分別在「名稱」欄與「資料」欄底下)。在範例程式執行時,我們輸入了三個數值名稱──Apples、Oranges和Peaches。如果你同時執行測試程式和「登錄編輯程式」,那麼當你存入或刪除設定之後,請記得要在「登錄編輯程式」的「檢視」功能表中點選「重新整理」或按下,這樣你才能看到最新的設定值。


 

 圖16-3 「登錄編輯程式」所顯示的系統登錄內容

參考資料:

請參閱 二十九章"圖形" 中的MySaver應用程式以及 三十一章"日期與時間" 的VBClock應用程式,這兩個部份也介紹如何使用系統登錄。


如何保留應用程式的狀態?
 

保留某個應用程式結束執行時的狀態,可以用前一節中Registry物件的RegSave方法,而讀取狀態資料則可以用RegGet方法,但現在的問題:我們該在哪裡呼叫這些方法呢?Form_Unload和Form_Load是最佳場所。採用這樣的設計可以讓表單在被顯示之前,就找到了上次執行結束時表單大小、形狀、位置、顏色以及其他細部的狀態資料;同樣地,在程式結束之前,目前的狀態也可以被一一儲存起來,以供下一次執行時使用。


參考資料:

請參閱前一節為 "如何讀寫登錄中的資料?" 

請參閱 二十九章"圖形" 中的MySaver應用程式以及 三十一章"日期與時間" 的VBClock應用程式,這兩部份介紹如何使用登錄以儲存和回復應用程式的狀態。


如何使應用程式與某個檔案類型相關聯?
 

系統的登錄存放著作業系統處理被觸動事件的相關資訊,有了這些資訊,當桌面上或「檔案總管」中的事件發生時,系統才能採取適當的回應行動。例如,當你連續點選二下桌面上的檔案MYFILE.TXT時,作業系統就會呼叫「記事本」來開啟MYFILE.TXT。這種存在於NOTEPAD.EXE與TXT檔案類型之間的關聯資訊,被存放在系統的登錄裡。

如果想查看屬於某個類型檔案的登錄資料,首先你要透過「登錄編輯程式」找到該種檔案類型。在機碼HKEY_CLASSES_ROOT底下,你可以看到所有的檔案類型,點選你要的檔案類型之後,在主功能的「登錄」的選項中選擇「匯出登錄檔」,叫出「匯出登錄檔」對話方塊,如圖16-4,在匯出登錄檔對話方塊中,先輸入檔案名稱,確定「選擇的子目錄」已被選取,然後按下「儲存檔案」。


 

 圖16-4 匯出系統登錄資料

「匯出登錄檔」命令會產生一個附屬檔名為REG的純文字檔,以下的文字檔內容是合併了二個匯出檔的內容── TXT檔匯出的內容和HEKY_CLASSES_ ROOT中txtfile子目錄匯出的內容──為一個REG檔。(依據系統設定的不同,你得到結果可能和筆者的結果不同)

REGEDIT4

[HKEY_CLASSES_ROOT\.txt]
"Content Type"="text/plain"
@="txtfile"

[HKEY_CLASSES_ROOT\.txt\ShellNew]
"NullFile"=""

[HKEY_CLASSES_ROOT\txtfile]
@="Text Document"
[HKEY_CLASSES_ROOT\txtfile\DefaultIcon]
@="c:\\windows\\SYSTEM\\shell32.dll,-152"

[HKEY_CLASSES_ROOT\txtfile\shell]

[HKEY_CLASSES_ROOT\txtfile\shell\open]

[HKEY_CLASSES_ROOT\txtfile\shell\open\command]
@="c:\\windows\\NOTEPAD.EXE %1"
You can modify the exported Registry file to create your own file type 
associations. For example, the REG file below creates an association 
between the file type MYA and MYAPP.EXE. 

REGEDIT4

[HKEY_CLASSES_ROOT\.mya]
"Content Type"="VBRegSample"
@="MyApp"

[HKEY_CLASSES_ROOT\.mya\ShellNew]
"NullFile"=""

[HKEY_CLASSES_ROOT\MyApp]
@="My File"

[HKEY_CLASSES_ROOT\MyApp\DefaultIcon]
@="c:\\VB6 Workshop\\Samples\\Chapter 16\\MyApp.EXE,0"

[HKEY_CLASSES_ROOT\MyApp\shell]

[HKEY_CLASSES_ROOT\MyApp\shell\open]

[HKEY_CLASSES_ROOT\MyApp\shell\open\command]
@="c:\\VB6 Workshop\\Samples\\Chapter 16\\MyApp.EXE %1"

在方括弧中的項目就是所謂的機碼(Key),登錄資料的結構由登錄機碼所建立;等號右邊的是登錄設定數值,而等號之前若有一個 @ 字元,那麼這表示這是一個預設值。在上例中,檔案類型MYA的第一筆登錄資料告訴系統:關於應用程式的資訊可以用機碼「 HKEY_CLASSES_ROOT\MYApp 」找到。

以下這張表所列的是對一些較重要的機碼所作的描述。

機碼 描述
\Default Icon 其設定值的第一個引數是一個檔名,這個檔案中存放著代表某個檔案類型的圖像;第二個引數則代表該圖像在檔案中的索引值。Visual Basic應用程式似乎只支援顯示第一個圖像(索引值為0)
\Shell\Open\Command 其設定值表示:當使用者開啟某個檔案時, Shell命令列中所應執行的命令,引數%1代表傳入給待執行命令的檔案。
\Shell\Print\Command 其設定值代表:當使用者列印檔案時,命令列中所應執行之命令,引數 %1代表傳入給待執行命令的檔案。

要把登錄資料加入到系統的登錄中,請在Windows 95的「開始」功能中執行Regedit,用REG檔作為引數,此外,你可以添上一個 /s使所有匯入處理的過程不會一一出現在使用者面前,整個完整的命令如下:

RegEdit /s MyApp.Reg

注意:

最好在修改系統的登錄之前,預先作好一份登錄備份以備回復原來的系統設定。


圖16-5顯示的是MYAPP.REG匯入後的.mya和MyApp機碼分支。

擷取命令列的引數
 

現在你已經了解了如何把應用程式的開啟、列印以其他命令放在登錄中,接著讓我們看看如何用Visual Basic的Command函式來擷取Shell命令列中的引數,請看以下的程式:


 

 圖16-5 MYAPP.REG匯入後的系統登錄
Dim mstrFile As String

Private Sub Form_Load()
    `Get command line argument
    mstrFile = Command()
    `If there was an argument, do something
    If Len(mstrFile) Then
        OpenFile `Or take other action
    End If
End Sub

請參閱線上說明主題中有關Command函式的範例,範例中展示了如何從Shell命令列中擷取多個引數項目。


參考資料:

請參閱Gunter Born所著的Inside the Registry for Microsoft Windows 95(Microsoft Press,1997)