2011年2月17日 星期四

Tcl 對 Windows 登錄檔的存取

登錄檔的簡介
在早期的 DOS、Windows 3.0 時代,許多應用程式的設定都是以存成 .ini 的檔案形式儲存,但各自的設定檔都存在自己的 ini 檔案,卻造成了系統不易管理,因此微軟為 Windows 系統打造了一個資料庫 registry,專門用來儲存系統及各應用軟體的設定,自 Windows 95 之後,這些應用軟體的設定已漸漸的移到 Windows 的 Registry (登錄檔)
在 Windows 中,只要在「開始」功能表的「執行」中,輸入「regedit」即可開啟此「登錄編輯程式」。此「登錄編輯程式」視窗左邊是機碼路徑,右邊則是設定值。
  • 紅色箭頭代表「機碼」,可以存放字串值、二進位值、DWORD 值...等。
  • 藍色箭頭代表「字串值」,專門存放可顯示的字串值。
  • 綠色箭頭代表「二進位值」,專門存放 Binary 的二進位資料。
20090313-01



Tcl 的 registry 套件是專用用來存取 Windows 的登錄檔,其提供幾個有用的功能,列表如下:

命令
功能描述
set 新增資料
get 取得資料
type 取得資料的類型 (sz 為字串, binary為二進制)
keys 取得所有的「機碼」
(PS:機碼如同檔案系統的資料夾,可存放資料及其他的機碼)
values 取得所有的資料
delete 刪除資料或機碼



初值設定

分別載入 registry 套件,並將登入檔要存取的路徑「HKEY_LOCAL_MACHINE\SOFTWARE\Test」存到 path 變數,其中「\\」是一定要如此輸入的,在 Tcl 的字串中,第一個「\」代表跳脫字元,第二個才是我們要的「\」字元。

# 載入 registry 套件
package require registry

# 設定存取的路徑
set path HKEY_LOCAL_MACHINE\\SOFTWARE\\Test


set 新增資料
registry 是透過 set 命令來新增機碼及資料,底下分別在 HKEY_LOCAL_MACHINE\SOFTWARE\Test 的機碼中建立「字串值」、「二進位值」及「機碼」。registry 支援的資料類別如下表:
# 新增 字串值 資料
registry set $path str "123ABC"

# 新增 二進位值 資料
registry set $path bin \x01\x02\x03 binary

# 新增 機碼
registry set $path\\CQi_1
registry set $path\\CQi_2
registry set $path\\CQi_3


20090313-02

get 取得資料

接著就是將剛建立的資料,透過 get 命令讀出來。
# 取得 字串 資料
registry get $path str

# 取得 二進位 資料
registry get $path bin

為了可以看到 Binary 的資料,可以使用底下的 hexDump 將存有 binary 資料的變數內容,以十六進制的方式顯示出來。
proc hexDump {data} {
 # pass by reference is used for performance reason
 upvar $data buff

 set i 0
 foreach byte [split $buff {}] {
  if {[expr ($i % 16) == 0]} {
   puts -nonewline \n[format "%06d: " $i]
  }
  puts -nonewline [format "%02X " [scan $byte %c]]
  incr i
 }
 puts ""
 return $i
}

type 取得資料的類型
# 取得 字串 資料
registry type $path str

# 取得 二進位 資料
registry type $path bin
20090313-04

keys 取得所有的「機碼」
# 取得 取得所有的「機碼」
registry keys HKEY_LOCAL_MACHINE\\SOFTWARE
20090313-05

values 取得所有的資料
# 取得 取得所有的資料
registry values $path
20090313-06

delete 刪除資料或機碼
# 刪除 str 資料
registry delete $path str

# 刪除 CQi_1 機碼
registry delete $path\\CQi_1

# 刪除整個 test 機碼
registry delete $path

Registry 測試程式
另外,附上一個存取 Registry 的測試程式
# 警告:本測試程式只適用 Windows 系統
# 程式主要在使用 Tcl 的 registry 套件對 Windows 系統的登入檔做操作測試
# 測試程式會在登入檔的 HKEY_LOCAL_MACHINE\SOFTWARE 建立一個新的機碼 Test 
# 機碼就像是檔案系統的資料夾, 可以存放各種類型的資料), 
# 接著使用 registry 套件提供的指令 set, get, type, keys, values, delete 來操作登入檔

package require registry

proc main {} {
 # 測試 registry 的指令
 testRegistry

 # 取得開啟副檔名的程式
 testGetExtAP
}

proc testRegistry {} {
 # Registry 機碼的路徑
 set path HKEY_LOCAL_MACHINE\\SOFTWARE\\Test

 puts "================\[ registry 指令的測試 \]================"

 ########################################################    
 # registry 的 set 指令測試    
 ########################################################
 # 建立資料, 預設型態為 sz (字串)
 registry set $path str1 "AAA"
 # 建立 sz(字串) 型態
 registry set $path str2 "BBB" sz
 # 建立 binary(二進位) 型態
 registry set $path bin1 "123ABC" binary
 # 建立 binary(二進位) 型態
 registry set $path bin2 \x01\x02\x03 binary

 ########################################################    
 # registry 的 get 指令測試    
 ########################################################
 puts "\n§ registry 的 get 指令測試 §"
 puts str1=[registry get $path str1]
 puts str2=[registry get $path str2]
 puts bin1=[registry get $path bin1]
 puts bin2=[registry get $path bin2]

 ########################################################    
 # registry 的 type 指令測試    
 ########################################################
 puts "\n§ registry 的 type 指令測試 §"
 puts str1=[registry type $path str1]
 puts str2=[registry type $path str2]
 puts bin1=[registry type $path bin1]
 puts bin2=[registry type $path bin2]

 ########################################################    
 # registry 的 keys 指令測試    
 ########################################################
 puts "\n§ registry 的 keys 指令測試 §"
 registry set $path\\keys1 key1 111
 registry set $path\\keys2 key2 222
 puts [registry keys $path]

 ########################################################    
 # registry 的 values 指令測試    
 ########################################################
 puts "\n§ registry 的 values 指令測試 §"
 puts [registry values $path]

 ########################################################    
 # registry 的 delete 指令測試    
 ########################################################
 puts "\n§ registry 的 values 指令測試 §"
 # 刪除單一個值
 registry delete $path\\str1
 registry delete $path\\str2

 # 刪除內含資料的機碼
 registry delete $path\\keys1

 # 刪除整個 test 機碼
 registry delete $path
}

proc testGetExtAP {} {
 puts "\n\n================\[ 取得開啟副檔名的程式 \]================"
 getAPCommand .tcl
 getAPCommand .doc
 getAPCommand .txt
 getAPCommand .html
}

# 取得開啟副檔名的程式
# ex: 輸入 getAPCommand .tcl
#     即回傳 "C:\PROGRA~1\TclPro1.4\win32-ix86\bin\prowish83.exe" "%1"
proc getAPCommand {ext} {
 set type [registry get HKEY_CLASSES_ROOT\\$ext {}]
 set path HKEY_CLASSES_ROOT\\$type\\Shell\\Open\\command
 set command [registry get $path {}]
 puts "\"$ext\" open with \n$command\n"
}

main

測試程式執行結果
20090313-07

參考資料

6 則留言:

  1. Good job.

    有兩個問題:
    1. 不是每台電腦上都有 CQiKit,所以讀者可能不曉得 hexDump 指令是哪來的,也許你得提供個 hexDump 指令。
    2. 第二個是文字編排問題,Registry 測試程式的文字可以縮排一下嗎?這樣會比較好看。

    回覆刪除
  2. 謝謝~~
    在搬舊的文章時沒有注意到....^^

    回覆刪除
  3. 有料哦~~~

    Registry 套件功能裡有幾個 typos, 錯打成大寫了吧!

    Set, Keys 與 Values 應該都是要小寫字母的 set, keys 與 values。

    回覆刪除
  4. 對呀~~我怎麼都沒有發現...@_@" (一直狂冒冷汗)
    謝~~謝~~

    回覆刪除
  5. 作者已經移除這則留言。

    回覆刪除
  6. 你之前不是寫了一支「數位相框」的 photoShow 程式?
    程式是怎麼寫的? 寫篇教材分享一下吧! :)

    回覆刪除